"advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cargotest 0.1.0",
- "chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crates-io 0.9.0",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-[[package]]
-name = "chrono"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
- "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "clap"
version = "2.19.3"
"libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
-[[package]]
-name = "redox_syscall"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
[[package]]
name = "regex"
version = "0.1.80"
name = "tidy"
version = "0.1.0"
-[[package]]
-name = "time"
-version = "0.1.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
[[package]]
name = "toml"
version = "0.1.30"
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum cargo 0.20.0 (git+https://github.com/rust-lang/cargo)" = "<none>"
"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
-"checksum chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d9123be86fd2a8f627836c235ecdf331fdd067ecf7ac05aa1a68fbcf2429f056"
"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374"
"checksum cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "92278eb79412c8f75cfc89e707a1bb3a6490b68f7f2e78d15c774f30fe701122"
"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum racer 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d72b3afd67882adfca61d609fafb8d7aa5f9e814f12c32fcc6e171995920e8"
"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
-"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
"checksum thread-id 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df7875b676fddfadffd96deea3b1124e5ede707d4884248931077518cf1f773"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
-"checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3"
"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
"checksum toml 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd86ad9ebee246fdedd610e0f6d0587b754a3d81438db930a244d0480ed7878f"
shutil.move(tp, fp)
shutil.rmtree(os.path.join(dst, fname))
-def run(args, verbose=False, exception=False, cwd=None):
+def run(args, verbose=False, exception=False, cwd=None, env=None):
if verbose:
print("running: " + ' '.join(args))
sys.stdout.flush()
# Use Popen here instead of call() as it apparently allows powershell on
# Windows to not lock up waiting for input presumably.
- ret = subprocess.Popen(args, cwd=cwd)
+ ret = subprocess.Popen(args, cwd=cwd, env=env)
code = ret.wait()
if code != 0:
err = "failed to run: " + ' '.join(args)
raise Exception("no cargo executable found at `%s`" % self.cargo())
args = [self.cargo(), "build", "--manifest-path",
os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")]
+ if self.verbose:
+ args.append("--verbose")
+ if self.verbose > 1:
+ args.append("--verbose")
if self.use_locked_deps:
args.append("--locked")
if self.use_vendored_sources:
args.append("--frozen")
- self.run(args, env)
-
- def run(self, args, env=None, cwd=None):
- proc = subprocess.Popen(args, env=env, cwd=cwd)
- ret = proc.wait()
- if ret != 0:
- sys.exit(ret)
+ run(args, env=env, verbose=self.verbose)
def output(self, args, env=None, cwd=None):
default_encoding = sys.getdefaultencoding()
path = line[1:].split(' ')[1]
submodules.append([path, line[0]])
- self.run(["git", "submodule", "sync"], cwd=self.rust_root)
+ run(["git", "submodule", "sync"], cwd=self.rust_root)
for submod in submodules:
path, status = submod
submod_path = os.path.join(self.rust_root, path)
if status == ' ':
- self.run(["git", "reset", "--hard"], cwd=submod_path)
- self.run(["git", "clean", "-fdx"], cwd=submod_path)
+ run(["git", "reset", "--hard"], cwd=submod_path)
+ run(["git", "clean", "-fdx"], cwd=submod_path)
elif status == '+':
- self.run(["git", "submodule", "update", path], cwd=self.rust_root)
- self.run(["git", "reset", "--hard"], cwd=submod_path)
- self.run(["git", "clean", "-fdx"], cwd=submod_path)
+ run(["git", "submodule", "update", path], cwd=self.rust_root)
+ run(["git", "reset", "--hard"], cwd=submod_path)
+ run(["git", "clean", "-fdx"], cwd=submod_path)
elif status == '-':
- self.run(["git", "submodule", "init", path], cwd=self.rust_root)
- self.run(["git", "submodule", "update", path], cwd=self.rust_root)
+ run(["git", "submodule", "init", path], cwd=self.rust_root)
+ run(["git", "submodule", "update", path], cwd=self.rust_root)
else:
raise ValueError('unknown submodule status: ' + status)
except:
pass
+ if '\nverbose = 2' in rb.config_toml:
+ rb.verbose = 2
+ elif '\nverbose = 1' in rb.config_toml:
+ rb.verbose = 1
+
rb.use_vendored_sources = '\nvendor = true' in rb.config_toml or \
'CFG_ENABLE_VENDOR' in rb.config_mk
env["BUILD"] = rb.build
env["SRC"] = rb.rust_root
env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
- rb.run(args, env)
+ run(args, env=env, verbose=rb.verbose)
def main():
start_time = time()
}
}
+fn find_files(files: &[&str], path: &[PathBuf]) -> Vec<PathBuf> {
+ let mut found = Vec::new();
+
+ for file in files {
+ let file_path =
+ path.iter()
+ .map(|dir| dir.join(file))
+ .find(|p| p.exists());
+
+ if let Some(file_path) = file_path {
+ found.push(file_path);
+ } else {
+ panic!("Could not find '{}' in {:?}", file, path);
+ }
+ }
+
+ found
+}
+
+fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: &Build) {
+ //Ask gcc where it keeps its stuff
+ let mut cmd = Command::new(build.cc(target_triple));
+ cmd.arg("-print-search-dirs");
+ build.run_quiet(&mut cmd);
+ let gcc_out =
+ String::from_utf8(
+ cmd
+ .output()
+ .expect("failed to execute gcc")
+ .stdout).expect("gcc.exe output was not utf8");
+
+ let mut bin_path: Vec<_> =
+ env::split_paths(&env::var_os("PATH").unwrap_or_default())
+ .collect();
+ let mut lib_path = Vec::new();
+
+ for line in gcc_out.lines() {
+ let idx = line.find(':').unwrap();
+ let key = &line[..idx];
+ let trim_chars: &[_] = &[' ', '='];
+ let value =
+ line[(idx + 1)..]
+ .trim_left_matches(trim_chars)
+ .split(';')
+ .map(|s| PathBuf::from(s));
+
+ if key == "programs" {
+ bin_path.extend(value);
+ } else if key == "libraries" {
+ lib_path.extend(value);
+ }
+ }
+
+ let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"];
+ let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"];
+ if target_triple.starts_with("i686-") {
+ rustc_dlls.push("libgcc_s_dw2-1.dll");
+ } else {
+ rustc_dlls.push("libgcc_s_seh-1.dll");
+ }
+
+ let target_libs = vec![ //MinGW libs
+ "libgcc.a",
+ "libgcc_eh.a",
+ "libgcc_s.a",
+ "libm.a",
+ "libmingw32.a",
+ "libmingwex.a",
+ "libstdc++.a",
+ "libiconv.a",
+ "libmoldname.a",
+ "libpthread.a",
+ //Windows import libs
+ "libadvapi32.a",
+ "libbcrypt.a",
+ "libcomctl32.a",
+ "libcomdlg32.a",
+ "libcrypt32.a",
+ "libgdi32.a",
+ "libimagehlp.a",
+ "libiphlpapi.a",
+ "libkernel32.a",
+ "libmsvcrt.a",
+ "libodbc32.a",
+ "libole32.a",
+ "liboleaut32.a",
+ "libopengl32.a",
+ "libpsapi.a",
+ "librpcrt4.a",
+ "libsetupapi.a",
+ "libshell32.a",
+ "libuser32.a",
+ "libuserenv.a",
+ "libuuid.a",
+ "libwinhttp.a",
+ "libwinmm.a",
+ "libwinspool.a",
+ "libws2_32.a",
+ "libwsock32.a",
+ ];
+
+ //Find mingw artifacts we want to bundle
+ let target_tools = find_files(&target_tools, &bin_path);
+ let rustc_dlls = find_files(&rustc_dlls, &bin_path);
+ let target_libs = find_files(&target_libs, &lib_path);
+
+ fn copy_to_folder(src: &Path, dest_folder: &Path) {
+ let file_name = src.file_name().unwrap().to_os_string();
+ let dest = dest_folder.join(file_name);
+ copy(src, &dest);
+ }
+
+ //Copy runtime dlls next to rustc.exe
+ let dist_bin_dir = rust_root.join("bin/");
+ fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed");
+ for src in rustc_dlls {
+ copy_to_folder(&src, &dist_bin_dir);
+ }
+
+ //Copy platform tools to platform-specific bin directory
+ let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin");
+ fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed");
+ for src in target_tools {
+ copy_to_folder(&src, &target_bin_dir);
+ }
+
+ //Copy platform libs to platform-specific lib directory
+ let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib");
+ fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed");
+ for src in target_libs {
+ copy_to_folder(&src, &target_lib_dir);
+ }
+}
+
/// Build the `rust-mingw` installer component.
///
/// This contains all the bits and pieces to run the MinGW Windows targets
let _ = fs::remove_dir_all(&image);
t!(fs::create_dir_all(&image));
- // The first argument to the script is a "temporary directory" which is just
+ // The first argument is a "temporary directory" which is just
// thrown away (this contains the runtime DLLs included in the rustc package
// above) and the second argument is where to place all the MinGW components
// (which is what we want).
- //
- // FIXME: this script should be rewritten into Rust
- let mut cmd = Command::new(build.python());
- cmd.arg(build.src.join("src/etc/make-win-dist.py"))
- .arg(tmpdir(build))
- .arg(&image)
- .arg(host);
- build.run(&mut cmd);
+ make_win_dist(&tmpdir(build), &image, host, &build);
let mut cmd = rust_installer(build);
cmd.arg("generate")
// anything requiring us to distribute a license, but it's likely the
// install will *also* include the rust-mingw package, which also needs
// licenses, so to be safe we just include it here in all MinGW packages.
- //
- // FIXME: this script should be rewritten into Rust
if host.contains("pc-windows-gnu") {
- let mut cmd = Command::new(build.python());
- cmd.arg(build.src.join("src/etc/make-win-dist.py"))
- .arg(&image)
- .arg(tmpdir(build))
- .arg(host);
- build.run(&mut cmd);
+ make_win_dist(&image, &tmpdir(build), host, build);
let dst = image.join("share/doc");
t!(fs::create_dir_all(&dst));
set -ex
source shared.sh
-VERSION=1.0.2j
+VERSION=1.0.2k
+URL=https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/openssl-$VERSION.tar.gz
-curl https://www.openssl.org/source/openssl-$VERSION.tar.gz | tar xzf -
+curl $URL | tar xzf -
cd openssl-$VERSION
hide_output ./config --prefix=/rustroot shared -fPIC
set -ex
source shared.sh
-VERSION=1.0.2j
+VERSION=1.0.2k
+URL=https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/openssl-$VERSION.tar.gz
-curl https://www.openssl.org/source/openssl-$VERSION.tar.gz | tar xzf -
+curl $URL | tar xzf -
cd openssl-$VERSION
hide_output ./config --prefix=/rustroot shared -fPIC
git clone https://github.com/rust-lang/rust.git $cache_src_dir"
fi
retry sh -c "cd $cache_src_dir && git reset --hard && git pull"
+(cd $cache_src_dir && git rm src/llvm)
retry sh -c "cd $cache_src_dir && \
git submodule deinit -f . && git submodule sync && git submodule update --init"
# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
for module in $modules; do
+ if [ "$module" = src/llvm ]; then
+ commit="$(git ls-tree HEAD src/llvm | awk '{print $3}')"
+ git rm src/llvm
+ curl -sSL -O "https://github.com/rust-lang/llvm/archive/$commit.tar.gz"
+ tar -C src/ -xf "$commit.tar.gz"
+ rm "$commit.tar.gz"
+ mv "src/llvm-$commit" src/llvm
+ continue
+ fi
if [ ! -d "$cache_src_dir/$module" ]; then
echo "WARNING: $module not found in pristine repo"
retry sh -c "git submodule deinit -f $module && git submodule update --init $module"
- [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md)
- [abi_ptx](language-features/abi-ptx.md)
- [abi_sysv64](language-features/abi-sysv64.md)
+ - [abi_thiscall](language-features/abi-thiscall.md)
- [abi_unadjusted](language-features/abi-unadjusted.md)
- [abi_vectorcall](language-features/abi-vectorcall.md)
- [abi_x86_interrupt](language-features/abi-x86-interrupt.md)
- [prelude_import](language-features/prelude-import.md)
- [proc_macro](language-features/proc-macro.md)
- [quote](language-features/quote.md)
- - [relaxed_adts](language-features/relaxed-adts.md)
- [repr_align](language-features/repr-align.md)
- [repr_simd](language-features/repr-simd.md)
- [rustc_attrs](language-features/rustc-attrs.md)
--- /dev/null
+# `abi_thiscall`
+
+The tracking issue for this feature is: [#42202]
+
+[#42202]: https://github.com/rust-lang/rust/issues/42202
+
+------------------------
+
+The MSVC ABI on x86 Windows uses the `thiscall` calling convention for C++
+instance methods by default; it is identical to the usual (C) calling
+convention on x86 Windows except that the first parameter of the method,
+the `this` pointer, is passed in the ECX register.
--- /dev/null
+# `decl_macro`
+
+The tracking issue for this feature is: [#39412]
+
+[#39412]: https://github.com/rust-lang/rust/issues/39412
+
+------------------------
+
+
+
+++ /dev/null
-# `relaxed_adts`
-
-The tracking issue for this feature is: [#35626]
-
-[#35626]: https://github.com/rust-lang/rust/issues/35626
-
-------------------------
-
-
-
# `step_trait`
-The tracking issue for this feature is: [#27741]
+The tracking issue for this feature is: [#42168]
-[#27741]: https://github.com/rust-lang/rust/issues/27741
+[#42168]: https://github.com/rust-lang/rust/issues/42168
------------------------
+++ /dev/null
-# Copyright 2013-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 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-# Script parameters:
-# argv[1] = rust component root,
-# argv[2] = gcc component root,
-# argv[3] = target triple
-# The first two correspond to the two installable components defined in the setup script.
-
-import sys
-import os
-import shutil
-import subprocess
-
-
-def find_files(files, path):
- found = []
- for fname in files:
- for dir in path:
- filepath = os.path.normpath(os.path.join(dir, fname))
- if os.path.isfile(filepath):
- found.append(filepath)
- break
- else:
- raise Exception("Could not find '%s' in %s" % (fname, path))
- return found
-
-
-# rust_root - root directory of the host binaries image
-# plat_root - root directory of the target platform tools and libs image
-# (the two get overlayed on top of each other during installation)
-# target_triple - triple of the target image being layed out
-def make_win_dist(rust_root, plat_root, target_triple):
- # Ask gcc where it keeps its stuff
- gcc_out = subprocess.check_output(["gcc.exe", "-print-search-dirs"])
- bin_path = os.environ["PATH"].split(os.pathsep)
- lib_path = []
- for line in gcc_out.splitlines():
- key, val = line.split(':', 1)
- if key == "programs":
- bin_path.extend(val.lstrip(' =').split(';'))
- elif key == "libraries":
- lib_path.extend(val.lstrip(' =').split(';'))
-
- target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe",
- "libwinpthread-1.dll"]
-
- rustc_dlls = ["libstdc++-6.dll", "libwinpthread-1.dll"]
- if target_triple.startswith("i686-"):
- rustc_dlls.append("libgcc_s_dw2-1.dll")
- else:
- rustc_dlls.append("libgcc_s_seh-1.dll")
-
- target_libs = [ # MinGW libs
- "libgcc.a",
- "libgcc_eh.a",
- "libgcc_s.a",
- "libm.a",
- "libmingw32.a",
- "libmingwex.a",
- "libstdc++.a",
- "libiconv.a",
- "libmoldname.a",
- "libpthread.a",
- # Windows import libs
- "libadvapi32.a",
- "libbcrypt.a",
- "libcomctl32.a",
- "libcomdlg32.a",
- "libcrypt32.a",
- "libgdi32.a",
- "libimagehlp.a",
- "libiphlpapi.a",
- "libkernel32.a",
- "libmsvcrt.a",
- "libodbc32.a",
- "libole32.a",
- "liboleaut32.a",
- "libopengl32.a",
- "libpsapi.a",
- "librpcrt4.a",
- "libsetupapi.a",
- "libshell32.a",
- "libuser32.a",
- "libuserenv.a",
- "libuuid.a",
- "libwinhttp.a",
- "libwinmm.a",
- "libwinspool.a",
- "libws2_32.a",
- "libwsock32.a",
- ]
-
- # Find mingw artifacts we want to bundle
- target_tools = find_files(target_tools, bin_path)
- rustc_dlls = find_files(rustc_dlls, bin_path)
- target_libs = find_files(target_libs, lib_path)
-
- # Copy runtime dlls next to rustc.exe
- dist_bin_dir = os.path.join(rust_root, "bin")
- for src in rustc_dlls:
- shutil.copy(src, dist_bin_dir)
-
- # Copy platform tools to platform-specific bin directory
- target_bin_dir = os.path.join(plat_root, "lib", "rustlib", target_triple, "bin")
- if not os.path.exists(target_bin_dir):
- os.makedirs(target_bin_dir)
- for src in target_tools:
- shutil.copy(src, target_bin_dir)
-
- # Copy platform libs to platform-specific lib directory
- target_lib_dir = os.path.join(plat_root, "lib", "rustlib", target_triple, "lib")
- if not os.path.exists(target_lib_dir):
- os.makedirs(target_lib_dir)
- for src in target_libs:
- shutil.copy(src, target_lib_dir)
-
-if __name__ == "__main__":
- make_win_dist(sys.argv[1], sys.argv[2], sys.argv[3])
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<T> RangeArgument<T> for RangeInclusive<T> {
fn start(&self) -> Bound<&T> {
- match *self {
- RangeInclusive::Empty{ ref at } => Included(at),
- RangeInclusive::NonEmpty { ref start, .. } => Included(start),
- }
+ Included(&self.start)
}
fn end(&self) -> Bound<&T> {
- match *self {
- RangeInclusive::Empty{ ref at } => Excluded(at),
- RangeInclusive::NonEmpty { ref end, .. } => Included(end),
- }
+ Included(&self.end)
}
}
///
/// ```
/// let x = "(///)".to_string();
- /// let d: Vec<_> = x.split('/').collect();;
+ /// let d: Vec<_> = x.split('/').collect();
///
/// assert_eq!(d, &["(", "", "", ")"]);
/// ```
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
- issue = "27741")]
+ issue = "42168")]
pub use self::range::Step;
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
/// two `Step` objects.
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
- issue = "27741")]
+ issue = "42168")]
pub trait Step: PartialOrd + Sized {
/// Steps `self` if possible.
fn step(&self, by: &Self) -> Option<Self>;
($($t:ty)*) => ($(
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
- issue = "27741")]
+ issue = "42168")]
impl Step for $t {
#[inline]
fn step(&self, by: &$t) -> Option<$t> {
($($t:ty)*) => ($(
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
- issue = "27741")]
+ issue = "42168")]
impl Step for $t {
#[inline]
fn step(&self, by: &$t) -> Option<$t> {
($($t:ty)*) => ($(
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
- issue = "27741")]
+ issue = "42168")]
impl Step for $t {
#[inline]
fn step(&self, by: &$t) -> Option<$t> {
#[inline]
fn next(&mut self) -> Option<A> {
- use ops::RangeInclusive::*;
-
- // this function has a sort of odd structure due to borrowck issues
- // we may need to replace self.range, so borrows of start and end need to end early
-
- let (finishing, n) = match self.range {
- Empty { .. } => return None, // empty iterators yield no values
-
- NonEmpty { ref mut start, ref mut end } => {
- let rev = self.step_by.is_negative();
-
- // march start towards (maybe past!) end and yield the old value
- if (rev && start >= end) ||
- (!rev && start <= end)
- {
- match start.step(&self.step_by) {
- Some(mut n) => {
- mem::swap(start, &mut n);
- (None, Some(n)) // yield old value, remain non-empty
- },
- None => {
- let mut n = end.clone();
- mem::swap(start, &mut n);
- (None, Some(n)) // yield old value, remain non-empty
- }
- }
- } else {
- // found range in inconsistent state (start at or past end), so become empty
- (Some(end.replace_zero()), None)
- }
- }
- };
+ let rev = self.step_by.is_negative();
- // turn into an empty iterator if we've reached the end
- if let Some(end) = finishing {
- self.range = Empty { at: end };
+ if (rev && self.range.start >= self.range.end) ||
+ (!rev && self.range.start <= self.range.end)
+ {
+ match self.range.start.step(&self.step_by) {
+ Some(n) => {
+ Some(mem::replace(&mut self.range.start, n))
+ },
+ None => {
+ let last = self.range.start.replace_one();
+ self.range.end.replace_zero();
+ self.step_by.replace_one();
+ Some(last)
+ },
+ }
+ }
+ else {
+ None
}
-
- n
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- use ops::RangeInclusive::*;
-
- match self.range {
- Empty { .. } => (0, Some(0)),
-
- NonEmpty { ref start, ref end } =>
- match Step::steps_between(start,
- end,
- &self.step_by) {
- Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
- None => (0, None)
- }
+ match Step::steps_between(&self.range.start,
+ &self.range.end,
+ &self.step_by) {
+ Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
+ None => (0, None)
}
}
}
#[inline]
fn next(&mut self) -> Option<A> {
- use ops::RangeInclusive::*;
-
- // this function has a sort of odd structure due to borrowck issues
- // we may need to replace self, so borrows of self.start and self.end need to end early
-
- let (finishing, n) = match *self {
- Empty { .. } => (None, None), // empty iterators yield no values
-
- NonEmpty { ref mut start, ref mut end } => {
- if start == end {
- (Some(end.replace_one()), Some(start.replace_one()))
- } else if start < end {
- let mut n = start.add_one();
- mem::swap(&mut n, start);
-
- // if the iterator is done iterating, it will change from
- // NonEmpty to Empty to avoid unnecessary drops or clones,
- // we'll reuse either start or end (they are equal now, so
- // it doesn't matter which) to pull out end, we need to swap
- // something back in
-
- (if n == *end { Some(end.replace_one()) } else { None },
- // ^ are we done yet?
- Some(n)) // < the value to output
- } else {
- (Some(start.replace_one()), None)
- }
- }
- };
-
- // turn into an empty iterator if this is the last value
- if let Some(end) = finishing {
- *self = Empty { at: end };
+ use cmp::Ordering::*;
+
+ match self.start.partial_cmp(&self.end) {
+ Some(Less) => {
+ let n = self.start.add_one();
+ Some(mem::replace(&mut self.start, n))
+ },
+ Some(Equal) => {
+ let last = self.start.replace_one();
+ self.end.replace_zero();
+ Some(last)
+ },
+ _ => None,
}
-
- n
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- use ops::RangeInclusive::*;
-
- match *self {
- Empty { .. } => (0, Some(0)),
+ if !(self.start <= self.end) {
+ return (0, Some(0));
+ }
- NonEmpty { ref start, ref end } =>
- match Step::steps_between_by_one(start, end) {
- Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
- None => (0, None),
- }
+ match Step::steps_between_by_one(&self.start, &self.end) {
+ Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
+ None => (0, None),
}
}
}
{
#[inline]
fn next_back(&mut self) -> Option<A> {
- use ops::RangeInclusive::*;
-
- // see Iterator::next for comments
-
- let (finishing, n) = match *self {
- Empty { .. } => return None,
-
- NonEmpty { ref mut start, ref mut end } => {
- if start == end {
- (Some(start.replace_one()), Some(end.replace_one()))
- } else if start < end {
- let mut n = end.sub_one();
- mem::swap(&mut n, end);
-
- (if n == *start { Some(start.replace_one()) } else { None },
- Some(n))
- } else {
- (Some(end.replace_one()), None)
- }
- }
- };
-
- if let Some(start) = finishing {
- *self = Empty { at: start };
+ use cmp::Ordering::*;
+
+ match self.start.partial_cmp(&self.end) {
+ Some(Less) => {
+ let n = self.end.sub_one();
+ Some(mem::replace(&mut self.end, n))
+ },
+ Some(Equal) => {
+ let last = self.end.replace_zero();
+ self.start.replace_one();
+ Some(last)
+ },
+ _ => None,
}
-
- n
}
}
/// [coerceunsized]: ../ops/trait.CoerceUnsized.html
/// [rc]: ../../std/rc/struct.Rc.html
/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
-
+/// [nomicon-coerce]: ../../nomicon/coercions.html
#[unstable(feature = "unsize", issue = "27732")]
#[lang="unsize"]
pub trait Unsize<T: ?Sized> {
/// The `Drop` trait is used to run some code when a value goes out of scope.
/// This is sometimes called a 'destructor'.
///
+/// When a value goes out of scope, if it implements this trait, it will have
+/// its `drop` method called. Then any fields the value contains will also
+/// be dropped recursively.
+///
+/// Because of the recursive dropping, you do not need to implement this trait
+/// unless your type needs its own destructor logic.
+///
/// # Examples
///
/// A trivial implementation of `Drop`. The `drop` method is called when `_x`
/// let _x = HasDrop;
/// }
/// ```
+///
+/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the
+/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore
+/// `main` prints `Dropping Outer!` and then `Dropping Inner!`.
+///
+/// ```
+/// struct Inner;
+/// struct Outer(Inner);
+///
+/// impl Drop for Inner {
+/// fn drop(&mut self) {
+/// println!("Dropping Inner!");
+/// }
+/// }
+///
+/// impl Drop for Outer {
+/// fn drop(&mut self) {
+/// println!("Dropping Outer!");
+/// }
+/// }
+///
+/// fn main() {
+/// let _x = Outer(Inner);
+/// }
+/// ```
+///
+/// Because variables are dropped in the reverse order they are declared,
+/// `main` will print `Declared second!` and then `Declared first!`.
+///
+/// ```
+/// struct PrintOnDrop(&'static str);
+///
+/// fn main() {
+/// let _first = PrintOnDrop("Declared first!");
+/// let _second = PrintOnDrop("Declared second!");
+/// }
+/// ```
#[lang = "drop"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Drop {
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax)]
/// fn main() {
-/// assert_eq!((3...5), std::ops::RangeInclusive::NonEmpty{ start: 3, end: 5 });
+/// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 });
/// assert_eq!(3+4+5, (3...5).sum());
///
/// let arr = [0, 1, 2, 3];
/// ```
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-pub enum RangeInclusive<Idx> {
- /// Empty range (iteration has finished)
+pub struct RangeInclusive<Idx> {
+ /// The lower bound of the range (inclusive).
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
- Empty {
- /// The point at which iteration finished
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
- issue = "28237")]
- at: Idx
- },
- /// Non-empty range (iteration will yield value(s))
+ pub start: Idx,
+ /// The upper bound of the range (inclusive).
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
- NonEmpty {
- /// The lower bound of the range (inclusive).
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
- issue = "28237")]
- start: Idx,
- /// The upper bound of the range (inclusive).
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
- issue = "28237")]
- end: Idx,
- },
+ pub end: Idx,
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- use self::RangeInclusive::*;
-
- match *self {
- Empty { ref at } => write!(fmt, "[empty range @ {:?}]", at),
- NonEmpty { ref start, ref end } => write!(fmt, "{:?}...{:?}", start, end),
- }
+ write!(fmt, "{:?}...{:?}", self.start, self.end)
}
}
/// }
/// ```
pub fn contains(&self, item: Idx) -> bool {
- if let &RangeInclusive::NonEmpty{ref start, ref end} = self {
- (*start <= item) && (item <= *end)
- } else { false }
+ self.start <= item && item <= self.end
}
}
#[inline]
fn get(self, slice: &[T]) -> Option<&[T]> {
- match self {
- ops::RangeInclusive::Empty { .. } => Some(&[]),
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get(slice),
- }
+ if self.end == usize::max_value() { None }
+ else { (self.start..self.end + 1).get(slice) }
}
#[inline]
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
- match self {
- ops::RangeInclusive::Empty { .. } => Some(&mut []),
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_mut(slice),
- }
+ if self.end == usize::max_value() { None }
+ else { (self.start..self.end + 1).get_mut(slice) }
}
#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &[],
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_unchecked(slice),
- }
+ (self.start..self.end + 1).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &mut [],
- ops::RangeInclusive::NonEmpty { start, end } => {
- (start..end + 1).get_unchecked_mut(slice)
- }
- }
+ (self.start..self.end + 1).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &[T]) -> &[T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &[],
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
- panic!("attempted to index slice up to maximum usize");
- },
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index(slice),
- }
+ assert!(self.end != usize::max_value(),
+ "attempted to index slice up to maximum usize");
+ (self.start..self.end + 1).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &mut [],
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
- panic!("attempted to index slice up to maximum usize");
- },
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index_mut(slice),
- }
+ assert!(self.end != usize::max_value(),
+ "attempted to index slice up to maximum usize");
+ (self.start..self.end + 1).index_mut(slice)
}
}
+#[cfg(stage0)] // The bootstrap compiler has a different `...` desugar
+fn inclusive(start: usize, end: usize) -> ops::RangeInclusive<usize> {
+ ops::RangeInclusive { start, end }
+}
+#[cfg(not(stage0))]
+fn inclusive(start: usize, end: usize) -> ops::RangeInclusive<usize> {
+ start...end
+}
+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
type Output = [T];
#[inline]
fn get(self, slice: &[T]) -> Option<&[T]> {
- (0...self.end).get(slice)
+ inclusive(0, self.end).get(slice)
}
#[inline]
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
- (0...self.end).get_mut(slice)
+ inclusive(0, self.end).get_mut(slice)
}
#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
- (0...self.end).get_unchecked(slice)
+ inclusive(0, self.end).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
- (0...self.end).get_unchecked_mut(slice)
+ inclusive(0, self.end).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &[T]) -> &[T] {
- (0...self.end).index(slice)
+ inclusive(0, self.end).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
- (0...self.end).index_mut(slice)
+ inclusive(0, self.end).index_mut(slice)
}
}
#[inline]
fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
- match index {
- ops::RangeInclusive::Empty { .. } => "",
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() =>
- panic!("attempted to index slice up to maximum usize"),
- ops::RangeInclusive::NonEmpty { start, end } =>
- self.index(start .. end+1)
- }
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index(index.start .. index.end+1)
}
}
+
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
#[inline]
fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
- self.index(0...index.end)
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index(.. index.end+1)
}
}
impl ops::IndexMut<ops::RangeInclusive<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
- match index {
- ops::RangeInclusive::Empty { .. } => &mut self[0..0], // `&mut ""` doesn't work
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() =>
- panic!("attempted to index str up to maximum usize"),
- ops::RangeInclusive::NonEmpty { start, end } =>
- self.index_mut(start .. end+1)
- }
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index_mut(index.start .. index.end+1)
}
}
#[unstable(feature = "inclusive_range",
impl ops::IndexMut<ops::RangeToInclusive<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
- self.index_mut(0...index.end)
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index_mut(.. index.end+1)
}
}
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get(slice)
+ (self.start..self.end+1).get(slice)
}
#[inline]
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get_mut(slice)
+ (self.start..self.end+1).get_mut(slice)
}
#[inline]
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get_unchecked(slice)
+ (self.start..self.end+1).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get_unchecked_mut(slice)
+ (self.start..self.end+1).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.index(slice)
+ (self.start..self.end+1).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.index_mut(slice)
+ (self.start..self.end+1).index_mut(slice)
}
}
#![feature(fmt_internals)]
#![feature(iterator_step_by)]
#![feature(i128_type)]
+#![feature(inclusive_range)]
#![feature(iter_rfind)]
#![feature(libc)]
#![feature(nonzero)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
+use core::ops::{Range, RangeFull, RangeFrom, RangeTo, RangeInclusive};
// Test the Range structs without the syntactic sugar.
// Not much to test.
let _ = RangeFull;
}
+
+#[test]
+fn test_range_inclusive() {
+ let mut r = RangeInclusive { start: 1i8, end: 2 };
+ assert_eq!(r.next(), Some(1));
+ assert_eq!(r.next(), Some(2));
+ assert_eq!(r.next(), None);
+
+ r = RangeInclusive { start: 127i8, end: 127 };
+ assert_eq!(r.next(), Some(127));
+ assert_eq!(r.next(), None);
+
+ r = RangeInclusive { start: -128i8, end: -128 };
+ assert_eq!(r.next_back(), Some(-128));
+ assert_eq!(r.next_back(), None);
+
+ // degenerate
+ r = RangeInclusive { start: 1, end: -1 };
+ assert_eq!(r.size_hint(), (0, Some(0)));
+ assert_eq!(r.next(), None);
+}
\ No newline at end of file
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
- pub name: ast::Name, // The name of the target.
+ pub ident: ast::Ident, // The name of the target.
pub def: Def, // The definition of the target.
pub span: Span, // The span of the target definition.
}
use hir::def::{Def, PathResolution};
use rustc_data_structures::indexed_vec::IndexVec;
use session::Session;
-use util::nodemap::{DefIdMap, NodeMap};
+use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
use std::collections::BTreeMap;
use std::fmt::Debug;
// a definition, then we can properly create the def id.
parent_def: Option<DefIndex>,
resolver: &'a mut Resolver,
+ name_map: FxHashMap<Ident, Name>,
/// The items being lowered are collected here.
items: BTreeMap<NodeId, hir::Item>,
sess: sess,
parent_def: None,
resolver: resolver,
+ name_map: FxHashMap(),
items: BTreeMap::new(),
trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(),
}
fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span {
- let mark = Mark::fresh();
+ let mark = Mark::fresh(Mark::root());
mark.set_expn_info(codemap::ExpnInfo {
call_site: span,
callee: codemap::NameAndSpan {
}
}
+ fn lower_ident(&mut self, ident: Ident) -> Name {
+ let ident = ident.modern();
+ if ident.ctxt == SyntaxContext::empty() {
+ return ident.name;
+ }
+ *self.name_map.entry(ident).or_insert_with(|| Symbol::from_ident(ident))
+ }
+
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
}
fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
hir::TypeBinding {
id: self.lower_node_id(b.id),
- name: b.ident.name,
+ name: self.lower_ident(b.ident),
ty: self.lower_ty(&b.ty),
span: b.span,
}
}
hir::PathSegment {
- name: segment.identifier.name,
+ name: self.lower_ident(segment.identifier),
parameters: parameters,
}
}
}
fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam {
- let mut name = tp.ident.name;
+ let mut name = self.lower_ident(tp.ident);
// Don't expose `Self` (recovered "keyword used as ident" parse error).
// `rustc::ty` expects `Self` to be only used for a trait's `Self`.
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
hir::Lifetime {
id: self.lower_node_id(l.id),
- name: l.name,
+ name: self.lower_ident(l.ident),
span: l.span,
}
}
hir::StructField {
span: f.span,
id: self.lower_node_id(f.id),
- name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
+ 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 },
+ }),
vis: self.lower_visibility(&f.vis, None),
ty: self.lower_ty(&f.ty),
attrs: self.lower_attrs(&f.attrs),
fn lower_field(&mut self, f: &Field) -> hir::Field {
hir::Field {
- name: respan(f.ident.span, f.ident.node.name),
+ name: respan(f.ident.span, self.lower_ident(f.ident.node)),
expr: P(self.lower_expr(&f.expr)),
span: f.span,
is_shorthand: f.is_shorthand,
self.with_parent_def(i.id, |this| {
hir::TraitItem {
id: this.lower_node_id(i.id),
- name: i.ident.name,
+ name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
node: match i.node {
TraitItemKind::Const(ref ty, ref default) => {
};
hir::TraitItemRef {
id: hir::TraitItemId { node_id: i.id },
- name: i.ident.name,
+ name: self.lower_ident(i.ident),
span: i.span,
defaultness: self.lower_defaultness(Defaultness::Default, has_default),
kind: kind,
self.with_parent_def(i.id, |this| {
hir::ImplItem {
id: this.lower_node_id(i.id),
- name: i.ident.name,
+ name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
vis: this.lower_visibility(&i.vis, None),
defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
hir::ImplItemRef {
id: hir::ImplItemId { node_id: i.id },
- name: i.ident.name,
+ name: self.lower_ident(i.ident),
span: i.span,
vis: self.lower_visibility(&i.vis, Some(i.id)),
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
let mut name = i.ident.name;
+ let mut vis = self.lower_visibility(&i.vis, None);
let attrs = self.lower_attrs(&i.attrs);
- if let ItemKind::MacroDef(ref tts) = i.node {
- if i.attrs.iter().any(|attr| attr.path == "macro_export") {
+ if let ItemKind::MacroDef(ref def) = i.node {
+ if !def.legacy || i.attrs.iter().any(|attr| attr.path == "macro_export") {
self.exported_macros.push(hir::MacroDef {
- name: name, attrs: attrs, id: i.id, span: i.span, body: tts.clone().into(),
+ name: name,
+ vis: vis,
+ attrs: attrs,
+ id: i.id,
+ span: i.span,
+ body: def.stream(),
+ legacy: def.legacy,
});
}
return None;
}
- let mut vis = self.lower_visibility(&i.vis, None);
let node = self.with_parent_def(i.id, |this| {
this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
});
Spanned {
span: f.span,
node: hir::FieldPat {
- name: f.node.ident.name,
+ name: self.lower_ident(f.node.ident),
pat: self.lower_pat(&f.node.pat),
is_shorthand: f.node.is_shorthand,
},
ExprKind::MethodCall(i, ref tps, ref args) => {
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
let args = args.iter().map(|x| self.lower_expr(x)).collect();
- hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
+ hir::ExprMethodCall(respan(i.span, self.lower_ident(i.node)), tps, args)
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop);
P(self.lower_expr(er)))
}
ExprKind::Field(ref el, ident) => {
- hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name))
+ hir::ExprField(P(self.lower_expr(el)),
+ respan(ident.span, self.lower_ident(ident.node)))
}
ExprKind::TupField(ref el, ident) => {
hir::ExprTupField(P(self.lower_expr(el)), ident)
ExprKind::Range(ref e1, ref e2, lims) => {
use syntax::ast::RangeLimits::*;
- let (path, variant) = match (e1, e2, lims) {
- (&None, &None, HalfOpen) => ("RangeFull", None),
- (&Some(..), &None, HalfOpen) => ("RangeFrom", None),
- (&None, &Some(..), HalfOpen) => ("RangeTo", None),
- (&Some(..), &Some(..), HalfOpen) => ("Range", None),
- (&None, &Some(..), Closed) => ("RangeToInclusive", None),
- (&Some(..), &Some(..), Closed) => ("RangeInclusive", Some("NonEmpty")),
+ let path = match (e1, e2, lims) {
+ (&None, &None, HalfOpen) => "RangeFull",
+ (&Some(..), &None, HalfOpen) => "RangeFrom",
+ (&None, &Some(..), HalfOpen) => "RangeTo",
+ (&Some(..), &Some(..), HalfOpen) => "Range",
+ (&None, &Some(..), Closed) => "RangeToInclusive",
+ (&Some(..), &Some(..), Closed) => "RangeInclusive",
(_, &None, Closed) =>
panic!(self.diagnostic().span_fatal(
e.span, "inclusive range with no end")),
let is_unit = fields.is_empty();
let unstable_span = self.allow_internal_unstable("...", e.span);
let struct_path =
- iter::once("ops").chain(iter::once(path)).chain(variant)
+ iter::once("ops").chain(iter::once(path))
.collect::<Vec<_>>();
let struct_path = self.std_path(unstable_span, &struct_path, is_unit);
let struct_path = hir::QPath::Resolved(None, P(struct_path));
let parent_def = self.parent_def.unwrap();
let def_id = {
let defs = self.resolver.definitions();
- let def_path_data = DefPathData::Binding(name.as_str());
- let def_index = defs.create_def_with_parent(parent_def,
- id,
- def_path_data,
- REGULAR_SPACE);
+ let def_path_data = DefPathData::Binding(Ident::with_empty_ctxt(name));
+ let def_index = defs
+ .create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root());
DefId::local(def_index)
};
use syntax::ast::*;
use syntax::ext::hygiene::Mark;
use syntax::visit;
-use syntax::symbol::{Symbol, keywords};
+use syntax::symbol::keywords;
use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
pub struct DefCollector<'a> {
definitions: &'a mut Definitions,
parent_def: Option<DefIndex>,
+ expansion: Mark,
pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
}
}
impl<'a> DefCollector<'a> {
- pub fn new(definitions: &'a mut Definitions) -> Self {
+ pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self {
DefCollector {
definitions: definitions,
+ expansion: expansion,
parent_def: None,
visit_macro_invoc: None,
}
-> DefIndex {
let parent_def = self.parent_def.unwrap();
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
- self.definitions.create_def_with_parent(parent_def, node_id, data, address_space)
+ self.definitions
+ .create_def_with_parent(parent_def, node_id, data, address_space, self.expansion)
}
pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
DefPathData::Impl,
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
- DefPathData::TypeNs(i.ident.name.as_str()),
+ DefPathData::TypeNs(i.ident.modern()),
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
return visit::walk_item(self, i);
}
- ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
+ ItemKind::Mod(..) => DefPathData::Module(i.ident.modern()),
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
- DefPathData::ValueNs(i.ident.name.as_str()),
- ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
+ DefPathData::ValueNs(i.ident.modern()),
+ ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.modern()),
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
ItemKind::GlobalAsm(..) => DefPathData::Misc,
ItemKind::Use(ref view_path) => {
for v in &enum_definition.variants {
let variant_def_index =
this.create_def(v.node.data.id(),
- DefPathData::EnumVariant(v.node.name.name.as_str()),
+ DefPathData::EnumVariant(v.node.name.modern()),
REGULAR_SPACE);
this.with_parent(variant_def_index, |this| {
for (index, field) in v.node.data.fields().iter().enumerate() {
- let name = field.ident.map(|ident| ident.name)
- .unwrap_or_else(|| Symbol::intern(&index.to_string()));
- this.create_def(field.id,
- DefPathData::Field(name.as_str()),
- REGULAR_SPACE);
+ let ident = field.ident.map(Ident::modern)
+ .unwrap_or_else(|| Ident::from_str(&index.to_string()));
+ this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
}
if let Some(ref expr) = v.node.disr_expr {
}
for (index, field) in struct_def.fields().iter().enumerate() {
- let name = field.ident.map(|ident| ident.name.as_str())
- .unwrap_or(Symbol::intern(&index.to_string()).as_str());
- this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
+ let ident = field.ident.map(Ident::modern)
+ .unwrap_or_else(|| Ident::from_str(&index.to_string()));
+ this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
}
}
_ => {}
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
let def = self.create_def(foreign_item.id,
- DefPathData::ValueNs(foreign_item.ident.name.as_str()),
+ DefPathData::ValueNs(foreign_item.ident.modern()),
REGULAR_SPACE);
self.with_parent(def, |this| {
fn visit_generics(&mut self, generics: &'a Generics) {
for ty_param in generics.ty_params.iter() {
self.create_def(ty_param.id,
- DefPathData::TypeParam(ty_param.ident.name.as_str()),
+ DefPathData::TypeParam(ty_param.ident.modern()),
REGULAR_SPACE);
}
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
let def_data = match ti.node {
TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
- DefPathData::ValueNs(ti.ident.name.as_str()),
- TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
+ DefPathData::ValueNs(ti.ident.modern()),
+ TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.modern()),
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
};
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
let def_data = match ii.node {
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
- DefPathData::ValueNs(ii.ident.name.as_str()),
- ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
+ DefPathData::ValueNs(ii.ident.modern()),
+ ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.modern()),
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
};
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
PatKind::Ident(_, id, _) => {
let def = self.create_def(pat.id,
- DefPathData::Binding(id.node.name.as_str()),
+ DefPathData::Binding(id.node.modern()),
REGULAR_SPACE);
self.parent_def = Some(def);
}
fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
self.create_def(def.lifetime.id,
- DefPathData::LifetimeDef(def.lifetime.name.as_str()),
+ DefPathData::LifetimeDef(def.lifetime.ident.modern()),
REGULAR_SPACE);
}
use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::fmt::Write;
use std::hash::Hash;
-use syntax::ast;
+use syntax::ast::{self, Ident};
+use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::symbol::{Symbol, InternedString};
use ty::TyCtxt;
use util::nodemap::NodeMap;
node_to_def_index: NodeMap<DefIndex>,
def_index_to_node: [Vec<ast::NodeId>; 2],
pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
+ macro_def_scopes: FxHashMap<Mark, DefId>,
+ expansions: FxHashMap<DefIndex, Mark>,
}
// Unfortunately we have to provide a manual impl of Clone because of the
self.def_index_to_node[1].clone(),
],
node_to_hir_id: self.node_to_hir_id.clone(),
+ macro_def_scopes: self.macro_def_scopes.clone(),
+ expansions: self.expansions.clone(),
}
}
}
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum DefPathData {
// Root: these should only be used for the root nodes, because
// they are treated specially by the `def_path` function.
/// An impl
Impl,
/// Something in the type NS
- TypeNs(InternedString),
+ TypeNs(Ident),
/// Something in the value NS
- ValueNs(InternedString),
+ ValueNs(Ident),
/// A module declaration
- Module(InternedString),
+ Module(Ident),
/// A macro rule
- MacroDef(InternedString),
+ MacroDef(Ident),
/// A closure expression
ClosureExpr,
// Subportions of items
/// A type parameter (generic parameter)
- TypeParam(InternedString),
+ TypeParam(Ident),
/// A lifetime definition
- LifetimeDef(InternedString),
+ LifetimeDef(Ident),
/// A variant of a enum
- EnumVariant(InternedString),
+ EnumVariant(Ident),
/// A struct field
- Field(InternedString),
+ Field(Ident),
/// Implicit ctor for a tuple-like struct
StructCtor,
/// Initializer for a const
Initializer,
/// Pattern binding
- Binding(InternedString),
+ Binding(Ident),
/// An `impl Trait` type node.
ImplTrait,
/// A `typeof` type node.
node_to_def_index: NodeMap(),
def_index_to_node: [vec![], vec![]],
node_to_hir_id: IndexVec::new(),
+ macro_def_scopes: FxHashMap(),
+ expansions: FxHashMap(),
}
}
parent: DefIndex,
node_id: ast::NodeId,
data: DefPathData,
- address_space: DefIndexAddressSpace)
+ address_space: DefIndexAddressSpace,
+ expansion: Mark)
-> DefIndex {
debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
parent, node_id, data);
assert_eq!(index.as_array_index(),
self.def_index_to_node[address_space.index()].len());
self.def_index_to_node[address_space.index()].push(node_id);
+ if expansion.is_modern() {
+ self.expansions.insert(index, expansion);
+ }
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
self.node_to_def_index.insert(node_id, index);
"Trying initialize NodeId -> HirId mapping twice");
self.node_to_hir_id = mapping;
}
+
+ pub fn expansion(&self, index: DefIndex) -> Mark {
+ self.expansions.get(&index).cloned().unwrap_or(Mark::root())
+ }
+
+ pub fn macro_def_scope(&self, mark: Mark) -> DefId {
+ self.macro_def_scopes[&mark]
+ }
+
+ pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) {
+ self.macro_def_scopes.insert(mark, scope);
+ }
}
impl DefPathData {
- pub fn get_opt_name(&self) -> Option<ast::Name> {
+ pub fn get_opt_ident(&self) -> Option<Ident> {
use self::DefPathData::*;
match *self {
- TypeNs(ref name) |
- ValueNs(ref name) |
- Module(ref name) |
- MacroDef(ref name) |
- TypeParam(ref name) |
- LifetimeDef(ref name) |
- EnumVariant(ref name) |
- Binding(ref name) |
- Field(ref name) => Some(Symbol::intern(name)),
+ TypeNs(ident) |
+ ValueNs(ident) |
+ Module(ident) |
+ MacroDef(ident) |
+ TypeParam(ident) |
+ LifetimeDef(ident) |
+ EnumVariant(ident) |
+ Binding(ident) |
+ Field(ident) => Some(ident),
Impl |
CrateRoot |
}
}
+ pub fn get_opt_name(&self) -> Option<ast::Name> {
+ self.get_opt_ident().map(|ident| ident.name)
+ }
+
pub fn as_interned_str(&self) -> InternedString {
use self::DefPathData::*;
let s = match *self {
- TypeNs(ref name) |
- ValueNs(ref name) |
- Module(ref name) |
- MacroDef(ref name) |
- TypeParam(ref name) |
- LifetimeDef(ref name) |
- EnumVariant(ref name) |
- Binding(ref name) |
- Field(ref name) => {
- return name.clone();
+ TypeNs(ident) |
+ ValueNs(ident) |
+ Module(ident) |
+ MacroDef(ident) |
+ TypeParam(ident) |
+ LifetimeDef(ident) |
+ EnumVariant(ident) |
+ Binding(ident) |
+ Field(ident) => {
+ return ident.name.as_str();
}
// note that this does not show up in user printouts
self.as_interned_str().to_string()
}
}
+
+impl Eq for DefPathData {}
+impl PartialEq for DefPathData {
+ fn eq(&self, other: &DefPathData) -> bool {
+ ::std::mem::discriminant(self) == ::std::mem::discriminant(other) &&
+ self.get_opt_ident() == other.get_opt_ident()
+ }
+}
+
+impl ::std::hash::Hash for DefPathData {
+ fn hash<H: ::std::hash::Hasher>(&self, hasher: &mut H) {
+ ::std::mem::discriminant(self).hash(hasher);
+ if let Some(ident) = self.get_opt_ident() {
+ if ident.ctxt == SyntaxContext::empty() && ident.name == ident.name.interned() {
+ ident.name.as_str().hash(hasher)
+ } else {
+ // FIXME(jseyfried) implement stable hashing for idents with macros 2.0 hygiene info
+ ident.hash(hasher)
+ }
+ }
+ }
+}
/// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no
/// module parent is in this map.
- pub fn get_module_parent(&self, id: NodeId) -> NodeId {
- match self.walk_parent_nodes(id, |node| match *node {
+ pub fn get_module_parent(&self, id: NodeId) -> DefId {
+ let id = match self.walk_parent_nodes(id, |node| match *node {
NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true,
_ => false,
}) {
Ok(id) => id,
Err(id) => id,
- }
+ };
+ self.local_def_id(id)
}
/// Returns the nearest enclosing scope. A scope is an item or block.
}
pub fn is_static(&self) -> bool {
- self.name == keywords::StaticLifetime.name()
+ self.name == "'static"
}
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct MacroDef {
pub name: Name,
+ pub vis: Visibility,
pub attrs: HirVec<Attribute>,
pub id: NodeId,
pub span: Span,
pub body: TokenStream,
+ pub legacy: bool,
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
impl_stable_hash_for!(struct hir::MacroDef {
name,
+ vis,
attrs,
id,
span,
+ legacy,
body
});
}
impl_stable_hash_for!(struct hir::def::Export {
- name,
+ ident,
def,
span
});
Stdcall,
Fastcall,
Vectorcall,
+ Thiscall,
Aapcs,
Win64,
SysV64,
impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
-impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, name });
+impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
+#![feature(discriminant_value)]
#![feature(i128_type)]
#![feature(libc)]
#![feature(never_type)]
use std::default::Default as StdDefault;
use std::mem;
use std::fmt;
+use std::cell::{Ref, RefCell};
use syntax::attr;
use syntax::ast;
use syntax::symbol::Symbol;
use hir::def_id::LOCAL_CRATE;
use hir::intravisit as hir_visit;
use syntax::visit as ast_visit;
-use syntax::tokenstream::ThinTokenStream;
/// Information about the registered lints.
///
lints: Vec<(&'static Lint, bool)>,
/// Trait objects for each lint pass.
- /// This is only `None` while iterating over the objects. See the definition
- /// of run_lints.
+ /// This is only `None` while performing a lint pass. See the definition
+ /// of `LintSession::new`.
early_passes: Option<Vec<EarlyLintPassObject>>,
late_passes: Option<Vec<LateLintPassObject>>,
by_name: FxHashMap<String, TargetLint>,
/// Current levels of each lint, and where they were set.
- levels: FxHashMap<LintId, LevelSource>,
+ levels: LintLevels,
/// Map of registered lint groups to what lints they expand to. The bool
/// is true if the lint group was added by a plugin.
/// Extra info for future incompatibility lints, descibing the
/// issue or RFC that caused the incompatibility.
future_incompatible: FxHashMap<LintId, FutureIncompatibleInfo>,
+}
+
+
+#[derive(Default)]
+struct LintLevels {
+ /// Current levels of each lint, and where they were set.
+ levels: FxHashMap<LintId, LevelSource>,
/// Maximum level a lint can be
lint_cap: Option<Level>,
}
+
+pub struct LintSession<'a, PassObject> {
+ /// Reference to the store of registered lints.
+ lints: Ref<'a, LintStore>,
+
+ /// The current lint levels.
+ levels: LintLevels,
+
+ /// When recursing into an attributed node of the ast which modifies lint
+ /// levels, this stack keeps track of the previous lint levels of whatever
+ /// was modified.
+ stack: Vec<(LintId, LevelSource)>,
+
+ /// Trait objects for each lint pass.
+ passes: Option<Vec<PassObject>>,
+}
+
+
/// When you call `add_lint` on the session, you wind up storing one
/// of these, which records a "potential lint" at a particular point.
#[derive(PartialEq, RustcEncodable, RustcDecodable)]
}
impl LintStore {
- fn get_level_source(&self, lint: LintId) -> LevelSource {
- match self.levels.get(&lint) {
- Some(&s) => s,
- None => (Allow, Default),
- }
- }
-
- fn set_level(&mut self, lint: LintId, mut lvlsrc: LevelSource) {
- if let Some(cap) = self.lint_cap {
- lvlsrc.0 = cmp::min(lvlsrc.0, cap);
- }
- if lvlsrc.0 == Allow {
- self.levels.remove(&lint);
- } else {
- self.levels.insert(lint, lvlsrc);
- }
- }
-
pub fn new() -> LintStore {
LintStore {
lints: vec![],
early_passes: Some(vec![]),
late_passes: Some(vec![]),
by_name: FxHashMap(),
- levels: FxHashMap(),
+ levels: LintLevels::default(),
future_incompatible: FxHashMap(),
lint_groups: FxHashMap(),
- lint_cap: None,
}
}
}
}
- if lint.default_level != Allow {
- self.levels.insert(id, (lint.default_level, Default));
- }
+ self.levels.set(id, (lint.default_level, Default));
}
}
let lint_flag_val = Symbol::intern(&lint_name);
match self.find_lint(&lint_name[..], sess, None) {
- Ok(lint_id) => self.set_level(lint_id, (level, CommandLine(lint_flag_val))),
+ Ok(lint_id) => self.levels.set(lint_id, (level, CommandLine(lint_flag_val))),
Err(FindLintError::Removed) => { }
Err(_) => {
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
Vec<LintId>>>()
.get(&lint_name[..]) {
Some(v) => {
- v.iter()
- .map(|lint_id: &LintId|
- self.set_level(*lint_id, (level, CommandLine(lint_flag_val))))
- .collect::<Vec<()>>();
+ for lint_id in v {
+ self.levels.set(*lint_id, (level, CommandLine(lint_flag_val)));
+ }
}
None => {
// The lint or lint group doesn't exist.
}
}
- self.lint_cap = sess.opts.lint_cap;
+ self.levels.set_lint_cap(sess.opts.lint_cap);
+ }
+}
+
+
+impl LintLevels {
+ fn get_source(&self, lint: LintId) -> LevelSource {
+ match self.levels.get(&lint) {
+ Some(&s) => s,
+ None => (Allow, Default),
+ }
+ }
+
+ fn set(&mut self, lint: LintId, mut lvlsrc: LevelSource) {
if let Some(cap) = self.lint_cap {
- for level in self.levels.iter_mut().map(|p| &mut (p.1).0) {
- *level = cmp::min(*level, cap);
+ lvlsrc.0 = cmp::min(lvlsrc.0, cap);
+ }
+ if lvlsrc.0 == Allow {
+ self.levels.remove(&lint);
+ } else {
+ self.levels.insert(lint, lvlsrc);
+ }
+ }
+
+ fn set_lint_cap(&mut self, lint_cap: Option<Level>) {
+ self.lint_cap = lint_cap;
+ if let Some(cap) = lint_cap {
+ for (_, level) in &mut self.levels {
+ level.0 = cmp::min(level.0, cap);
}
}
}
}
+
+impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> {
+ /// Creates a new `LintSession`, by moving out the `LintStore`'s initial
+ /// lint levels and pass objects. These can be restored using the `restore`
+ /// method.
+ fn new(store: &'a RefCell<LintStore>) -> LintSession<'a, PassObject> {
+ let mut s = store.borrow_mut();
+ let levels = mem::replace(&mut s.levels, LintLevels::default());
+ let passes = PassObject::take_passes(&mut *s);
+ drop(s);
+ LintSession {
+ lints: store.borrow(),
+ stack: Vec::new(),
+ levels,
+ passes,
+ }
+ }
+
+ /// Restores the levels back to the original lint store.
+ fn restore(self, store: &RefCell<LintStore>) {
+ drop(self.lints);
+ let mut s = store.borrow_mut();
+ s.levels = self.levels;
+ PassObject::restore_passes(&mut *s, self.passes);
+ }
+
+ fn get_source(&self, lint_id: LintId) -> LevelSource {
+ self.levels.get_source(lint_id)
+ }
+}
+
+
+
/// Context for lint checking after type checking.
pub struct LateContext<'a, 'tcx: 'a> {
/// Type context we're checking in.
/// Items accessible from the crate being checked.
pub access_levels: &'a AccessLevels,
- /// The store of registered lints.
- lints: LintStore,
-
- /// When recursing into an attributed node of the ast which modifies lint
- /// levels, this stack keeps track of the previous lint levels of whatever
- /// was modified.
- level_stack: Vec<(LintId, LevelSource)>,
+ /// The store of registered lints and the lint levels.
+ lint_sess: LintSession<'tcx, LateLintPassObject>,
}
/// Context for lint checking of the AST, after expansion, before lowering to
/// The crate being checked.
pub krate: &'a ast::Crate,
- /// The store of registered lints.
- lints: LintStore,
-
- /// When recursing into an attributed node of the ast which modifies lint
- /// levels, this stack keeps track of the previous lint levels of whatever
- /// was modified.
- level_stack: Vec<(LintId, LevelSource)>,
+ /// The store of registered lints and the lint levels.
+ lint_sess: LintSession<'a, EarlyLintPassObject>,
}
/// Convenience macro for calling a `LintPass` method on every pass in the context.
macro_rules! run_lints { ($cx:expr, $f:ident, $ps:ident, $($args:expr),*) => ({
// Move the vector of passes out of `$cx` so that we can
// iterate over it mutably while passing `$cx` to the methods.
- let mut passes = $cx.mut_lints().$ps.take().unwrap();
+ let mut passes = $cx.lint_sess_mut().passes.take().unwrap();
for obj in &mut passes {
obj.$f($cx, $($args),*);
}
- $cx.mut_lints().$ps = Some(passes);
+ $cx.lint_sess_mut().passes = Some(passes);
}) }
/// Parse the lint attributes into a vector, with `Err`s for malformed lint
err
}
+
+pub trait LintPassObject: Sized {
+ fn take_passes(store: &mut LintStore) -> Option<Vec<Self>>;
+ fn restore_passes(store: &mut LintStore, passes: Option<Vec<Self>>);
+}
+
+impl LintPassObject for EarlyLintPassObject {
+ fn take_passes(store: &mut LintStore) -> Option<Vec<Self>> {
+ store.early_passes.take()
+ }
+
+ fn restore_passes(store: &mut LintStore, passes: Option<Vec<Self>>) {
+ store.early_passes = passes;
+ }
+}
+
+impl LintPassObject for LateLintPassObject {
+ fn take_passes(store: &mut LintStore) -> Option<Vec<Self>> {
+ store.late_passes.take()
+ }
+
+ fn restore_passes(store: &mut LintStore, passes: Option<Vec<Self>>) {
+ store.late_passes = passes;
+ }
+}
+
+
pub trait LintContext<'tcx>: Sized {
+ type PassObject: LintPassObject;
+
fn sess(&self) -> &Session;
fn lints(&self) -> &LintStore;
- fn mut_lints(&mut self) -> &mut LintStore;
- fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)>;
+ fn lint_sess(&self) -> &LintSession<'tcx, Self::PassObject>;
+ fn lint_sess_mut(&mut self) -> &mut LintSession<'tcx, Self::PassObject>;
fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]);
fn exit_attrs(&mut self, attrs: &'tcx [ast::Attribute]);
/// Get the level of `lint` at the current position of the lint
/// traversal.
fn current_level(&self, lint: &'static Lint) -> Level {
- self.lints().levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl)
+ self.lint_sess().get_source(LintId::of(lint)).0
}
fn level_src(&self, lint: &'static Lint) -> Option<LevelSource> {
- self.lints().levels.get(&LintId::of(lint)).map(|ls| match ls {
+ let ref levels = self.lint_sess().levels;
+ levels.levels.get(&LintId::of(lint)).map(|ls| match ls {
&(Warn, _) => {
let lint_id = LintId::of(builtin::WARNINGS);
- let warn_src = self.lints().get_level_source(lint_id);
+ let warn_src = levels.get_source(lint_id);
if warn_src.0 != Warn {
warn_src
} else {
let lint_attr_name = result.expect("lint attribute should be well-formed").0;
for (lint_id, level, span) in v {
- let (now, now_source) = self.lints().get_level_source(lint_id);
+ let (now, now_source) = self.lint_sess().get_source(lint_id);
if now == Forbid && level != Forbid {
let lint_name = lint_id.to_string();
let mut diag_builder = struct_span_err!(self.sess(), span, E0453,
}
}.emit()
} else if now != level {
- let src = self.lints().get_level_source(lint_id).1;
- self.level_stack().push((lint_id, (now, src)));
+ let cx = self.lint_sess_mut();
+ cx.stack.push((lint_id, (now, now_source)));
pushed += 1;
- self.mut_lints().set_level(lint_id, (level, Node(lint_attr_name, span)));
+ cx.levels.set(lint_id, (level, Node(lint_attr_name, span)));
}
}
}
self.exit_attrs(attrs);
// rollback
+ let cx = self.lint_sess_mut();
for _ in 0..pushed {
- let (lint, lvlsrc) = self.level_stack().pop().unwrap();
- self.mut_lints().set_level(lint, lvlsrc);
+ let (lint, lvlsrc) = cx.stack.pop().unwrap();
+ cx.levels.set(lint, lvlsrc);
}
}
}
impl<'a> EarlyContext<'a> {
fn new(sess: &'a Session,
krate: &'a ast::Crate) -> EarlyContext<'a> {
- // We want to own the lint store, so move it out of the session. Remember
- // to put it back later...
- let lint_store = mem::replace(&mut *sess.lint_store.borrow_mut(),
- LintStore::new());
EarlyContext {
sess: sess,
krate: krate,
- lints: lint_store,
- level_stack: vec![],
+ lint_sess: LintSession::new(&sess.lint_store),
}
}
}
impl<'a, 'tcx> LintContext<'tcx> for LateContext<'a, 'tcx> {
+ type PassObject = LateLintPassObject;
+
/// Get the overall compiler `Session` object.
fn sess(&self) -> &Session {
&self.tcx.sess
}
fn lints(&self) -> &LintStore {
- &self.lints
+ &*self.lint_sess.lints
}
- fn mut_lints(&mut self) -> &mut LintStore {
- &mut self.lints
+ fn lint_sess(&self) -> &LintSession<'tcx, Self::PassObject> {
+ &self.lint_sess
}
- fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> {
- &mut self.level_stack
+ fn lint_sess_mut(&mut self) -> &mut LintSession<'tcx, Self::PassObject> {
+ &mut self.lint_sess
}
fn enter_attrs(&mut self, attrs: &'tcx [ast::Attribute]) {
}
impl<'a> LintContext<'a> for EarlyContext<'a> {
+ type PassObject = EarlyLintPassObject;
+
/// Get the overall compiler `Session` object.
fn sess(&self) -> &Session {
&self.sess
}
fn lints(&self) -> &LintStore {
- &self.lints
+ &*self.lint_sess.lints
}
- fn mut_lints(&mut self) -> &mut LintStore {
- &mut self.lints
+ fn lint_sess(&self) -> &LintSession<'a, Self::PassObject> {
+ &self.lint_sess
}
- fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> {
- &mut self.level_stack
+ fn lint_sess_mut(&mut self) -> &mut LintSession<'a, Self::PassObject> {
+ &mut self.lint_sess
}
fn enter_attrs(&mut self, attrs: &'a [ast::Attribute]) {
run_lints!(self, check_attribute, early_passes, attr);
}
- fn visit_mac_def(&mut self, _mac: &'a ThinTokenStream, id: ast::NodeId) {
+ fn visit_mac_def(&mut self, _mac: &'a ast::MacroDef, id: ast::NodeId) {
let lints = self.sess.lints.borrow_mut().take(id);
for early_lint in lints {
self.early_lint(&early_lint);
continue;
}
Ok((lint_name, _, span)) => {
- match check_lint_name(&cx.lints, &lint_name.as_str()) {
+ match check_lint_name(&cx.lint_sess.lints, &lint_name.as_str()) {
CheckLintNameResult::Ok => (),
CheckLintNameResult::Warning(ref msg) => {
cx.span_lint(builtin::RENAMED_AND_REMOVED_LINTS,
let krate = tcx.hir.krate();
- // We want to own the lint store, so move it out of the session.
- let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), LintStore::new());
let mut cx = LateContext {
tcx: tcx,
tables: &ty::TypeckTables::empty(),
krate: krate,
access_levels: access_levels,
- lints: lint_store,
- level_stack: vec![],
+ lint_sess: LintSession::new(&tcx.sess.lint_store),
};
// Visit the whole crate.
}
}
- // Put the lint store back in the session.
- mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), cx.lints);
+ // Put the lint store levels and passes back in the session.
+ cx.lint_sess.restore(&tcx.sess.lint_store);
}
pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
run_lints!(cx, check_crate_post, early_passes, krate);
});
- // Put the lint store back in the session.
- mem::replace(&mut *sess.lint_store.borrow_mut(), cx.lints);
+ // Put the lint store levels and passes back in the session.
+ cx.lint_sess.restore(&sess.lint_store);
// If we missed any lints added to the session, then there's a bug somewhere
// in the iteration code.
struct EffectCheckVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
+ body_id: hir::BodyId,
/// Whether we're in an unsafe context.
unsafe_context: UnsafeContext,
fn visit_nested_body(&mut self, body: hir::BodyId) {
let old_tables = self.tables;
+ let old_body_id = self.body_id;
self.tables = self.tcx.body_tables(body);
+ self.body_id = body;
let body = self.tcx.hir.body(body);
self.visit_body(body);
self.tables = old_tables;
+ self.body_id = old_body_id;
}
fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl,
}
}
}
+ hir::ExprAssign(ref lhs, ref rhs) => {
+ if let hir::ExprField(ref base_expr, field) = lhs.node {
+ if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty {
+ if adt.is_union() {
+ let field_ty = self.tables.expr_ty_adjusted(lhs);
+ let owner_def_id = self.tcx.hir.body_owner_def_id(self.body_id);
+ let param_env = self.tcx.param_env(owner_def_id);
+ if field_ty.moves_by_default(self.tcx, param_env, field.span) {
+ self.require_unsafe(field.span,
+ "assignment to non-`Copy` union field");
+ }
+ // Do not walk the field expr again.
+ intravisit::walk_expr(self, base_expr);
+ intravisit::walk_expr(self, rhs);
+ return
+ }
+ }
+ }
+ }
_ => {}
}
let mut visitor = EffectCheckVisitor {
tcx: tcx,
tables: &ty::TypeckTables::empty(),
+ body_id: hir::BodyId { node_id: ast::CRATE_NODE_ID },
unsafe_context: UnsafeContext::new(SafeContext),
};
use syntax::ast;
use syntax::attr;
use syntax::ptr::P;
-use syntax::symbol::keywords;
use syntax_pos::Span;
use errors::DiagnosticBuilder;
use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap};
match set {
Set1::Empty => Set1::Empty,
Set1::One(name) => {
- if name == keywords::StaticLifetime.name() {
+ if name == "'static" {
Set1::One(Region::Static)
} else {
generics.lifetimes.iter().enumerate().find(|&(_, def)| {
use std::slice;
use std::vec::IntoIter;
use std::mem;
-use syntax::ast::{self, DUMMY_NODE_ID, Name, NodeId};
+use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
use syntax::attr;
+use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::symbol::{Symbol, InternedString};
use syntax_pos::{DUMMY_SP, Span};
use rustc_const_math::ConstInt;
def => Visibility::Restricted(def.def_id()),
},
hir::Inherited => {
- Visibility::Restricted(tcx.hir.local_def_id(tcx.hir.get_module_parent(id)))
+ Visibility::Restricted(tcx.hir.get_module_parent(id))
}
}
}
impl<'a, 'gcx, 'tcx> VariantDef {
#[inline]
- pub fn find_field_named(&self,
- name: ast::Name)
- -> Option<&FieldDef> {
- self.fields.iter().find(|f| f.name == name)
+ pub fn find_field_named(&self, name: ast::Name) -> Option<&FieldDef> {
+ self.index_of_field_named(name).map(|index| &self.fields[index])
}
- #[inline]
- pub fn index_of_field_named(&self,
- name: ast::Name)
- -> Option<usize> {
- self.fields.iter().position(|f| f.name == name)
+ pub fn index_of_field_named(&self, name: ast::Name) -> Option<usize> {
+ if let Some(index) = self.fields.iter().position(|f| f.name == name) {
+ return Some(index);
+ }
+ let mut ident = name.to_ident();
+ while ident.ctxt != SyntaxContext::empty() {
+ ident.ctxt.remove_mark();
+ if let Some(field) = self.fields.iter().position(|f| f.name.to_ident() == ident) {
+ return Some(field);
+ }
+ }
+ None
}
#[inline]
}
}
- pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool {
- vis.is_accessible_from(self.hir.local_def_id(self.hir.get_module_parent(block)), self)
- }
-
pub fn item_name(self, id: DefId) -> ast::Name {
if let Some(id) = self.hir.as_local_node_id(id) {
self.hir.name(id)
Err(self.sess.cstore.crate_name(impl_did.krate))
}
}
+
+ pub fn adjust(self, name: Name, scope: DefId, block: NodeId) -> (Ident, DefId) {
+ self.adjust_ident(name.to_ident(), scope, block)
+ }
+
+ pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) {
+ let expansion = match scope.krate {
+ LOCAL_CRATE => self.hir.definitions().expansion(scope.index),
+ _ => Mark::root(),
+ };
+ let scope = match ident.ctxt.adjust(expansion) {
+ Some(macro_def) => self.hir.definitions().macro_def_scope(macro_def),
+ None => self.hir.get_module_parent(block),
+ };
+ (ident, scope)
+ }
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm
pub fn abi_blacklist() -> Vec<Abi> {
- vec![Abi::Stdcall, Abi::Fastcall, Abi::Vectorcall, Abi::Win64, Abi::SysV64]
+ vec![Abi::Stdcall, Abi::Fastcall, Abi::Vectorcall, Abi::Thiscall, Abi::Win64, Abi::SysV64]
}
}
}
- let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id));
+ let module = self.tcx.hir.get_module_parent(scrut.id);
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
let mut have_errors = false;
// Then, if the match has no arms, check whether the scrutinee
// is uninhabited.
let pat_ty = self.tables.node_id_to_type(scrut.id);
- let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id));
+ let module = self.tcx.hir.get_module_parent(scrut.id);
if inlined_arms.is_empty() {
let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
pat_ty.is_uninhabited_from(module, self.tcx)
"local binding"
};
- let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(pat.id));
+ let module = self.tcx.hir.get_module_parent(pat.id);
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
let mut patcx = PatternContext::new(self.tcx, self.tables);
let pattern = patcx.lower_pattern(pat);
fn abort_msg(err_count: usize) -> String {
match err_count {
0 => "aborting with no errors (maybe a bug?)".to_owned(),
- 1 => "aborting due to previous error".to_owned(),
- e => format!("aborting due to {} previous errors", e),
+ _ => "aborting due to previous error(s)".to_owned(),
}
}
return;
}
- 1 => s = "aborting due to previous error".to_string(),
- _ => {
- s = format!("aborting due to {} previous errors", self.err_count.get());
- }
+ _ => s = "aborting due to previous error(s)".to_string(),
}
panic!(self.fatal(&s));
+++ /dev/null
-[root]
-name = "rustc_llvm"
-version = "0.0.0"
-dependencies = [
- "build_helper 0.1.0",
- "gcc 0.3.28 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_bitflags 0.0.0",
-]
-
-[[package]]
-name = "build_helper"
-version = "0.1.0"
-
-[[package]]
-name = "gcc"
-version = "0.3.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "rustc_bitflags"
-version = "0.0.0"
-
X86FastcallCallConv = 65,
ArmAapcsCallConv = 67,
Msp430Intr = 69,
+ X86_ThisCall = 70,
PtxKernel = 71,
X86_64_SysV = 78,
X86_64_Win64 = 79,
id: ast::DUMMY_NODE_ID,
span: local_span,
attrs: attrs.iter().cloned().collect(),
- node: ast::ItemKind::MacroDef(body.into()),
+ node: ast::ItemKind::MacroDef(ast::MacroDef {
+ tokens: body.into(),
+ legacy: def.legacy,
+ }),
vis: ast::Visibility::Inherited,
})
}
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
use syntax::attr;
-use syntax::ast;
+use syntax::ast::{self, Ident};
use syntax::codemap;
use syntax::ext::base::MacroKind;
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
},
ext.kind()
);
- callback(def::Export { name: name, def: def, span: DUMMY_SP });
+ let ident = Ident::with_empty_ctxt(name);
+ callback(def::Export { ident: ident, def: def, span: DUMMY_SP });
}
}
return
if let Some(def) = self.get_def(child_index) {
callback(def::Export {
def: def,
- name: self.item_name(child_index),
+ ident: Ident::with_empty_ctxt(self.item_name(child_index)),
span: self.entry(child_index).span.decode(self),
});
}
let span = child.span.decode(self);
if let (Some(def), Some(name)) =
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
- callback(def::Export { def: def, name: name, span: span });
+ let ident = Ident::with_empty_ctxt(name);
+ callback(def::Export { def: def, ident: ident, span: span });
// For non-reexport structs and variants add their constructors to children.
// Reexport lists automatically contain constructors when necessary.
match def {
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
let ctor_kind = self.get_ctor_kind(child_index);
let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
- callback(def::Export { def: ctor_def, name: name, span: span });
+ callback(def::Export { def: ctor_def, ident: ident, span: span });
}
}
Def::Variant(def_id) => {
// value namespace, they are reserved for possible future use.
let ctor_kind = self.get_ctor_kind(child_index);
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
- callback(def::Export { def: ctor_def, name: name, span: span });
+ callback(def::Export { def: ctor_def, ident: ident, span: span });
}
_ => {}
}
Entry {
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
body: pprust::tts_to_string(¯o_def.body.trees().collect::<Vec<_>>()),
+ legacy: macro_def.legacy,
})),
visibility: self.lazy(&ty::Visibility::Public),
span: self.lazy(¯o_def.span),
#[derive(RustcEncodable, RustcDecodable)]
pub struct MacroDef {
pub body: String,
+ pub legacy: bool,
}
-impl_stable_hash_for!(struct MacroDef { body });
+impl_stable_hash_for!(struct MacroDef { body, legacy });
#[derive(RustcEncodable, RustcDecodable)]
pub struct FnData {
impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_lifetime(&mut self, lt: &'a Lifetime) {
- if lt.name == "'_" {
+ if lt.ident.name == "'_" {
self.session.add_lint(lint::builtin::LIFETIME_UNDERSCORE,
lt.id,
lt.span,
- format!("invalid lifetime name `{}`", lt.name));
+ format!("invalid lifetime name `{}`", lt.ident));
}
visit::walk_lifetime(self, lt)
let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
let param_env = infcx.param_env.clone();
let outer_penv = mem::replace(&mut self.param_env, param_env);
- let region_maps = &self.tcx.region_maps(item_def_id);;
+ let region_maps = &self.tcx.region_maps(item_def_id);
euv::ExprUseVisitor::new(self, region_maps, &infcx).consume_body(body);
outer_penv
});
use rustc::hir::{self, PatKind};
use rustc::hir::def::Def;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
+use rustc::hir::def_id::{LOCAL_CRATE, CrateNum, DefId};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::DeepVisitor;
use rustc::lint;
use rustc::ty::fold::TypeVisitor;
use rustc::ty::maps::Providers;
use rustc::util::nodemap::NodeSet;
-use syntax::ast;
+use syntax::ast::{self, CRATE_NODE_ID, Ident};
+use syntax::symbol::keywords;
use syntax_pos::Span;
use std::cmp;
}
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
- self.update(md.id, Some(AccessLevel::Public));
+ if md.legacy {
+ self.update(md.id, Some(AccessLevel::Public));
+ return
+ }
+
+ let module_did = ty::DefIdTree::parent(self.tcx, self.tcx.hir.local_def_id(md.id)).unwrap();
+ let mut module_id = self.tcx.hir.as_local_node_id(module_did).unwrap();
+ let level = if md.vis == hir::Public { self.get(module_id) } else { None };
+ let level = self.update(md.id, level);
+ if level.is_none() {
+ return
+ }
+
+ loop {
+ let module = if module_id == ast::CRATE_NODE_ID {
+ &self.tcx.hir.krate().module
+ } else if let hir::ItemMod(ref module) = self.tcx.hir.expect_item(module_id).node {
+ module
+ } else {
+ unreachable!()
+ };
+ for id in &module.item_ids {
+ self.update(id.id, level);
+ }
+ if module_id == ast::CRATE_NODE_ID {
+ break
+ }
+ module_id = self.tcx.hir.get_parent_node(module_id);
+ }
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
struct NamePrivacyVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
- current_item: DefId,
+ current_item: ast::NodeId,
}
impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
// Checks that a field is accessible.
fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
- if !def.is_enum() && !field.vis.is_accessible_from(self.current_item, self.tcx) {
+ let ident = Ident { ctxt: span.ctxt.modern(), ..keywords::Invalid.ident() };
+ 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",
field.name, def.variant_descr(), self.tcx.item_path_str(def.did))
.span_label(span, format!("field `{}` is private", field.name))
}
fn visit_item(&mut self, item: &'tcx hir::Item) {
- let orig_current_item = replace(&mut self.current_item, self.tcx.hir.local_def_id(item.id));
+ let orig_current_item = replace(&mut self.current_item, item.id);
intravisit::walk_item(self, item);
self.current_item = orig_current_item;
}
let mut visitor = NamePrivacyVisitor {
tcx: tcx,
tables: &ty::TypeckTables::empty(),
- current_item: DefId::local(CRATE_DEF_INDEX),
+ current_item: CRATE_NODE_ID,
};
intravisit::walk_crate(&mut visitor, krate);
use rustc::middle::cstore::LoadedMacro;
use rustc::hir::def::*;
-use rustc::hir::def_id::{CrateNum, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefId};
+use rustc::hir::def_id::{BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
use rustc::ty;
use std::cell::Cell;
impl<'a> Resolver<'a> {
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
/// otherwise, reports an error.
- fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
+ pub fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
where T: ToNameBinding<'a>,
{
let binding = def.to_name_binding(self.arenas);
view_path.span,
ResolutionError::SelfImportsOnlyAllowedWithin);
} else if source_name == "$crate" && full_path.segments.len() == 1 {
- let crate_root = self.resolve_crate_var(source.ctxt, item.span);
+ let crate_root = self.resolve_crate_root(source.ctxt);
let crate_name = match crate_root.kind {
ModuleKind::Def(_, name) => name,
ModuleKind::Block(..) => unreachable!(),
// n.b. we don't need to look at the path option here, because cstore already did
let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
- let module = self.get_extern_crate_root(crate_id, item.span);
+ let module =
+ self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(module);
let used = self.process_legacy_macro_imports(item, module, expansion);
let binding =
no_implicit_prelude: parent.no_implicit_prelude || {
attr::contains_name(&item.attrs, "no_implicit_prelude")
},
- ..ModuleData::new(Some(parent), module_kind, def_id, item.span)
+ ..ModuleData::new(Some(parent), module_kind, def_id, expansion, item.span)
});
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.module_map.insert(def_id, module);
let module = self.new_module(parent,
module_kind,
parent.normal_ancestor_id,
+ expansion,
item.span);
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
let module = self.new_module(parent,
module_kind,
parent.normal_ancestor_id,
+ expansion,
item.span);
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.current_module = module;
self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion));
}
- fn build_reduced_graph_for_block(&mut self, block: &Block) {
+ fn build_reduced_graph_for_block(&mut self, block: &Block, expansion: Mark) {
let parent = self.current_module;
if self.block_needs_anonymous_module(block) {
let module = self.new_module(parent,
ModuleKind::Block(block.id),
parent.normal_ancestor_id,
+ expansion,
block.span);
self.block_map.insert(block.id, module);
self.current_module = module; // Descend into the block.
/// Builds the reduced graph for a single item in an external crate.
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
- let ident = Ident::with_empty_ctxt(child.name);
+ let ident = child.ident;
let def = child.def;
let def_id = def.def_id();
let vis = self.session.cstore.visibility(def_id);
let span = child.span;
-
+ let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
match def {
Def::Mod(..) | Def::Enum(..) => {
let module = self.new_module(parent,
ModuleKind::Def(def, ident.name),
def_id,
+ expansion,
span);
- self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
+ self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
}
Def::Variant(..) | Def::TyAlias(..) => {
- self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
+ self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
}
Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
- self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
+ self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
}
Def::StructCtor(..) => {
- self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
+ self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
if let Some(struct_def_id) =
self.session.cstore.def_key(def_id).parent
let module = self.new_module(parent,
module_kind,
parent.normal_ancestor_id,
+ expansion,
span);
- self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
+ self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
for child in self.session.cstore.item_children(def_id) {
let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
- let ident = Ident::with_empty_ctxt(child.name);
- self.define(module, ident, ns, (child.def, ty::Visibility::Public,
- DUMMY_SP, Mark::root()));
+ self.define(module, child.ident, ns,
+ (child.def, ty::Visibility::Public, DUMMY_SP, expansion));
- let has_self = self.session.cstore.associated_item_cloned(child.def.def_id())
- .method_has_self_argument;
- self.trait_item_map.insert((def_id, child.name, ns), (child.def, has_self));
+ if self.session.cstore.associated_item_cloned(child.def.def_id())
+ .method_has_self_argument {
+ self.has_self.insert(child.def.def_id());
+ }
}
module.populated.set(true);
}
Def::Struct(..) | Def::Union(..) => {
- self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
+ self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
// Record field names for error reporting.
let field_names = self.session.cstore.struct_field_names(def_id);
self.insert_field_names(def_id, field_names);
}
Def::Macro(..) => {
- self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, Mark::root()));
+ self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, expansion));
}
_ => bug!("unexpected definition: {:?}", def)
}
}
- fn get_extern_crate_root(&mut self, cnum: CrateNum, span: Span) -> Module<'a> {
- let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
- let name = self.session.cstore.crate_name(cnum);
- let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
- let module_kind = ModuleKind::Def(Def::Mod(def_id), name);
- let arenas = self.arenas;
- *self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
- arenas.alloc_module(ModuleData::new(None, module_kind, def_id, span))
- })
+ pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
+ if def_id.krate == LOCAL_CRATE {
+ return self.module_map[&def_id]
+ }
+
+ let macros_only = self.session.cstore.dep_kind(def_id.krate).macros_only();
+ if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
+ return module;
+ }
+
+ let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
+ (self.session.cstore.crate_name(def_id.krate), None)
+ } else {
+ let def_key = self.session.cstore.def_key(def_id);
+ (def_key.disambiguated_data.data.get_opt_name().unwrap(),
+ Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
+ };
+
+ let kind = ModuleKind::Def(Def::Mod(def_id), name);
+ self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP))
}
- pub fn macro_def_scope(&mut self, expansion: Mark, span: Span) -> Module<'a> {
+ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
let def_id = self.macro_defs[&expansion];
if let Some(id) = self.definitions.as_local_node_id(def_id) {
self.local_macro_def_scopes[&id]
self.graph_root
} else {
let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
- self.get_extern_crate_root(module_def_id.krate, span)
+ self.get_module(module_def_id)
}
}
let ident = Ident::with_empty_ctxt(name);
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
if let Ok(binding) = result {
- self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
+ self.macro_exports.push(Export { ident: ident, def: binding.def(), span: span });
} else {
span_err!(self.session, span, E0470, "reexported macro not found");
}
fn visit_item(&mut self, item: &'a Item) {
let macro_use = match item.node {
ItemKind::MacroDef(..) => {
- self.resolver.define_macro(item, &mut self.legacy_scope);
+ self.resolver.define_macro(item, self.expansion, &mut self.legacy_scope);
return
}
ItemKind::Mac(..) => {
fn visit_block(&mut self, block: &'a Block) {
let (parent, legacy_scope) = (self.resolver.current_module, self.legacy_scope);
- self.resolver.build_reduced_graph_for_block(block);
+ self.resolver.build_reduced_graph_for_block(block, self.expansion);
visit::walk_block(self, block);
self.resolver.current_module = parent;
self.legacy_scope = legacy_scope;
fn visit_trait_item(&mut self, item: &'a TraitItem) {
let parent = self.resolver.current_module;
- let def_id = parent.def_id().unwrap();
if let TraitItemKind::Macro(_) = item.node {
self.visit_invoc(item.id);
// Add the item to the trait info.
let item_def_id = self.resolver.definitions.local_def_id(item.id);
- let (def, ns, has_self) = match item.node {
- TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS, false),
- TraitItemKind::Method(ref sig, _) =>
- (Def::Method(item_def_id), ValueNS, sig.decl.has_self()),
- TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS, false),
+ let (def, ns) = match item.node {
+ TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
+ TraitItemKind::Method(ref sig, _) => {
+ if sig.decl.has_self() {
+ self.resolver.has_self.insert(item_def_id);
+ }
+ (Def::Method(item_def_id), ValueNS)
+ }
+ TraitItemKind::Type(..) => (Def::AssociatedTy(item_def_id), TypeNS),
TraitItemKind::Macro(_) => bug!(), // handled above
};
- self.resolver.trait_item_map.insert((def_id, item.ident.name, ns), (def, has_self));
-
let vis = ty::Visibility::Public;
self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion));
use rustc::session::Session;
use rustc::lint;
use rustc::hir::def::*;
-use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
use rustc::ty;
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
use syntax::ext::base::SyntaxExtension;
-use syntax::ext::base::Determinacy::{Determined, Undetermined};
+use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::base::MacroKind;
use syntax::symbol::{Symbol, keywords};
use syntax::util::lev_distance::find_best_match_for_name;
/// Span of the module itself. Used for error reporting.
span: Span,
+
+ expansion: Mark,
}
pub type Module<'a> = &'a ModuleData<'a>;
fn new(parent: Option<Module<'a>>,
kind: ModuleKind,
normal_ancestor_id: DefId,
+ expansion: Mark,
span: Span) -> Self {
ModuleData {
parent: parent,
traits: RefCell::new(None),
populated: Cell::new(normal_ancestor_id.is_local()),
span: span,
+ expansion: expansion,
}
}
_ => true,
}
}
+
+ fn is_macro_def(&self) -> bool {
+ match self.kind {
+ NameBindingKind::Def(Def::Macro(..)) => true,
+ _ => false,
+ }
+ }
}
/// Interns the names of the primitive types.
prelude: Option<Module<'a>>,
- trait_item_map: FxHashMap<(DefId, Name, Namespace), (Def, bool /* has self */)>,
+ // n.b. This is used only for better diagnostics, not name resolution itself.
+ has_self: FxHashSet<DefId>,
// Names of fields of an item `DefId` accessible with dot syntax.
// Used for hints during error reporting.
label_ribs: Vec<Rib<'a>>,
// The trait that the current context can refer to.
- current_trait_ref: Option<(DefId, TraitRef)>,
+ current_trait_ref: Option<(Module<'a>, TraitRef)>,
// The current self type if inside an impl (used for better errors).
current_self_type: Option<Ty>,
// entry block for `f`.
block_map: NodeMap<Module<'a>>,
module_map: FxHashMap<DefId, Module<'a>>,
- extern_crate_roots: FxHashMap<(CrateNum, bool /* MacrosOnly? */), Module<'a>>,
+ extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>,
pub make_glob_map: bool,
// Maps imports to the names of items actually imported (this actually maps
use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
crate_loader: &'a mut CrateLoader,
- macro_names: FxHashSet<Name>,
+ macro_names: FxHashSet<Ident>,
global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
- lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>,
+ lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
macro_defs: FxHashMap<Mark, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
let graph_root = arenas.alloc_module(ModuleData {
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
- ..ModuleData::new(None, root_module_kind, root_def_id, krate.span)
+ ..ModuleData::new(None, root_module_kind, root_def_id, Mark::root(), krate.span)
});
let mut module_map = FxHashMap();
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
let mut definitions = Definitions::new();
- DefCollector::new(&mut definitions)
+ DefCollector::new(&mut definitions, Mark::root())
.collect_root(crate_name, &session.local_crate_disambiguator().as_str());
let mut invocations = FxHashMap();
graph_root: graph_root,
prelude: None,
- trait_item_map: FxHashMap(),
+ has_self: FxHashSet(),
field_names: FxHashMap(),
determined_imports: Vec::new(),
trait_map: NodeMap(),
module_map: module_map,
block_map: NodeMap(),
- extern_crate_roots: FxHashMap(),
+ extern_module_map: FxHashMap(),
make_glob_map: make_glob_map == MakeGlobMap::Yes,
glob_map: NodeMap(),
vis: ty::Visibility::Public,
}),
- // `#![feature(proc_macro)]` implies `#[feature(extern_macros)]`
- use_extern_macros: features.use_extern_macros || features.proc_macro,
+ // The `proc_macro` and `decl_macro` features imply `use_extern_macros`
+ use_extern_macros:
+ features.use_extern_macros || features.proc_macro || features.decl_macro,
crate_loader: crate_loader,
macro_names: FxHashSet(),
parent: Module<'a>,
kind: ModuleKind,
normal_ancestor_id: DefId,
+ expansion: Mark,
span: Span,
) -> Module<'a> {
- self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id, span))
+ let module = ModuleData::new(Some(parent), kind, normal_ancestor_id, expansion, span);
+ self.arenas.alloc_module(module)
}
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
path_span: Span)
-> Option<LexicalScopeBinding<'a>> {
if ns == TypeNS {
- ident = ident.unhygienize();
+ ident.ctxt = if ident.name == keywords::SelfType.name() {
+ SyntaxContext::empty() // FIXME(jseyfried) improve `Self` hygiene
+ } else {
+ ident.ctxt.modern()
+ }
}
// Walk backwards up the ribs in scope.
+ let mut module = self.graph_root;
for i in (0 .. self.ribs[ns].len()).rev() {
if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() {
// The ident resolves to a type parameter or local variable.
));
}
- if let ModuleRibKind(module) = self.ribs[ns][i].kind {
- let item = self.resolve_ident_in_module(module, ident, ns, false,
- record_used, path_span);
- if let Ok(binding) = item {
- // The ident resolves to an item.
- return Some(LexicalScopeBinding::Item(binding));
+ module = match self.ribs[ns][i].kind {
+ ModuleRibKind(module) => module,
+ MacroDefinition(def) if def == self.macro_defs[&ident.ctxt.outer()] => {
+ // 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();
+ continue
}
+ _ => continue,
+ };
- if let ModuleKind::Block(..) = module.kind { // We can see through blocks
- } else if !module.no_implicit_prelude {
- return self.prelude.and_then(|prelude| {
- self.resolve_ident_in_module(prelude, ident, ns, false,
- false, path_span).ok()
- }).map(LexicalScopeBinding::Item)
- } else {
- return None;
- }
+ let item = self.resolve_ident_in_module_unadjusted(
+ module, ident, ns, false, record_used, path_span,
+ );
+ if let Ok(binding) = item {
+ // The ident resolves to an item.
+ return Some(LexicalScopeBinding::Item(binding));
}
- if let MacroDefinition(def) = self.ribs[ns][i].kind {
- // If an invocation of this macro created `ident`, give up on `ident`
- // and switch to `ident`'s source from the macro definition.
- let ctxt_data = ident.ctxt.data();
- if def == self.macro_defs[&ctxt_data.outer_mark] {
- ident.ctxt = ctxt_data.prev_ctxt;
- }
+ match module.kind {
+ ModuleKind::Block(..) => {}, // We can see through blocks
+ _ => break,
}
}
+ ident.ctxt = ident.ctxt.modern();
+ loop {
+ module = unwrap_or!(self.hygienic_lexical_parent(module, &mut ident.ctxt), 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(
+ module, ident, ns, false, record_used, path_span,
+ );
+ self.current_module = orig_current_module;
+
+ match result {
+ Ok(binding) => return Some(LexicalScopeBinding::Item(binding)),
+ Err(Undetermined) => return None,
+ Err(Determined) => {}
+ }
+ }
+
+ match self.prelude {
+ Some(prelude) if !module.no_implicit_prelude => {
+ self.resolve_ident_in_module_unadjusted(prelude, ident, ns, false, false, path_span)
+ .ok().map(LexicalScopeBinding::Item)
+ }
+ _ => None,
+ }
+ }
+
+ fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, ctxt: &mut SyntaxContext)
+ -> Option<Module<'a>> {
+ if !module.expansion.is_descendant_of(ctxt.outer()) {
+ return Some(self.macro_def_scope(ctxt.remove_mark()));
+ }
+
+ if let ModuleKind::Block(..) = module.kind {
+ return Some(module.parent.unwrap());
+ }
+
+ let mut module_expansion = module.expansion.modern(); // for backward compatability
+ while let Some(parent) = module.parent {
+ 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()) {
+ Some(parent)
+ } else {
+ None
+ };
+ }
+ module = parent;
+ module_expansion = parent_expansion;
+ }
+
None
}
- fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext, span: Span) -> Module<'a> {
- let mut ctxt_data = crate_var_ctxt.data();
- while ctxt_data.prev_ctxt != SyntaxContext::empty() {
- ctxt_data = ctxt_data.prev_ctxt.data();
+ fn resolve_ident_in_module(&mut self,
+ module: Module<'a>,
+ mut ident: Ident,
+ ns: Namespace,
+ ignore_unresolved_invocations: bool,
+ record_used: bool,
+ span: Span)
+ -> Result<&'a NameBinding<'a>, Determinacy> {
+ ident.ctxt = ident.ctxt.modern();
+ let orig_current_module = self.current_module;
+ if let Some(def) = ident.ctxt.adjust(module.expansion) {
+ self.current_module = self.macro_def_scope(def);
+ }
+ let result = self.resolve_ident_in_module_unadjusted(
+ module, ident, ns, ignore_unresolved_invocations, record_used, span,
+ );
+ self.current_module = orig_current_module;
+ result
+ }
+
+ fn resolve_crate_root(&mut self, mut ctxt: SyntaxContext) -> Module<'a> {
+ let module = match ctxt.adjust(Mark::root()) {
+ Some(def) => self.macro_def_scope(def),
+ None => return self.graph_root,
+ };
+ self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id })
+ }
+
+ fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
+ let mut module = self.get_module(module.normal_ancestor_id);
+ while module.span.ctxt.modern() != *ctxt {
+ let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark()));
+ module = self.get_module(parent.normal_ancestor_id);
}
- let module = self.macro_def_scope(ctxt_data.outer_mark, span);
- if module.is_local() { self.graph_root } else { module }
+ module
}
// AST resolution
fn search_label(&self, mut ident: Ident) -> Option<Def> {
for rib in self.label_ribs.iter().rev() {
match rib.kind {
- NormalRibKind => {
- // Continue
- }
+ NormalRibKind => {}
+ // 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 an invocation of this macro created `ident`, give up on `ident`
- // and switch to `ident`'s source from the macro definition.
- let ctxt_data = ident.ctxt.data();
- if def == self.macro_defs[&ctxt_data.outer_mark] {
- ident.ctxt = ctxt_data.prev_ctxt;
+ if def == self.macro_defs[&ident.ctxt.outer()] {
+ ident.ctxt.remove_mark();
}
}
_ => {
let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = FxHashMap();
for type_parameter in &generics.ty_params {
- let name = type_parameter.ident.name;
+ let ident = type_parameter.ident.modern();
debug!("with_type_parameter_rib: {}", type_parameter.id);
- if seen_bindings.contains_key(&name) {
- let span = seen_bindings.get(&name).unwrap();
- resolve_error(self,
- type_parameter.span,
- ResolutionError::NameAlreadyUsedInTypeParameterList(name,
- span));
+ if seen_bindings.contains_key(&ident) {
+ let span = seen_bindings.get(&ident).unwrap();
+ let err =
+ ResolutionError::NameAlreadyUsedInTypeParameterList(ident.name, span);
+ resolve_error(self, type_parameter.span, err);
}
- seen_bindings.entry(name).or_insert(type_parameter.span);
+ seen_bindings.entry(ident).or_insert(type_parameter.span);
// plain insert (no renaming)
let def_id = self.definitions.local_def_id(type_parameter.id);
let def = Def::TyParam(def_id);
- function_type_rib.bindings.insert(Ident::with_empty_ctxt(name), def);
+ function_type_rib.bindings.insert(ident, def);
self.record_def(type_parameter.id, PathResolution::new(def));
}
self.ribs[TypeNS].push(function_type_rib);
let mut new_val = None;
let mut new_id = None;
if let Some(trait_ref) = opt_trait_ref {
- let def = self.smart_resolve_path(trait_ref.ref_id, None,
- &trait_ref.path, PathSource::Trait).base_def();
+ let path: Vec<_> = trait_ref.path.segments.iter().map(|seg| seg.identifier).collect();
+ let def = self.smart_resolve_path_fragment(trait_ref.ref_id,
+ None,
+ &path,
+ trait_ref.path.span,
+ trait_ref.path.segments.last().unwrap().span,
+ PathSource::Trait)
+ .base_def();
if def != Def::Err {
- new_val = Some((def.def_id(), trait_ref.clone()));
new_id = Some(def.def_id());
+ let span = trait_ref.path.span;
+ if let PathResult::Module(module) = self.resolve_path(&path, None, false, span) {
+ new_val = Some((module, trait_ref.clone()));
+ }
}
}
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
ImplItemKind::Const(..) => {
// If this is a trait impl, ensure the const
// exists in trait
- this.check_trait_item(impl_item.ident.name,
+ this.check_trait_item(impl_item.ident,
ValueNS,
impl_item.span,
|n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
ImplItemKind::Method(ref sig, _) => {
// If this is a trait impl, ensure the method
// exists in trait
- this.check_trait_item(impl_item.ident.name,
+ this.check_trait_item(impl_item.ident,
ValueNS,
impl_item.span,
|n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
ImplItemKind::Type(ref ty) => {
// If this is a trait impl, ensure the type
// exists in trait
- this.check_trait_item(impl_item.ident.name,
+ this.check_trait_item(impl_item.ident,
TypeNS,
impl_item.span,
|n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
});
}
- fn check_trait_item<F>(&self, name: Name, ns: Namespace, span: Span, err: F)
+ fn check_trait_item<F>(&mut self, ident: Ident, ns: Namespace, span: Span, err: F)
where F: FnOnce(Name, &str) -> ResolutionError
{
// If there is a TraitRef in scope for an impl, then the method must be in the
// trait.
- if let Some((did, ref trait_ref)) = self.current_trait_ref {
- if !self.trait_item_map.contains_key(&(did, name, ns)) {
- let path_str = path_names_to_string(&trait_ref.path);
- resolve_error(self, span, err(name, &path_str));
+ if let Some((module, _)) = self.current_trait_ref {
+ if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() {
+ let path = &self.current_trait_ref.as_ref().unwrap().1.path;
+ resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
}
}
}
}
// Try to lookup the name in more relaxed fashion for better error reporting.
- let name = path.last().unwrap().name;
- let candidates = this.lookup_import_candidates(name, ns, is_expected);
+ let ident = *path.last().unwrap();
+ let candidates = this.lookup_import_candidates(ident.name, ns, is_expected);
if !candidates.is_empty() {
let mut module_span = this.current_module.span;
module_span.hi = module_span.lo;
// Report import candidates as help and proceed searching for labels.
show_candidates(&mut err, module_span, &candidates, def.is_some());
} else if is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) {
- let enum_candidates = this.lookup_import_candidates(name, ns, is_enum_variant);
+ let enum_candidates =
+ 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::<Vec<_>>();
enum_candidates.sort();
}
}
if path.len() == 1 && this.self_type_is_available(span) {
- if let Some(candidate) = this.lookup_assoc_candidate(name, ns, is_expected) {
+ if let Some(candidate) = this.lookup_assoc_candidate(ident, ns, is_expected) {
let self_is_available = this.self_value_is_available(path[0].ctxt, span);
match candidate {
AssocSuggestion::Field => {
// or `<T>::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().name;
+ let item_name = *path.last().unwrap();
let traits = self.get_traits_containing_item(item_name, ns);
self.trait_map.insert(id, traits);
}
}
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].name)) {
+ if primary_ns != MacroNS && (is_global || 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))
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
if i == 0 && ns == TypeNS && ident.name == keywords::SelfValue.name() {
- module = Some(self.module_map[&self.current_module.normal_ancestor_id]);
+ let mut ctxt = ident.ctxt.modern();
+ module = Some(self.resolve_self(&mut ctxt, self.current_module));
continue
} else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() {
- let current_module = if i == 0 { self.current_module } else { module.unwrap() };
- let self_module = self.module_map[¤t_module.normal_ancestor_id];
+ let mut ctxt = ident.ctxt.modern();
+ let self_module = match i {
+ 0 => self.resolve_self(&mut ctxt, self.current_module),
+ _ => module.unwrap(),
+ };
if let Some(parent) = self_module.parent {
- module = Some(self.module_map[&parent.normal_ancestor_id]);
+ module = Some(self.resolve_self(&mut ctxt, parent));
continue
} else {
let msg = "There are too many initial `super`s.".to_string();
allow_super = false;
if i == 0 && ns == TypeNS && ident.name == keywords::CrateRoot.name() {
- module = Some(self.graph_root);
+ module = Some(self.resolve_crate_root(ident.ctxt.modern()));
continue
} else if i == 0 && ns == TypeNS && ident.name == "$crate" {
- module = Some(self.resolve_crate_var(ident.ctxt, path_span));
+ module = Some(self.resolve_crate_root(ident.ctxt));
continue
}
}
fn lookup_assoc_candidate<FilterFn>(&mut self,
- name: Name,
+ ident: Ident,
ns: Namespace,
filter_fn: FilterFn)
-> Option<AssocSuggestion>
Def::Struct(did) | Def::Union(did)
if resolution.unresolved_segments() == 0 => {
if let Some(field_names) = self.field_names.get(&did) {
- if field_names.iter().any(|&field_name| name == field_name) {
+ if field_names.iter().any(|&field_name| ident.name == field_name) {
return Some(AssocSuggestion::Field);
}
}
}
// Look for associated items in the current trait.
- if let Some((trait_did, _)) = self.current_trait_ref {
- if let Some(&(def, has_self)) = self.trait_item_map.get(&(trait_did, name, ns)) {
+ if let Some((module, _)) = self.current_trait_ref {
+ if let Ok(binding) =
+ self.resolve_ident_in_module(module, ident, ns, false, false, module.span) {
+ let def = binding.def();
if filter_fn(def) {
- return Some(if has_self {
+ return Some(if self.has_self.contains(&def.def_id()) {
AssocSuggestion::MethodWithSelf
} else {
AssocSuggestion::AssocItem
// 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.name, ValueNS);
+ let traits = self.get_traits_containing_item(name.node, ValueNS);
self.trait_map.insert(expr.id, traits);
}
ExprKind::MethodCall(name, ..) => {
debug!("(recording candidate traits for expr) recording traits for {}",
expr.id);
- let traits = self.get_traits_containing_item(name.node.name, ValueNS);
+ let traits = self.get_traits_containing_item(name.node, ValueNS);
self.trait_map.insert(expr.id, traits);
}
_ => {
}
}
- fn get_traits_containing_item(&mut self, name: Name, ns: Namespace) -> Vec<TraitCandidate> {
- debug!("(getting traits containing item) looking for '{}'", name);
+ fn get_traits_containing_item(&mut self, mut ident: Ident, ns: Namespace)
+ -> Vec<TraitCandidate> {
+ debug!("(getting traits containing item) looking for '{}'", ident.name);
let mut found_traits = Vec::new();
// Look for the current trait.
- if let Some((trait_def_id, _)) = self.current_trait_ref {
- if self.trait_item_map.contains_key(&(trait_def_id, name, ns)) {
- found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: None });
+ if let Some((module, _)) = self.current_trait_ref {
+ if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() {
+ let def_id = module.def_id().unwrap();
+ found_traits.push(TraitCandidate { def_id: def_id, import_id: None });
}
}
+ ident.ctxt = ident.ctxt.modern();
let mut search_module = self.current_module;
loop {
- self.get_traits_in_module_containing_item(name, ns, search_module, &mut found_traits);
- match search_module.kind {
- ModuleKind::Block(..) => search_module = search_module.parent.unwrap(),
- _ => break,
- }
+ 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);
}
if let Some(prelude) = self.prelude {
if !search_module.no_implicit_prelude {
- self.get_traits_in_module_containing_item(name, ns, prelude, &mut found_traits);
+ self.get_traits_in_module_containing_item(ident, ns, prelude, &mut found_traits);
}
}
}
fn get_traits_in_module_containing_item(&mut self,
- name: Name,
+ ident: Ident,
ns: Namespace,
- module: Module,
+ module: Module<'a>,
found_traits: &mut Vec<TraitCandidate>) {
let mut traits = module.traits.borrow_mut();
if traits.is_none() {
}
for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
- let trait_def_id = binding.def().def_id();
- if self.trait_item_map.contains_key(&(trait_def_id, name, ns)) {
+ let module = binding.module().unwrap();
+ let mut ident = ident;
+ if ident.ctxt.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)
+ .is_ok() {
let import_id = match binding.kind {
NameBindingKind::Import { directive, .. } => {
self.maybe_unused_trait_imports.insert(directive.id);
}
_ => None,
};
+ let trait_def_id = module.def_id().unwrap();
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id });
}
}
}
fn report_shadowing_errors(&mut self) {
- for (name, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
- self.resolve_legacy_scope(scope, name, true);
+ for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
+ self.resolve_legacy_scope(scope, ident, true);
}
let mut reported_errors = FxHashSet();
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
- if self.resolve_legacy_scope(&binding.parent, binding.name, false).is_some() &&
- reported_errors.insert((binding.name, binding.span)) {
- let msg = format!("`{}` is already in scope", binding.name);
+ if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() &&
+ reported_errors.insert((binding.ident, binding.span)) {
+ let msg = format!("`{}` is already in scope", binding.ident);
self.session.struct_span_err(binding.span, &msg)
.note("macro-expanded `macro_rules!`s may not shadow \
existing macros (see RFC 1560)")
pub struct LegacyBinding<'a> {
pub parent: Cell<LegacyScope<'a>>,
- pub name: ast::Name,
+ pub ident: Ident,
def_id: DefId,
pub span: Span,
}
}
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
- let mark = Mark::fresh();
+ let mark = Mark::fresh(Mark::root());
let module = self.module_map[&self.definitions.local_def_id(id)];
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
module: Cell::new(module),
let ident = path.segments[0].identifier;
if ident.name == "$crate" {
path.segments[0].identifier.name = keywords::CrateRoot.name();
- let module = self.0.resolve_crate_var(ident.ctxt, self.1);
+ let module = self.0.resolve_crate_root(ident.ctxt);
if !module.is_local() {
let span = path.segments[0].span;
path.segments.insert(1, match module.kind {
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) {
let invocation = self.invocations[&mark];
- self.collect_def_ids(invocation, expansion);
+ self.collect_def_ids(mark, invocation, expansion);
self.current_module = invocation.module.get();
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
Err(determinacy) => return Err(determinacy),
},
};
+
self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
+ let normal_module_def_id =
+ self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
+ self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id);
+
self.unused_macros.remove(&def.def_id());
- Ok(Some(self.get_macro(def)))
+ let ext = self.get_macro(def);
+ if ext.is_modern() {
+ invoc.expansion_data.mark.set_modern();
+ }
+ Ok(Some(ext))
}
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
return def;
}
- let name = path[0].name;
- let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, name, 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 {
// Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
pub fn resolve_lexical_macro_path_segment(&mut self,
- ident: Ident,
+ mut ident: Ident,
ns: Namespace,
record_used: bool,
path_span: Span)
-> Result<MacroBinding<'a>, Determinacy> {
+ ident = ident.modern();
let mut module = Some(self.current_module);
let mut potential_illegal_shadower = Err(Determinacy::Determined);
let determinacy =
if record_used { Determinacy::Determined } else { Determinacy::Undetermined };
loop {
+ let orig_current_module = self.current_module;
let result = if let Some(module) = module {
+ self.current_module = module; // Lexical resolutions can never be a privacy error.
// Since expanded macros may not shadow the lexical scope and
// globs may not shadow global macros (both enforced below),
// we resolve with restricted shadowing (indicated by the penultimate argument).
- self.resolve_ident_in_module(module, ident, ns, true, record_used, path_span)
- .map(MacroBinding::Modern)
+ self.resolve_ident_in_module_unadjusted(
+ module, ident, ns, true, record_used, path_span,
+ ).map(MacroBinding::Modern)
} else {
self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
.map(MacroBinding::Global)
};
+ self.current_module = orig_current_module;
match result.map(MacroBinding::binding) {
Ok(binding) => {
}
module = match module {
- Some(module) => match module.kind {
- ModuleKind::Block(..) => module.parent,
- ModuleKind::Def(..) => None,
- },
+ Some(module) => self.hygienic_lexical_parent(module, &mut ident.ctxt),
None => return potential_illegal_shadower,
}
}
pub fn resolve_legacy_scope(&mut self,
mut scope: &'a Cell<LegacyScope<'a>>,
- name: Name,
+ ident: Ident,
record_used: bool)
-> Option<MacroBinding<'a>> {
+ let ident = ident.modern();
let mut possible_time_travel = None;
let mut relative_depth: u32 = 0;
let mut binding = None;
scope = &invocation.legacy_scope;
}
LegacyScope::Binding(potential_binding) => {
- if potential_binding.name == name {
+ if potential_binding.ident == ident {
if (!self.use_extern_macros || record_used) && relative_depth > 0 {
self.disallowed_shadowing.push(potential_binding);
}
let binding = if let Some(binding) = binding {
MacroBinding::Legacy(binding)
- } else if let Some(binding) = self.global_macros.get(&name).cloned() {
+ } else if let Some(binding) = self.global_macros.get(&ident.name).cloned() {
if !self.use_extern_macros {
- self.record_use(Ident::with_empty_ctxt(name), MacroNS, binding, DUMMY_SP);
+ self.record_use(ident, MacroNS, binding, DUMMY_SP);
}
MacroBinding::Global(binding)
} else {
if !self.use_extern_macros {
if let Some(scope) = possible_time_travel {
// Check for disallowed shadowing later
- self.lexical_macro_resolutions.push((name, scope));
+ self.lexical_macro_resolutions.push((ident, scope));
}
}
for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() {
let legacy_scope = &self.invocations[&mark].legacy_scope;
- let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
+ let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident, true);
let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span);
match (legacy_resolution, resolution) {
(Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
err: &mut DiagnosticBuilder<'a>, span: Span) {
// First check if this is a locally-defined bang macro.
let suggestion = if let MacroKind::Bang = kind {
- find_best_match_for_name(self.macro_names.iter(), name, None)
+ find_best_match_for_name(self.macro_names.iter().map(|ident| &ident.name), name, None)
} else {
None
// Then check global macros.
}
}
- fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Expansion) {
+ fn collect_def_ids(&mut self,
+ mark: Mark,
+ invocation: &'a InvocationData<'a>,
+ expansion: &Expansion) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
let InvocationData { def_index, const_expr, .. } = *invocation;
});
};
- let mut def_collector = DefCollector::new(&mut self.definitions);
+ let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| {
if const_expr {
});
}
- pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) {
+ pub fn define_macro(&mut self,
+ item: &ast::Item,
+ expansion: Mark,
+ legacy_scope: &mut LegacyScope<'a>) {
self.local_macro_def_scopes.insert(item.id, self.current_module);
let ident = item.ident;
if ident.name == "macro_rules" {
&self.session.features,
item));
self.macro_map.insert(def_id, ext);
- *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
- parent: Cell::new(*legacy_scope), name: ident.name, def_id: def_id, span: item.span,
- }));
- self.macro_names.insert(ident.name);
- if attr::contains_name(&item.attrs, "macro_export") {
- let def = Def::Macro(def_id, MacroKind::Bang);
- self.macro_exports.push(Export { name: ident.name, def: def, span: item.span });
+ let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
+ if def.legacy {
+ let ident = ident.modern();
+ self.macro_names.insert(ident);
+ *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
+ parent: Cell::new(*legacy_scope), ident: ident, def_id: def_id, span: item.span,
+ }));
+ if attr::contains_name(&item.attrs, "macro_export") {
+ let def = Def::Macro(def_id, MacroKind::Bang);
+ self.macro_exports
+ .push(Export { ident: ident.modern(), def: def, span: item.span });
+ } else {
+ self.unused_macros.insert(def_id);
+ }
} else {
- self.unused_macros.insert(def_id);
+ let module = self.current_module;
+ let def = Def::Macro(def_id, MacroKind::Bang);
+ let vis = self.resolve_visibility(&item.vis);
+ self.define(module, ident, MacroNS, (def, vis, item.span, expansion));
}
}
impl<'a> Resolver<'a> {
fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
-> &'a RefCell<NameResolution<'a>> {
- let ident = ident.unhygienize();
- *module.resolutions.borrow_mut().entry((ident, ns))
+ *module.resolutions.borrow_mut().entry((ident.modern(), ns))
.or_insert_with(|| self.arenas.alloc_name_resolution())
}
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
/// Invariant: if `record_used` is `Some`, import resolution must be complete.
- pub fn resolve_ident_in_module(&mut self,
- module: Module<'a>,
- ident: Ident,
- ns: Namespace,
- restricted_shadowing: bool,
- record_used: bool,
- path_span: Span)
- -> Result<&'a NameBinding<'a>, Determinacy> {
+ pub fn resolve_ident_in_module_unadjusted(&mut self,
+ module: Module<'a>,
+ ident: Ident,
+ ns: Namespace,
+ restricted_shadowing: bool,
+ record_used: bool,
+ path_span: Span)
+ -> Result<&'a NameBinding<'a>, Determinacy> {
self.populate_module_if_necessary(module);
let resolution = self.resolution(module, ident, ns)
return Err(Determined);
}
for directive in module.globs.borrow().iter() {
- if self.is_accessible(directive.vis.get()) {
- if let Some(module) = directive.imported_module.get() {
- let result = self.resolve_ident_in_module(module,
- ident,
- ns,
- false,
- false,
- path_span);
- if let Err(Undetermined) = result {
- return Err(Undetermined);
- }
- } else {
- return Err(Undetermined);
- }
+ if !self.is_accessible(directive.vis.get()) {
+ continue
+ }
+ 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()) {
+ Some(Some(def)) => self.current_module = self.macro_def_scope(def),
+ Some(None) => {}
+ None => continue,
+ };
+ let result = self.resolve_ident_in_module_unadjusted(
+ module, ident, ns, false, false, path_span,
+ );
+ self.current_module = orig_current_module;
+ if let Err(Undetermined) = result {
+ return Err(Undetermined);
}
}
// Define `binding` in `module`s glob importers.
for directive in module.glob_importers.borrow_mut().iter() {
- if self.is_accessible_from(binding.vis, directive.parent) {
+ let mut ident = ident.modern();
+ let scope = match ident.ctxt.reverse_glob_adjust(module.expansion,
+ directive.span.ctxt.modern()) {
+ Some(Some(def)) => self.macro_def_scope(def),
+ Some(None) => directive.parent,
+ None => continue,
+ };
+ if self.is_accessible_from(binding.vis, scope) {
let imported_binding = self.import(binding, directive);
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
}
let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| {
resolution.borrow().binding().map(|binding| (ident, binding))
}).collect::<Vec<_>>();
- for ((ident, ns), binding) in bindings {
- if binding.pseudo_vis() == ty::Visibility::Public || self.is_accessible(binding.vis) {
+ for ((mut ident, ns), binding) in bindings {
+ let scope = match ident.ctxt.reverse_glob_adjust(module.expansion,
+ directive.span.ctxt.modern()) {
+ Some(Some(def)) => self.macro_def_scope(def),
+ Some(None) => self.current_module,
+ None => continue,
+ };
+ if self.is_accessible_from(binding.pseudo_vis(), scope) {
let imported_binding = self.import(binding, directive);
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
}
if module as *const _ == self.graph_root as *const _ {
let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
for export in macro_exports.into_iter().rev() {
- if exported_macro_names.insert(export.name, export.span).is_none() {
+ if exported_macro_names.insert(export.ident.modern(), export.span).is_none() {
reexports.push(export);
}
}
};
if binding.vis == ty::Visibility::Public &&
- (binding.is_import() || binding.is_extern_crate()) {
+ (binding.is_import() || binding.is_macro_def()) {
let def = binding.def();
if def != Def::Err {
if !def.def_id().is_local() {
self.session.cstore.export_macros(def.def_id().krate);
}
if let Def::Macro(..) = def {
- if let Some(&span) = exported_macro_names.get(&ident.name) {
+ if let Some(&span) = exported_macro_names.get(&ident.modern()) {
let msg =
format!("a macro named `{}` has already been exported", ident);
self.session.struct_span_err(span, &msg)
.emit();
}
}
- reexports.push(Export { name: ident.name, def: def, span: binding.span });
+ reexports.push(Export { ident: ident.modern(), def: def, span: binding.span });
}
}
if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
sig.push('<');
sig.push_str(&generics.lifetimes.iter()
- .map(|l| l.lifetime.name.to_string())
+ .map(|l| l.lifetime.ident.name.to_string())
.collect::<Vec<_>>()
.join(", "));
if !generics.lifetimes.is_empty() {
Stdcall => llvm::X86StdcallCallConv,
Fastcall => llvm::X86FastcallCallConv,
Vectorcall => llvm::X86_VectorCall,
+ Thiscall => llvm::X86_ThisCall,
C => llvm::CCallConv,
Unadjusted => llvm::CCallConv,
Win64 => llvm::X86_64_Win64,
let llty = type_of::type_of(bcx.ccx, val.ty);
let cast_ptr = bcx.pointercast(dst.llval, llty.ptr_to());
let in_type = val.ty;
- let out_type = dst.ty.to_ty(bcx.tcx());;
+ let out_type = dst.ty.to_ty(bcx.tcx());
let llalign = cmp::min(bcx.ccx.align_of(in_type), bcx.ccx.align_of(out_type));
self.store_operand(bcx, cast_ptr, Some(llalign), val);
}
let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name)
.expect("missing associated type");
let def = Def::AssociatedTy(item.def_id);
- if !tcx.vis_is_accessible_from(item.vis, ref_id) {
+ let def_scope = tcx.adjust(assoc_name, item.container.id(), ref_id).1;
+ if !item.vis.is_accessible_from(def_scope, tcx) {
let msg = format!("{} `{}` is private", def.kind_name(), assoc_name);
tcx.sess.span_err(span, &msg);
}
pub fn prohibit_projection(&self, span: Span) {
let mut err = struct_span_err!(self.tcx().sess, span, E0229,
"associated type bindings are not allowed here");
- err.span_label(span, "associate type not allowed here").emit();
+ err.span_label(span, "associated type not allowed here").emit();
}
// Check a type Path and convert it to a Ty.
/// and return it, or `None`, if no such item was defined there.
pub fn associated_item(&self, def_id: DefId, item_name: ast::Name)
-> Option<ty::AssociatedItem> {
- self.tcx.associated_items(def_id).find(|item| item.name == item_name)
+ let ident = self.tcx.adjust(item_name, def_id, self.body_id).0;
+ self.tcx.associated_items(def_id).find(|item| item.name.to_ident() == ident)
}
}
fn push_inherent_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem,
kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) {
- if self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
+ let is_accessible = if let LookingFor::MethodName(name) = self.looking_for {
+ let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1;
+ item.vis.is_accessible_from(def_scope, self.tcx)
+ } else {
+ true
+ };
+ if is_accessible {
self.inherent_candidates.push(Candidate { xform_self_ty, item, kind, import_id });
} else if self.private_candidate.is_none() {
self.private_candidate = Some(item.def());
fn push_extension_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem,
kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) {
- if self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
+ let is_accessible = if let LookingFor::MethodName(name) = self.looking_for {
+ let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1;
+ item.vis.is_accessible_from(def_scope, self.tcx)
+ } else {
+ true
+ };
+ if is_accessible {
self.extension_candidates.push(Candidate { xform_self_ty, item, kind, import_id });
} else if self.private_candidate.is_none() {
self.private_candidate = Some(item.def());
};
let field_ty = field.ty(tcx, substs);
-
- if tcx.vis_is_accessible_from(field.vis, self.body_id) {
+ let scope = self.tcx.hir.get_module_parent(self.body_id);
+ if field.vis.is_accessible_from(scope, self.tcx) {
if self.is_fn_ty(&field_ty, span) {
err.help(&format!("use `({0}.{1})(...)` if you \
meant to call the function \
match base_t.sty {
ty::TyAdt(base_def, substs) if !base_def.is_enum() => {
debug!("struct named {:?}", base_t);
- if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
+ let (ident, def_scope) =
+ self.tcx.adjust(field.node, base_def.did, self.body_id);
+ let fields = &base_def.struct_variant().fields;
+ if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
- if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
+ if field.vis.is_accessible_from(def_scope, self.tcx) {
autoderef.finalize(lvalue_pref, base);
self.apply_autoderef_adjustment(base.id, autoderefs, base_t);
if !tuple_like { continue }
debug!("tuple struct named {:?}", base_t);
- base_def.struct_variant().fields.get(idx.node).and_then(|field| {
+ let ident = ast::Ident {
+ name: Symbol::intern(&idx.node.to_string()),
+ ctxt: idx.span.ctxt.modern(),
+ };
+ let (ident, def_scope) =
+ self.tcx.adjust_ident(ident, base_def.did, self.body_id);
+ let fields = &base_def.struct_variant().fields;
+ if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
- private_candidate = Some((base_def.did, field_ty));
- if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
+ if field.vis.is_accessible_from(def_scope, self.tcx) {
self.tcx.check_stability(field.did, expr.id, expr.span);
Some(field_ty)
} else {
+ private_candidate = Some((base_def.did, field_ty));
None
}
- })
+ } else {
+ None
+ }
}
ty::TyTuple(ref v, _) => {
tuple_like = true;
let mut remaining_fields = FxHashMap();
for field in &variant.fields {
- remaining_fields.insert(field.name, field);
+ remaining_fields.insert(field.name.to_ident(), field);
}
let mut seen_fields = FxHashMap();
let final_field_type;
let field_type_hint;
- if let Some(v_field) = remaining_fields.remove(&field.name.node) {
+ let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0;
+ if let Some(v_field) = remaining_fields.remove(&ident) {
final_field_type = self.field_ty(field.span, v_field, substs);
field_type_hint = self.field_ty(field.span, v_field, hint_substs);
let mut displayable_field_names = remaining_fields
.keys()
- .map(|x| x.as_str())
+ .map(|ident| ident.name.as_str())
.collect::<Vec<_>>();
displayable_field_names.sort();
let def_id = item.def.def_id();
if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
if !visited.insert(def_id) { continue }
- if let Some(i) = try_inline(cx, item.def, item.name) {
+ if let Some(i) = try_inline(cx, item.def, item.ident.name) {
items.extend(i)
}
}
stable(optopt("", "markdown-playground-url",
"URL to send code snippets to", "URL")),
stable(optflag("", "markdown-no-toc", "don't include table of contents")),
- unstable(optopt("e", "extend-css",
- "to redefine some css rules with a given file to generate doc with your \
- own theme", "PATH")),
+ stable(optopt("e", "extend-css",
+ "To add some CSS rules with a given file to generate doc with your \
+ own theme. However, your theme might break if the rustdoc's generated HTML \
+ changes, so be careful!", "PATH")),
unstable(optmulti("Z", "",
"internal and debugging options (only on nightly build)", "FLAG")),
stable(optopt("", "sysroot", "Override the system root", "PATH")),
use syntax::abi;
use syntax::ast;
use syntax::attr;
-use syntax::tokenstream::TokenStream;
use syntax_pos::Span;
use rustc::hir::map as hir_map;
LoadedMacro::ProcMacro(..) => continue,
};
- let matchers = if let ast::ItemKind::MacroDef(ref tokens) = def.node {
- let tts: Vec<_> = TokenStream::from(tokens.clone()).into_trees().collect();
+ let matchers = if let ast::ItemKind::MacroDef(ref def) = def.node {
+ let tts: Vec<_> = def.stream().into_trees().collect();
tts.chunks(4).map(|arm| arm[0].span()).collect()
} else {
unreachable!()
self.inner.shrink_to_fit()
}
- /// Converts this `OsString` into a boxed `OsStr`.
+ /// Converts this `OsString` into a boxed [`OsStr`].
+ ///
+ /// [`OsStr`]: struct.OsStr.html
///
/// # Examples
///
/// Returns the length of this `OsStr`.
///
/// Note that this does **not** return the number of bytes in this string
- /// as, for example, OS strings on Windows are encoded as a list of `u16`
+ /// as, for example, OS strings on Windows are encoded as a list of [`u16`]
/// rather than a list of bytes. This number is simply useful for passing to
/// other methods like [`OsString::with_capacity`] to avoid reallocations.
///
/// See `OsStr` introduction for more information about encoding.
///
+ /// [`u16`]: ../primitive.u16.html
/// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity
///
/// # Examples
self.inner.inner.len()
}
- /// Converts a `Box<OsStr>` into an `OsString` without copying or allocating.
+ /// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
+ ///
+ /// [`Box`]: ../boxed/struct.Box.html
+ /// [`OsString`]: struct.OsString.html
#[unstable(feature = "into_boxed_os_str", issue = "40380")]
pub fn into_os_string(self: Box<OsStr>) -> OsString {
let inner: Box<Slice> = unsafe { mem::transmute(self) };
use sys_common;
use sys_common::thread_info;
use thread::Thread;
+ #[cfg(not(feature = "backtrace"))]
+ use mem;
sys::init();
sys::args::init(argc, argv);
// Let's run some code!
+ #[cfg(feature = "backtrace")]
let res = panic::catch_unwind(|| {
::sys_common::backtrace::__rust_begin_short_backtrace(main)
});
+ #[cfg(not(feature = "backtrace"))]
+ let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
sys_common::cleanup();
res.is_err()
};
-/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are
- * those of the authors and should not be interpreted as representing official
- * policies, either expressed or implied, of Dmitry Vyukov.
- */
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
//! A mostly lock-free multi-producer, single consumer queue.
//!
-/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are
- * those of the authors and should not be interpreted as representing official
- * policies, either expressed or implied, of Dmitry Vyukov.
- */
-
-// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
//! A single-producer single-consumer concurrent queue
//!
//! concurrently between two threads. This data structure is safe to use and
//! enforces the semantics that there is one pusher and one popper.
+// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+
use alloc::boxed::Box;
use core::ptr;
use core::cell::UnsafeCell;
pub unsafe fn destroy(key: Key) {
keys().remove(&key);
}
+
+#[inline]
+pub fn requires_synchronized_create() -> bool {
+ false
+}
}
unsafe {
thread_info::set(imp::guard::current(), their_thread);
+ #[cfg(feature = "backtrace")]
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
::sys_common::backtrace::__rust_begin_short_backtrace(f)
}));
+ #[cfg(not(feature = "backtrace"))]
+ let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));
*their_packet.get() = Some(try_result);
}
};
/// want to specify the stack size or the name of the thread, use this API
/// instead.
///
+/// As you can see in the signature of `spawn` there are two constraints on
+/// both the closure given to `spawn` and its return value, let's explain them:
+///
+/// - The `'static` constraint means that the closure and its return value
+/// must have a lifetime of the whole program execution. The reason for this
+/// is that threads can `detach` and outlive the lifetime they have been
+/// created in.
+/// Indeed if the thread, and by extension its return value, can outlive their
+/// caller, we need to make sure that they will be valid afterwards, and since
+/// we *can't* know when it will return we need to have them valid as long as
+/// possible, that is until the end of the program, hence the `'static`
+/// lifetime.
+/// - The [`Send`] constraint is because the closure will need to be passed
+/// *by value* from the thread where it is spawned to the new thread. Its
+/// return value will need to be passed from the new thread to the thread
+/// where it is `join`ed.
+/// As a reminder, the [`Send`] marker trait, expresses that it is safe to be
+/// passed from thread to thread. [`Sync`] expresses that it is safe to have a
+/// reference be passed from thread to thread.
+///
/// # Panics
///
/// Panics if the OS fails to create a thread; use [`Builder::spawn`]
/// [`panic`]: ../../std/macro.panic.html
/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
/// [`Builder`]: ../../std/thread/struct.Builder.html
+/// [`Send`]: ../../std/marker/trait.Send.html
+/// [`Sync`]: ../../std/marker/trait.Sync.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
Stdcall,
Fastcall,
Vectorcall,
+ Thiscall,
Aapcs,
Win64,
SysV64,
AbiData {abi: Abi::Stdcall, name: "stdcall", generic: false },
AbiData {abi: Abi::Fastcall, name: "fastcall", generic: false },
AbiData {abi: Abi::Vectorcall, name: "vectorcall", generic: false},
+ AbiData {abi: Abi::Thiscall, name: "thiscall", generic: false},
AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false },
AbiData {abi: Abi::Win64, name: "win64", generic: false },
AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
pub struct Lifetime {
pub id: NodeId,
pub span: Span,
- pub name: Name
+ pub ident: Ident,
}
impl fmt::Debug for Lifetime {
}
}
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct MacroDef {
+ pub tokens: ThinTokenStream,
+ pub legacy: bool,
+}
+
+impl MacroDef {
+ pub fn stream(&self) -> TokenStream {
+ self.tokens.clone().into()
+ }
+}
+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum StrStyle {
/// A regular string, like `"foo"`
Mac(Mac),
/// A macro definition.
- MacroDef(ThinTokenStream),
+ MacroDef(MacroDef),
}
impl ItemKind {
pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T>
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
- let mut parser = Parser::new(sess, self.tokens.clone(), None, false);
+ let mut parser = Parser::new(sess, self.tokens.clone(), None, false, false);
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
(descriptions.len(), ecx.expr_vec(span, descriptions))
});
- let static_ = ecx.lifetime(span, ecx.name_of("'static"));
+ let static_ = ecx.lifetime(span, Ident::from_str("'static"));
let ty_str = ecx.ty_rptr(
span,
ecx.ty_ident(span, ecx.ident_of("str")),
/// An attribute-like procedural macro that derives a builtin trait.
BuiltinDerive(BuiltinDeriveFn),
+
+ /// A declarative macro, e.g. `macro m() {}`.
+ DeclMacro(Box<TTMacroExpander>, Option<Span> /* definition site span */),
}
impl SyntaxExtension {
/// Return which kind of macro calls this syntax extension.
pub fn kind(&self) -> MacroKind {
match *self {
+ SyntaxExtension::DeclMacro(..) |
SyntaxExtension::NormalTT(..) |
SyntaxExtension::IdentTT(..) |
SyntaxExtension::ProcMacro(..) =>
MacroKind::Derive,
}
}
+
+ pub fn is_modern(&self) -> bool {
+ match *self {
+ SyntaxExtension::DeclMacro(..) => true,
+ _ => false,
+ }
+ }
}
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
fn trait_ref(&self, path: ast::Path) -> ast::TraitRef;
fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef;
fn typarambound(&self, path: ast::Path) -> ast::TyParamBound;
- fn lifetime(&self, span: Span, ident: ast::Name) -> ast::Lifetime;
+ fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime;
fn lifetime_def(&self,
span: Span,
- name: ast::Name,
+ ident: ast::Ident,
attrs: Vec<ast::Attribute>,
bounds: Vec<ast::Lifetime>)
-> ast::LifetimeDef;
ast::TraitTyParamBound(self.poly_trait_ref(path.span, path), ast::TraitBoundModifier::None)
}
- fn lifetime(&self, span: Span, name: ast::Name) -> ast::Lifetime {
- ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, name: name }
+ fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime {
+ ast::Lifetime { id: ast::DUMMY_NODE_ID, span: span, ident: ident }
}
fn lifetime_def(&self,
span: Span,
- name: ast::Name,
+ ident: ast::Ident,
attrs: Vec<ast::Attribute>,
bounds: Vec<ast::Lifetime>)
-> ast::LifetimeDef {
ast::LifetimeDef {
attrs: attrs.into(),
- lifetime: self.lifetime(span, name),
+ lifetime: self.lifetime(span, ident),
bounds: bounds
}
}
let derives = derives.entry(invoc.expansion_data.mark).or_insert_with(Vec::new);
for path in &traits {
- let mark = Mark::fresh();
+ let mark = Mark::fresh(self.cx.current_expansion.mark);
derives.push(mark);
let item = match self.cx.resolver.resolve_macro(
Mark::root(), path, MacroKind::Derive, false) {
let path = &mac.node.path;
let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
+ let validate_and_set_expn_info = |def_site_span, allow_internal_unstable| {
+ if ident.name != keywords::Invalid.name() {
+ return Err(format!("macro {}! expects no ident argument, given '{}'", path, ident));
+ }
+ mark.set_expn_info(ExpnInfo {
+ call_site: span,
+ callee: NameAndSpan {
+ format: MacroBang(Symbol::intern(&format!("{}", path))),
+ span: def_site_span,
+ allow_internal_unstable: allow_internal_unstable,
+ },
+ });
+ Ok(())
+ };
+
let marked_tts = noop_fold_tts(mac.node.stream(), &mut Marker(mark));
let opt_expanded = match *ext {
- NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
- if ident.name != keywords::Invalid.name() {
- let msg =
- format!("macro {}! expects no ident argument, given '{}'", path, ident);
+ SyntaxExtension::DeclMacro(ref expand, def_site_span) => {
+ if let Err(msg) = validate_and_set_expn_info(def_site_span, false) {
self.cx.span_err(path.span, &msg);
return kind.dummy(span);
}
+ kind.make_from(expand.expand(self.cx, span, marked_tts))
+ }
- invoc.expansion_data.mark.set_expn_info(ExpnInfo {
- call_site: span,
- callee: NameAndSpan {
- format: MacroBang(Symbol::intern(&format!("{}", path))),
- span: exp_span.map(|(_, s)| s),
- allow_internal_unstable: allow_internal_unstable,
- },
- });
-
+ NormalTT(ref expandfun, def_info, allow_internal_unstable) => {
+ if let Err(msg) = validate_and_set_expn_info(def_info.map(|(_, s)| s),
+ allow_internal_unstable) {
+ self.cx.span_err(path.span, &msg);
+ return kind.dummy(span);
+ }
kind.make_from(expandfun.expand(self.cx, span, marked_tts))
}
impl<'a, 'b> InvocationCollector<'a, 'b> {
fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion {
- let mark = Mark::fresh();
+ let mark = Mark::fresh(self.cx.current_expansion.mark);
self.invocations.push(Invocation {
kind: kind,
expansion_kind: expansion_kind,
Success(())
}
-pub fn parse(sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], directory: Option<Directory>)
+pub fn parse(sess: &ParseSess,
+ tts: TokenStream,
+ ms: &[TokenTree],
+ directory: Option<Directory>,
+ recurse_into_modules: bool)
-> NamedParseResult {
- let mut parser = Parser::new(sess, tts, directory, true);
+ let mut parser = Parser::new(sess, tts, directory, recurse_into_modules, true);
let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), parser.span.lo));
let mut next_eis = Vec::new(); // or proceed normally
path: cx.current_expansion.module.directory.clone(),
ownership: cx.current_expansion.directory_ownership,
};
- let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), false);
+ let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false);
p.root_module_name = cx.current_expansion.module.mod_path.last()
.map(|id| id.name.as_str().to_string());
let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs"));
let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs"));
+ // Parse the macro_rules! invocation
+ let body = match def.node {
+ ast::ItemKind::MacroDef(ref body) => body,
+ _ => unreachable!(),
+ };
+
// The pattern that macro_rules matches.
// The grammar for macro_rules! is:
// $( $lhs:tt => $rhs:tt );+
quoted::TokenTree::Token(DUMMY_SP, token::FatArrow),
quoted::TokenTree::MetaVarDecl(DUMMY_SP, rhs_nm, ast::Ident::from_str("tt")),
],
- separator: Some(token::Semi),
+ separator: Some(if body.legacy { token::Semi } else { token::Comma }),
op: quoted::KleeneOp::OneOrMore,
num_captures: 2,
})),
})),
];
- // Parse the macro_rules! invocation
- let body = match def.node {
- ast::ItemKind::MacroDef(ref body) => body.clone().into(),
- _ => unreachable!(),
- };
- let argument_map = match parse(sess, body, &argument_gram, None) {
+ let argument_map = match parse(sess, body.stream(), &argument_gram, None, true) {
Success(m) => m,
Failure(sp, tok) => {
let s = parse_failure_msg(tok);
valid: valid,
});
- NormalTT(exp,
- Some((def.id, def.span)),
- attr::contains_name(&def.attrs, "allow_internal_unstable"))
+ if body.legacy {
+ let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
+ NormalTT(exp, Some((def.id, def.span)), allow_internal_unstable)
+ } else {
+ SyntaxExtension::DeclMacro(exp, Some(def.span))
+ }
}
fn check_lhs_nt_follows(sess: &ParseSess,
// Allows `impl Trait` in function return types.
(active, conservative_impl_trait, "1.12.0", Some(34511)),
- // Permits numeric fields in struct expressions and patterns.
- (active, relaxed_adts, "1.12.0", Some(35626)),
-
// The `!` type
(active, never_type, "1.13.0", Some(35121)),
// The `unadjusted` ABI. Perma unstable.
(active, abi_unadjusted, "1.16.0", None),
- // Macros 1.1
+ // Procedural macros 2.0.
(active, proc_macro, "1.16.0", Some(38356)),
+ // Declarative macros 2.0 (`macro`).
+ (active, decl_macro, "1.17.0", Some(39412)),
+
// Allows attributes on struct literal fields.
(active, struct_field_attributes, "1.16.0", Some(38814)),
// Allows use of the :vis macro fragment specifier
(active, macro_vis_matcher, "1.18.0", Some(41022)),
+
+ // rustc internal
+ (active, abi_thiscall, "1.19.0", None),
);
declare_features! (
(accepted, windows_subsystem, "1.18.0", Some(37499)),
// Allows `break {expr}` with a value inside `loop`s.
(accepted, loop_break_value, "1.19.0", Some(37339)),
+ // Permits numeric fields in struct expressions and patterns.
+ (accepted, relaxed_adts, "1.19.0", Some(35626)),
);
+
// If you change this, please modify src/doc/unstable-book as well. You must
// move that documentation into the relevant place in the other docs, and
// remove the chapter on the flag.
gate_feature_post!(&self, abi_vectorcall, span,
"vectorcall is experimental and subject to change");
},
+ Abi::Thiscall => {
+ gate_feature_post!(&self, abi_thiscall, span,
+ "thiscall is experimental and subject to change");
+ },
Abi::RustCall => {
gate_feature_post!(&self, unboxed_closures, span,
"rust-call ABI is subject to change");
}
}
-fn starts_with_digit(s: &str) -> bool {
- s.as_bytes().first().cloned().map_or(false, |b| b >= b'0' && b <= b'9')
-}
-
impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_attribute(&mut self, attr: &ast::Attribute) {
if !attr.span.allows_unstable() {
}
}
+ ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
+ let msg = "`macro` is experimental";
+ gate_feature_post!(&self, decl_macro, i.span, msg);
+ }
+
_ => {}
}
ast::ExprKind::InPlace(..) => {
gate_feature_post!(&self, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
}
- ast::ExprKind::Struct(_, ref fields, _) => {
- for field in fields {
- if starts_with_digit(&field.ident.node.name.as_str()) {
- gate_feature_post!(&self, relaxed_adts,
- field.span,
- "numeric fields in struct expressions are unstable");
- }
- }
- }
ast::ExprKind::Lit(ref lit) => {
if let ast::LitKind::Int(_, ref ty) = lit.node {
match *ty {
pattern.span,
"box pattern syntax is experimental");
}
- PatKind::Struct(_, ref fields, _) => {
- for field in fields {
- if starts_with_digit(&field.node.ident.name.as_str()) {
- gate_feature_post!(&self, relaxed_adts,
- field.span,
- "numeric fields in struct patterns are unstable");
- }
- }
- }
PatKind::Range(_, _, RangeEnd::Excluded) => {
gate_feature_post!(&self, exclusive_range_pattern, pattern.span,
"exclusive range pattern syntax is experimental");
// fold::noop_fold_mac(_mac, self)
}
+ fn fold_macro_def(&mut self, def: MacroDef) -> MacroDef {
+ noop_fold_macro_def(def, self)
+ }
+
fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
noop_fold_lifetime(l, self)
}
pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
Spanned {
node: Variant_ {
- name: v.node.name,
+ name: fld.fold_ident(v.node.name),
attrs: fold_attrs(v.node.attrs, fld),
data: fld.fold_variant_data(v.node.data),
disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)),
}
}
+pub fn noop_fold_macro_def<T: Folder>(def: MacroDef, fld: &mut T) -> MacroDef {
+ MacroDef {
+ tokens: fld.fold_tts(def.tokens.into()).into(),
+ legacy: def.legacy,
+ }
+}
+
pub fn noop_fold_meta_list_item<T: Folder>(li: NestedMetaItem, fld: &mut T)
-> NestedMetaItem {
Spanned {
pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
Lifetime {
id: fld.new_id(l.id),
- name: l.name,
+ ident: fld.fold_ident(l.ident),
span: fld.new_span(l.span)
}
}
items.move_flat_map(|item| folder.fold_trait_item(item)),
),
ItemKind::Mac(m) => ItemKind::Mac(folder.fold_mac(m)),
- ItemKind::MacroDef(tts) => ItemKind::MacroDef(folder.fold_tts(tts.into()).into()),
+ ItemKind::MacroDef(def) => ItemKind::MacroDef(folder.fold_macro_def(def)),
}
}
match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
Some(&(ascii_char, ascii_name)) => {
let msg =
- format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not",
+ format!("unicode character '{}' ({}) looks like '{}' ({}), but it's not",
ch, u_name, ascii_char, ascii_name);
err.span_help(span, &msg);
},
// Create a new parser from a source string
pub fn new_parser_from_source_str(sess: &ParseSess, name: String, source: String)
-> Parser {
- filemap_to_parser(sess, sess.codemap().new_filemap(name, source))
+ let mut parser = filemap_to_parser(sess, sess.codemap().new_filemap(name, source));
+ parser.recurse_into_file_modules = false;
+ parser
}
/// Create a new parser, handling errors as appropriate
/// Given stream and the `ParseSess`, produce a parser
pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser {
- Parser::new(sess, stream, None, false)
+ Parser::new(sess, stream, None, true, false)
}
/// Parse a string representing a character literal into its final form.
Err(_) => panic!("could not get snippet"),
}
}
+
+ // This tests that when parsing a string (rather than a file) we don't try
+ // and read in a file for a module declaration and just parse a stub.
+ // See `recurse_into_file_modules` in the parser.
+ #[test]
+ fn out_of_line_mod() {
+ let sess = ParseSess::new(FilePathMapping::empty());
+ let item = parse_item_from_source_str(
+ "foo".to_owned(),
+ "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
+ &sess,
+ ).unwrap().unwrap();
+
+ if let ast::ItemKind::Mod(ref m) = item.node {
+ assert!(m.items.len() == 2);
+ } else {
+ panic!();
+ }
+ }
}
pub obsolete_set: HashSet<ObsoleteSyntax>,
/// Used to determine the path to externally loaded source files
pub directory: Directory,
+ /// Whether to parse sub-modules in other files.
+ pub recurse_into_file_modules: bool,
/// Name of the root module this parser originated from. If `None`, then the
/// name is not known. This does not change while the parser is descending
/// into modules, and sub-parsers have new values for this name.
pub cfg_mods: bool,
}
+
struct TokenCursor {
frame: TokenCursorFrame,
stack: Vec<TokenCursorFrame>,
pub fn new(sess: &'a ParseSess,
tokens: TokenStream,
directory: Option<Directory>,
+ recurse_into_file_modules: bool,
desugar_doc_comments: bool)
-> Self {
let mut parser = Parser {
prev_token_kind: PrevTokenKind::Other,
restrictions: Restrictions::empty(),
obsolete_set: HashSet::new(),
+ recurse_into_file_modules: recurse_into_file_modules,
directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
root_module_name: None,
expected_tokens: Vec::new(),
let tok = parser.next_tok();
parser.token = tok.tok;
parser.span = tok.sp;
+
if let Some(directory) = directory {
parser.directory = directory;
} else if parser.span != syntax_pos::DUMMY_SP {
parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
parser.directory.path.pop();
}
+
parser.process_potential_macro_variable();
parser
}
token::Lifetime(ident) => {
let ident_span = self.span;
self.bump();
- Lifetime { name: ident.name, span: ident_span, id: ast::DUMMY_NODE_ID }
+ Lifetime { ident: ident, span: ident_span, id: ast::DUMMY_NODE_ID }
}
_ => self.span_bug(self.span, "not a lifetime")
}
fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility)
-> PResult<'a, Option<P<Item>>> {
let lo = self.span;
- match self.token {
- token::Ident(ident) if ident.name == "macro_rules" => {
- if self.look_ahead(1, |t| *t == token::Not) {
- let prev_span = self.prev_span;
- self.complain_if_pub_macro(vis, prev_span);
- self.bump();
- self.bump();
+ let (ident, def) = match self.token {
+ token::Ident(ident) if ident.name == keywords::Macro.name() => {
+ self.bump();
+ let ident = self.parse_ident()?;
+ let tokens = if self.check(&token::OpenDelim(token::Brace)) {
+ match self.parse_token_tree() {
+ TokenTree::Delimited(_, ref delimited) => delimited.stream(),
+ _ => unreachable!(),
+ }
+ } else if self.check(&token::OpenDelim(token::Paren)) {
+ let args = self.parse_token_tree();
+ let body = if self.check(&token::OpenDelim(token::Brace)) {
+ self.parse_token_tree()
+ } else {
+ self.unexpected()?;
+ unreachable!()
+ };
+ TokenStream::concat(vec![
+ args.into(),
+ TokenTree::Token(lo.to(self.prev_span), token::FatArrow).into(),
+ body.into(),
+ ])
+ } else {
+ self.unexpected()?;
+ unreachable!()
+ };
+
+ (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
+ }
+ token::Ident(ident) if ident.name == "macro_rules" &&
+ self.look_ahead(1, |t| *t == token::Not) => {
+ let prev_span = self.prev_span;
+ self.complain_if_pub_macro(vis, prev_span);
+ self.bump();
+ self.bump();
+
+ let ident = self.parse_ident()?;
+ let (delim, tokens) = self.expect_delimited_token_tree()?;
+ if delim != token::Brace {
+ if !self.eat(&token::Semi) {
+ let msg = "macros that expand to items must either \
+ be surrounded with braces or followed by a semicolon";
+ self.span_err(self.prev_span, msg);
+ }
}
+
+ (ident, ast::MacroDef { tokens: tokens, legacy: true })
}
_ => return Ok(None),
};
- let id = self.parse_ident()?;
- let (delim, tts) = self.expect_delimited_token_tree()?;
- if delim != token::Brace {
- if !self.eat(&token::Semi) {
- let msg = "macros that expand to items must either be surrounded with braces \
- or followed by a semicolon";
- self.span_err(self.prev_span, msg);
- }
- }
-
let span = lo.to(self.prev_span);
- let kind = ItemKind::MacroDef(tts);
- Ok(Some(self.mk_item(span, id, kind, Visibility::Inherited, attrs.to_owned())))
+ Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec())))
}
fn parse_stmt_without_recovery(&mut self,
mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
let item = self.parse_item_(attrs.clone(), false, true)?;
self.directory.ownership = old_directory_ownership;
+
match item {
Some(i) => Stmt {
id: ast::DUMMY_NODE_ID,
let id = self.parse_ident()?;
if self.check(&token::Semi) {
self.bump();
- if in_cfg {
+ if in_cfg && self.recurse_into_file_modules {
// This mod is in an external file. Let's go get it!
let ModulePathSuccess { path, directory_ownership, warn } =
self.submod_path(id, &outer_attrs, id_span)?;
} else {
let old_directory = self.directory.clone();
self.push_directory(id, &outer_attrs);
+
self.expect(&token::OpenDelim(token::Brace))?;
let mod_inner_lo = self.span;
let attrs = self.parse_inner_attributes()?;
let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
+
self.directory = old_directory;
Ok((id, ItemKind::Mod(module), Some(attrs)))
}
fn submod_path(&mut self,
id: ast::Ident,
outer_attrs: &[ast::Attribute],
- id_sp: Span) -> PResult<'a, ModulePathSuccess> {
+ id_sp: Span)
+ -> PResult<'a, ModulePathSuccess> {
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
return Ok(ModulePathSuccess {
directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
self.print_ident(item.ident)?;
self.cbox(INDENT_UNIT)?;
self.popen()?;
- self.print_tts(tts.clone().into())?;
+ self.print_tts(tts.stream())?;
self.pclose()?;
word(&mut self.s, ";")?;
self.end()?;
lifetime: &ast::Lifetime)
-> io::Result<()>
{
- self.print_name(lifetime.name)
+ self.print_name(lifetime.ident.name)
}
pub fn print_lifetime_bounds(&mut self,
/// call to codemap's `is_internal` check.
/// The expanded code uses the unstable `#[prelude_import]` attribute.
fn ignored_span(sp: Span) -> Span {
- let mark = Mark::fresh();
+ let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
callee: NameAndSpan {
let mut cleaner = EntryPointCleaner { depth: 0 };
let krate = cleaner.fold_crate(krate);
- let mark = Mark::fresh();
+ let mark = Mark::fresh(Mark::root());
let mut cx: TestCtxt = TestCtxt {
sess: sess,
span_diagnostic: sd,
let struct_type = ecx.ty_path(ecx.path(sp, vec![ecx.ident_of("self"),
ecx.ident_of("test"),
ecx.ident_of("TestDescAndFn")]));
- let static_lt = ecx.lifetime(sp, keywords::StaticLifetime.name());
+ let static_lt = ecx.lifetime(sp, keywords::StaticLifetime.ident());
// &'static [self::test::TestDescAndFn]
let static_type = ecx.ty_rptr(sp,
ecx.ty(sp, ast::TyKind::Slice(struct_type)),
path: cx.current_expansion.module.directory.clone(),
ownership: cx.current_expansion.directory_ownership,
};
- macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory))
+ macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true)
}
/// Check if this TokenTree is equal to the other, regardless of span information.
use ast::*;
use syntax_pos::Span;
use codemap::Spanned;
-use tokenstream::ThinTokenStream;
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum FnKind<'a> {
// definition in your trait impl:
// visit::walk_mac(self, _mac)
}
- fn visit_mac_def(&mut self, _mac: &'ast ThinTokenStream, _id: NodeId) {
+ fn visit_mac_def(&mut self, _mac: &'ast MacroDef, _id: NodeId) {
// Nothing to do
}
fn visit_path(&mut self, path: &'ast Path, _id: NodeId) {
}
pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) {
- visitor.visit_name(lifetime.span, lifetime.name);
+ visitor.visit_ident(lifetime.span, lifetime.ident);
}
pub fn walk_lifetime_def<'a, V: Visitor<'a>>(visitor: &mut V, lifetime_def: &'a LifetimeDef) {
fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
match *lt {
- Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
+ Some(s) => Some(cx.lifetime(span, Ident::from_str(s))),
None => None,
}
}
fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
match *lt {
- Some(ref s) => vec![cx.lifetime(span, cx.ident_of(*s).name)],
+ Some(s) => vec![cx.lifetime(span, Ident::from_str(s))],
None => vec![],
}
}
-> Generics {
let lifetimes = self.lifetimes
.iter()
- .map(|&(ref lt, ref bounds)| {
+ .map(|&(lt, ref bounds)| {
let bounds = bounds.iter()
- .map(|b| cx.lifetime(span, cx.ident_of(*b).name))
+ .map(|b| cx.lifetime(span, Ident::from_str(b)))
.collect();
- cx.lifetime_def(span, cx.ident_of(*lt).name, vec![], bounds)
+ cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds)
})
.collect();
let ty_params = self.bounds
respan(span,
match *ptr {
Borrowed(ref lt, mutbl) => {
- let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
+ let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s)));
SelfKind::Region(lt, mutbl)
}
Raw(_) => {
} else { // Avoid instability errors with user defined curstom derives, cc #36316
let mut info = cx.current_expansion.mark.expn_info().unwrap();
info.callee.allow_internal_unstable = true;
- let mark = Mark::fresh();
+ let mark = Mark::fresh(Mark::root());
mark.set_expn_info(info);
span.ctxt = SyntaxContext::empty().apply_mark(mark);
}
// interface.
//
-use syntax::ast;
+use syntax::ast::{self, Ident};
use syntax::ext::base::*;
use syntax::ext::base;
use syntax::ext::build::AstBuilder;
cx.std_path(&["option", "Option", "None"]),
Vec::new(),
vec![cx.ty_rptr(sp,
- cx.ty_ident(sp, cx.ident_of("str")),
+ cx.ty_ident(sp, Ident::from_str("str")),
Some(cx.lifetime(sp,
- cx.ident_of("'static")
- .name)),
+ Ident::from_str("'static"))),
ast::Mutability::Immutable)],
Vec::new()))
}
let sp = piece_ty.span;
let ty = ecx.ty_rptr(sp,
ecx.ty(sp, ast::TyKind::Slice(piece_ty)),
- Some(ecx.lifetime(sp, keywords::StaticLifetime.name())),
+ Some(ecx.lifetime(sp, keywords::StaticLifetime.ident())),
ast::Mutability::Immutable);
let slice = ecx.expr_vec_slice(sp, pieces);
// static instead of const to speed up codegen by not requiring this to be inlined
// First, build up the static array which will become our precompiled
// format "string"
- let static_lifetime = self.ecx.lifetime(self.fmtsp, keywords::StaticLifetime.name());
+ let static_lifetime = self.ecx.lifetime(self.fmtsp, keywords::StaticLifetime.ident());
let piece_ty = self.ecx.ty_rptr(self.fmtsp,
self.ecx.ty_ident(self.fmtsp, self.ecx.ident_of("str")),
Some(static_lifetime),
custom_derives: &[ProcMacroDerive],
custom_attrs: &[ProcMacroDef],
custom_macros: &[ProcMacroDef]) -> P<ast::Item> {
- let mark = Mark::fresh();
+ let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
call_site: DUMMY_SP,
callee: NameAndSpan {
//! DOI=10.1017/S0956796812000093 http://dx.doi.org/10.1017/S0956796812000093
use Span;
-use symbol::Symbol;
+use symbol::{Ident, Symbol};
use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::cell::RefCell;
use std::fmt;
/// A SyntaxContext represents a chain of macro expansions (represented by marks).
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
pub struct SyntaxContext(u32);
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Default)]
pub struct SyntaxContextData {
pub outer_mark: Mark,
pub prev_ctxt: SyntaxContext,
+ pub modern: SyntaxContext,
}
/// A mark is a unique id associated with a macro expansion.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable, RustcDecodable)]
pub struct Mark(u32);
+#[derive(Default)]
+struct MarkData {
+ parent: Mark,
+ modern: bool,
+ expn_info: Option<ExpnInfo>,
+}
+
impl Mark {
- pub fn fresh() -> Self {
+ pub fn fresh(parent: Mark) -> Self {
HygieneData::with(|data| {
- data.marks.push(None);
+ data.marks.push(MarkData { parent: parent, modern: false, expn_info: None });
Mark(data.marks.len() as u32 - 1)
})
}
}
pub fn expn_info(self) -> Option<ExpnInfo> {
- HygieneData::with(|data| data.marks[self.0 as usize].clone())
+ HygieneData::with(|data| data.marks[self.0 as usize].expn_info.clone())
}
pub fn set_expn_info(self, info: ExpnInfo) {
- HygieneData::with(|data| data.marks[self.0 as usize] = Some(info))
+ HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
+ }
+
+ pub fn modern(mut self) -> Mark {
+ HygieneData::with(|data| {
+ loop {
+ if self == Mark::root() || data.marks[self.0 as usize].modern {
+ return self;
+ }
+ self = data.marks[self.0 as usize].parent;
+ }
+ })
+ }
+
+ pub fn is_modern(self) -> bool {
+ HygieneData::with(|data| data.marks[self.0 as usize].modern)
+ }
+
+ pub fn set_modern(self) {
+ HygieneData::with(|data| data.marks[self.0 as usize].modern = true)
+ }
+
+ pub fn is_descendant_of(mut self, ancestor: Mark) -> bool {
+ HygieneData::with(|data| {
+ while self != ancestor {
+ if self == Mark::root() {
+ return false;
+ }
+ self = data.marks[self.0 as usize].parent;
+ }
+ true
+ })
}
}
struct HygieneData {
- marks: Vec<Option<ExpnInfo>>,
+ marks: Vec<MarkData>,
syntax_contexts: Vec<SyntaxContextData>,
markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
+ gensym_to_ctxt: HashMap<Symbol, SyntaxContext>,
}
impl HygieneData {
fn new() -> Self {
HygieneData {
- marks: vec![None],
- syntax_contexts: vec![SyntaxContextData {
- outer_mark: Mark::root(),
- prev_ctxt: SyntaxContext::empty(),
- }],
+ marks: vec![MarkData::default()],
+ syntax_contexts: vec![SyntaxContextData::default()],
markings: HashMap::new(),
+ gensym_to_ctxt: HashMap::new(),
}
}
SyntaxContext(0)
}
- pub fn data(self) -> SyntaxContextData {
- HygieneData::with(|data| data.syntax_contexts[self.0 as usize])
- }
-
/// Extend a syntax context with a given mark
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
- // Applying the same mark twice is a no-op
- let ctxt_data = self.data();
- if mark == ctxt_data.outer_mark {
- return ctxt_data.prev_ctxt;
- }
-
HygieneData::with(|data| {
let syntax_contexts = &mut data.syntax_contexts;
+ let ctxt_data = syntax_contexts[self.0 as usize];
+ if mark == ctxt_data.outer_mark {
+ return ctxt_data.prev_ctxt;
+ }
+
+ let modern = if data.marks[mark.0 as usize].modern {
+ *data.markings.entry((ctxt_data.modern, mark)).or_insert_with(|| {
+ let modern = SyntaxContext(syntax_contexts.len() as u32);
+ syntax_contexts.push(SyntaxContextData {
+ outer_mark: mark,
+ prev_ctxt: ctxt_data.modern,
+ modern: modern,
+ });
+ modern
+ })
+ } else {
+ ctxt_data.modern
+ };
+
*data.markings.entry((self, mark)).or_insert_with(|| {
syntax_contexts.push(SyntaxContextData {
outer_mark: mark,
prev_ctxt: self,
+ modern: modern,
});
SyntaxContext(syntax_contexts.len() as u32 - 1)
})
})
}
+ pub fn remove_mark(&mut self) -> Mark {
+ HygieneData::with(|data| {
+ let outer_mark = data.syntax_contexts[self.0 as usize].outer_mark;
+ *self = data.syntax_contexts[self.0 as usize].prev_ctxt;
+ outer_mark
+ })
+ }
+
+ /// Adjust this context for resolution in a scope created by the given expansion.
+ /// For example, consider the following three resolutions of `f`:
+ /// ```rust
+ /// mod foo { pub fn f() {} } // `f`'s `SyntaxContext` is empty.
+ /// m!(f);
+ /// macro m($f:ident) {
+ /// mod bar {
+ /// pub fn f() {} // `f`'s `SyntaxContext` has a single `Mark` from `m`.
+ /// pub fn $f() {} // `$f`'s `SyntaxContext` is empty.
+ /// }
+ /// foo::f(); // `f`'s `SyntaxContext` has a single `Mark` from `m`
+ /// //^ Since `mod foo` is outside this expansion, `adjust` removes the mark from `f`,
+ /// //| and it resolves to `::foo::f`.
+ /// bar::f(); // `f`'s `SyntaxContext` has a single `Mark` from `m`
+ /// //^ Since `mod bar` not outside this expansion, `adjust` does not change `f`,
+ /// //| and it resolves to `::bar::f`.
+ /// bar::$f(); // `f`'s `SyntaxContext` is empty.
+ /// //^ Since `mod bar` is not outside this expansion, `adjust` does not change `$f`,
+ /// //| and it resolves to `::bar::$f`.
+ /// }
+ /// ```
+ /// This returns the expansion whose definition scope we use to privacy check the resolution,
+ /// or `None` if we privacy check as usual (i.e. not w.r.t. a macro definition scope).
+ pub fn adjust(&mut self, expansion: Mark) -> Option<Mark> {
+ let mut scope = None;
+ while !expansion.is_descendant_of(self.outer()) {
+ scope = Some(self.remove_mark());
+ }
+ scope
+ }
+
+ /// Adjust this context for resolution in a scope created by the given expansion
+ /// via a glob import with the given `SyntaxContext`.
+ /// For example,
+ /// ```rust
+ /// m!(f);
+ /// macro m($i:ident) {
+ /// mod foo {
+ /// pub fn f() {} // `f`'s `SyntaxContext` has a single `Mark` from `m`.
+ /// pub fn $i() {} // `$i`'s `SyntaxContext` is empty.
+ /// }
+ /// n(f);
+ /// macro n($j:ident) {
+ /// use foo::*;
+ /// f(); // `f`'s `SyntaxContext` has a mark from `m` and a mark from `n`
+ /// //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::f`.
+ /// $i(); // `$i`'s `SyntaxContext` has a mark from `n`
+ /// //^ `glob_adjust` removes the mark from `n`, so this resolves to `foo::$i`.
+ /// $j(); // `$j`'s `SyntaxContext` has a mark from `m`
+ /// //^ This cannot be glob-adjusted, so this is a resolution error.
+ /// }
+ /// }
+ /// ```
+ /// This returns `None` if the context cannot be glob-adjusted.
+ /// Otherwise, it returns the scope to use when privacy checking (see `adjust` for details).
+ pub fn glob_adjust(&mut self, expansion: Mark, mut glob_ctxt: SyntaxContext)
+ -> Option<Option<Mark>> {
+ let mut scope = None;
+ while !expansion.is_descendant_of(glob_ctxt.outer()) {
+ scope = Some(glob_ctxt.remove_mark());
+ if self.remove_mark() != scope.unwrap() {
+ return None;
+ }
+ }
+ if self.adjust(expansion).is_some() {
+ return None;
+ }
+ Some(scope)
+ }
+
+ /// Undo `glob_adjust` if possible:
+ /// ```rust
+ /// if let Some(privacy_checking_scope) = self.reverse_glob_adjust(expansion, glob_ctxt) {
+ /// assert!(self.glob_adjust(expansion, glob_ctxt) == Some(privacy_checking_scope));
+ /// }
+ /// ```
+ pub fn reverse_glob_adjust(&mut self, expansion: Mark, mut glob_ctxt: SyntaxContext)
+ -> Option<Option<Mark>> {
+ if self.adjust(expansion).is_some() {
+ return None;
+ }
+
+ let mut marks = Vec::new();
+ while !expansion.is_descendant_of(glob_ctxt.outer()) {
+ marks.push(glob_ctxt.remove_mark());
+ }
+
+ let scope = marks.last().cloned();
+ while let Some(mark) = marks.pop() {
+ *self = self.apply_mark(mark);
+ }
+ Some(scope)
+ }
+
+ pub fn modern(self) -> SyntaxContext {
+ HygieneData::with(|data| data.syntax_contexts[self.0 as usize].modern)
+ }
+
pub fn outer(self) -> Mark {
HygieneData::with(|data| data.syntax_contexts[self.0 as usize].outer_mark)
}
Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene
}
}
+
+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);
+ gensym
+ })
+ }
+
+ pub fn to_ident(self) -> Ident {
+ HygieneData::with(|data| {
+ match data.gensym_to_ctxt.get(&self) {
+ Some(&ctxt) => Ident { name: self.interned(), ctxt: ctxt },
+ None => Ident::with_empty_ctxt(self),
+ }
+ })
+ }
+}
Ident::with_empty_ctxt(Symbol::intern(string))
}
- pub fn unhygienize(self) -> Ident {
- Ident { name: self.name, ctxt: SyntaxContext::empty() }
+ pub fn modern(self) -> Ident {
+ Ident { name: self.name, ctxt: self.ctxt.modern() }
}
}
impl Encodable for Ident {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- self.name.encode(s)
+ if self.ctxt.modern() == SyntaxContext::empty() {
+ s.emit_str(&self.name.as_str())
+ } else { // FIXME(jseyfried) intercrate hygiene
+ let mut string = "#".to_owned();
+ string.push_str(&self.name.as_str());
+ s.emit_str(&string)
+ }
}
}
impl Decodable for Ident {
fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
- Ok(Ident::with_empty_ctxt(Symbol::decode(d)?))
+ let string = d.read_str()?;
+ Ok(if !string.starts_with('#') {
+ Ident::from_str(&string)
+ } else { // FIXME(jseyfried) intercrate hygiene
+ Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
+ })
}
}
with_interner(|interner| interner.intern(string))
}
+ pub fn interned(self) -> Self {
+ with_interner(|interner| interner.interned(self))
+ }
+
/// gensym's a new usize, using the current interner.
pub fn gensym(string: &str) -> Self {
with_interner(|interner| interner.gensym(string))
}
+ pub fn gensymed(self) -> Self {
+ with_interner(|interner| interner.gensymed(self))
+ }
+
pub fn as_str(self) -> InternedString {
with_interner(|interner| unsafe {
InternedString {
pub struct Interner {
names: HashMap<Box<str>, Symbol>,
strings: Vec<Box<str>>,
+ gensyms: Vec<Symbol>,
}
impl Interner {
name
}
+ pub fn interned(&self, symbol: Symbol) -> Symbol {
+ if (symbol.0 as usize) < self.strings.len() {
+ symbol
+ } else {
+ self.interned(self.gensyms[(!0 - symbol.0) as usize])
+ }
+ }
+
fn gensym(&mut self, string: &str) -> Symbol {
- let gensym = Symbol(self.strings.len() as u32);
- // leave out of `names` to avoid colliding
- self.strings.push(string.to_string().into_boxed_str());
- gensym
+ let symbol = self.intern(string);
+ self.gensymed(symbol)
}
- pub fn get(&self, name: Symbol) -> &str {
- &self.strings[name.0 as usize]
+ fn gensymed(&mut self, symbol: Symbol) -> Symbol {
+ self.gensyms.push(symbol);
+ Symbol(!0 - self.gensyms.len() as u32 + 1)
+ }
+
+ pub fn get(&self, symbol: Symbol) -> &str {
+ match self.strings.get(symbol.0 as usize) {
+ Some(ref string) => string,
+ None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
+ }
}
}
assert_eq!(i.intern("cat"), Symbol(1));
// dog is still at zero
assert_eq!(i.intern("dog"), Symbol(0));
- // gensym gets 3
- assert_eq!(i.gensym("zebra"), Symbol(2));
+ assert_eq!(i.gensym("zebra"), Symbol(4294967295));
// gensym of same string gets new number :
- assert_eq!(i.gensym("zebra"), Symbol(3));
+ assert_eq!(i.gensym("zebra"), Symbol(4294967294));
// gensym of *existing* string gets new number:
- assert_eq!(i.gensym("dog"), Symbol(4));
+ assert_eq!(i.gensym("dog"), Symbol(4294967293));
}
}
// except according to those terms.
// aux-build:attr_proc_macro.rs
-// gate-test-proc_macro
#![feature(use_extern_macros)]
extern crate attr_proc_macro;
fn main() {
let _ = Foo;
-}
\ No newline at end of file
+}
fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
//~^ ERROR associated type bindings are not allowed here [E0229]
-//~| NOTE associate type not allowed here
+//~| NOTE associated type not allowed here
fn main() {
}
// gate-test-intrinsics
// gate-test-platform_intrinsics
// gate-test-abi_vectorcall
+// gate-test-abi_thiscall
// gate-test-abi_ptx
// gate-test-abi_x86_interrupt
extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
+extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change
// Methods in trait definition
trait Tr {
extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
+ extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change
extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change
extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental
extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
+ extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change
}
struct S;
extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
+ extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change
}
// Methods in inherent impl
extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
+ extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change
}
// Function pointer types
type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
+type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change
// Foreign modules
extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental
extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change
extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
+extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change
fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro m() {} //~ ERROR `macro` is experimental (see issue #39412)
+//~| HELP add #![feature(decl_macro)] to the crate attributes to enable
+
+fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// gate-test-global_asm
-
global_asm!(""); //~ ERROR `global_asm!` is not stable
fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+mod foo {
+ pub fn f() {}
+}
+
+mod bar {
+ pub fn g() {}
+}
+
+macro m($($t:tt)*) {
+ $($t)*
+ use foo::*;
+ f();
+ g(); //~ ERROR cannot find function `g` in this scope
+}
+
+fn main() {
+ m! {
+ use bar::*;
+ g();
+ f(); //~ ERROR cannot find function `f` in this scope
+ }
+}
+
+n!(f);
+macro n($i:ident) {
+ mod foo {
+ pub fn $i() -> u32 { 0 }
+ pub fn f() {}
+
+ mod test {
+ use super::*;
+ fn g() {
+ let _: u32 = $i();
+ let _: () = f();
+ }
+ }
+
+ macro n($j:ident) {
+ mod test {
+ use super::*;
+ fn g() {
+ let _: u32 = $i();
+ let _: () = f();
+ $j();
+ }
+ }
+ }
+
+ n!(f);
+ mod test2 {
+ super::n! {
+ f //~ ERROR cannot find function `f` in this scope
+ }
+ }
+ }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+macro n($foo:ident, $S:ident, $i:ident, $m:ident) {
+ mod $foo {
+ #[derive(Default)]
+ pub struct $S { $i: u32 }
+ pub macro $m($e:expr) { $e.$i }
+ }
+}
+
+n!(foo, S, i, m);
+
+fn main() {
+ use foo::{S, m};
+ S::default().i; //~ ERROR field `i` of struct `foo::S` is private
+ m!(S::default()); // ok
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+mod foo {
+ pub macro m() { Vec::new(); ().clone() }
+ fn f() { ::bar::m!(); }
+}
+
+#[no_implicit_prelude]
+mod bar {
+ pub macro m() {
+ Vec::new(); //~ ERROR failed to resolve
+ ().clone() //~ ERROR no method named `clone` found
+ }
+ fn f() { ::foo::m!(); }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+mod foo {
+ fn f() {}
+
+ pub macro m($e:expr) {
+ f();
+ self::f();
+ ::foo::f();
+ $e
+ }
+}
+
+fn main() {
+ foo::m!(
+ foo::f() //~ ERROR `f` is private
+ );
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+mod foo {
+ pub trait T {
+ fn f(&self) {}
+ }
+ impl T for () {}
+}
+
+mod bar {
+ use foo::*;
+ pub macro m() { ().f() }
+ fn f() { ::baz::m!(); }
+}
+
+mod baz {
+ pub macro m() { ().f() } //~ ERROR no method named `f` found for type `()` in the current scope
+ fn f() { ::bar::m!(); }
+}
+
+fn main() {}
fn f<T>(self)
where T<Bogus = Foo>: A;
//~^ ERROR associated type bindings are not allowed here [E0229]
- //~| NOTE associate type not allowed here
+ //~| NOTE associated type not allowed here
}
fn main() {}
fn f<T>(self)
where T<Bogus = Self::AlsoBogus>: A;
//~^ ERROR associated type bindings are not allowed here [E0229]
- //~| NOTE associate type not allowed here
+ //~| NOTE associated type not allowed here
}
fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(conservative_impl_trait, rustc_attrs)]
+
+fn _test() -> impl Default { }
+
+#[rustc_error]
+fn main() { } //~ ERROR compilation successful
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_fn)]
+
+const fn x() {
+ let t = true; //~ ERROR blocks in constant functions are limited to items and tail expressions
+ let x = || t; //~ ERROR blocks in constant functions are limited to items and tail expressions
+}
+
+fn main() {}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z unstable-options --unpretty=mir
+
+use std::path::MAIN_SEPARATOR;
+
+fn main() {
+ let mut foo : String = "hello".to_string();
+ foo.push(MAIN_SEPARATOR);
+ println!("{}", foo);
+ let x: () = 0; //~ ERROR: mismatched types
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts, rustc_attrs)]
+#![allow(warnings)]
+
+trait MyTrait {
+ const MY_CONST: &'static str;
+}
+
+macro_rules! my_macro {
+ () => {
+ struct MyStruct;
+
+ impl MyTrait for MyStruct {
+ const MY_CONST: &'static str = stringify!(abc);
+ }
+ }
+}
+
+my_macro!();
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+fn _test(ref _p: str) {}
+
+#[rustc_error]
+fn main() { } //~ ERROR compilation successful
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo {
+ Bar { bar: Bar, id: usize }
+}
+
+enum Bar {
+ A, B, C, D, E, F
+}
+
+fn test(f: Foo) {
+ match f {
+ //~^ ERROR non-exhaustive patterns
+ //~| patterns
+ Foo::Bar { bar: Bar::A, .. } => (),
+ Foo::Bar { bar: Bar::B, .. } => (),
+ }
+}
+
+fn main() {}
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// gate-test-relaxed_adts
-
-struct S(u8);
-
-fn main() {
- let s = S{0: 10}; //~ ERROR numeric fields in struct expressions are unstable
- match s {
- S{0: a, ..} => {} //~ ERROR numeric fields in struct patterns are unstable
- }
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(relaxed_adts)]
-
struct S(u8, u16);
fn main() {
#![feature(untagged_unions)]
-union U {
+union U1 {
a: u8
}
+union U2 {
+ a: String
+}
+
+union U3<T> {
+ a: T
+}
+
+union U4<T: Copy> {
+ a: T
+}
+
+fn generic_noncopy<T: Default>() {
+ let mut u3 = U3 { a: T::default() };
+ u3.a = T::default(); //~ ERROR assignment to non-`Copy` union field requires unsafe
+}
+
+fn generic_copy<T: Copy + Default>() {
+ let mut u3 = U3 { a: T::default() };
+ u3.a = T::default(); // OK
+ let mut u4 = U4 { a: T::default() };
+ u4.a = T::default(); // OK
+}
+
fn main() {
- let mut u = U { a: 10 }; // OK
- let a = u.a; //~ ERROR access to union field requires unsafe function or block
- u.a = 11; //~ ERROR access to union field requires unsafe function or block
- let U { a } = u; //~ ERROR matching on union field requires unsafe function or block
- if let U { a: 12 } = u {} //~ ERROR matching on union field requires unsafe function or block
- // let U { .. } = u; // OK
+ let mut u1 = U1 { a: 10 }; // OK
+ let a = u1.a; //~ ERROR access to union field requires unsafe
+ u1.a = 11; // OK
+ let U1 { a } = u1; //~ ERROR matching on union field requires unsafe
+ if let U1 { a: 12 } = u1 {} //~ ERROR matching on union field requires unsafe
+ // let U1 { .. } = u1; // OK
+
+ let mut u2 = U2 { a: String::from("old") }; // OK
+ u2.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field requires unsafe
+ let mut u3 = U3 { a: 0 }; // OK
+ u3.a = 1; // OK
+ let mut u3 = U3 { a: String::from("old") }; // OK
+ u3.a = String::from("new"); //~ ERROR assignment to non-`Copy` union field requires unsafe
}
// except according to those terms.
// compile-flags: -Z parse-only
-// ignore-tidy-linelength
fn main() {
let y = 0;
//~^ ERROR unknown start of token: \u{37e}
- //~^^ HELP unicode character ';' (Greek Question Mark) looks much like ';' (Semicolon), but it's not
+ //~^^ HELP unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it's not
}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[repr(u8)]
+pub enum E {
+ B = 1 as u8,
+}
\ No newline at end of file
--- /dev/null
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-arm
+// ignore-aarch64
+
+#![feature(abi_thiscall)]
+
+trait A {
+ extern "thiscall" fn test1(i: i32);
+}
+
+struct S;
+
+impl A for S {
+ extern "thiscall" fn test1(i: i32) {
+ assert_eq!(i, 1);
+ }
+}
+
+extern "thiscall" fn test2(i: i32) {
+ assert_eq!(i, 2);
+}
+
+fn main() {
+ <S as A>::test1(1);
+ test2(2);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+macro m($t:ty, $e:expr) {
+ mod foo {
+ #[allow(unused)]
+ struct S;
+ pub(super) fn f(_: $t) {}
+ }
+ foo::f($e);
+}
+
+fn main() {
+ struct S;
+ m!(S, S);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+pub mod foo {
+ pub use self::bar::m;
+ mod bar {
+ fn f() -> u32 { 1 }
+ pub macro m() {
+ f();
+ }
+ }
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+mod foo {
+ struct S { x: u32 }
+ struct T(u32);
+
+ pub macro m($S:ident, $x:ident) {{
+ struct $S {
+ $x: u32,
+ x: i32,
+ }
+
+ let s = S { x: 0 };
+ let _ = s.x;
+
+ let t = T(0);
+ let _ = t.0;
+
+ let s = $S { $x: 0, x: 1 };
+ assert_eq!((s.$x, s.x), (0, 1));
+ s
+ }}
+}
+
+fn main() {
+ let s = foo::m!(S, x);
+ assert_eq!(s.x, 0);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+mod foo {
+ struct S;
+ impl S {
+ fn f(&self) {}
+ }
+
+ pub macro m() {
+ let _: () = S.f();
+ }
+}
+
+struct S;
+
+macro m($f:ident) {
+ impl S {
+ fn f(&self) -> u32 { 0 }
+ fn $f(&self) -> i32 { 0 }
+ }
+ fn f() {
+ let _: u32 = S.f();
+ let _: i32 = S.$f();
+ }
+}
+
+m!(f);
+
+fn main() {
+ let _: i32 = S.f();
+ foo::m!();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+// aux-build:intercrate.rs
+
+#![feature(decl_macro)]
+
+extern crate intercrate;
+
+fn main() {
+ assert_eq!(intercrate::foo::m!(), 1);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+pub macro m($foo:ident, $f:ident, $e:expr) {
+ mod foo {
+ pub fn f() -> u32 { 0 }
+ pub fn $f() -> u64 { 0 }
+ }
+
+ mod $foo {
+ pub fn f() -> i32 { 0 }
+ pub fn $f() -> i64 { 0 }
+ }
+
+ let _: u32 = foo::f();
+ let _: u64 = foo::$f();
+ let _: i32 = $foo::f();
+ let _: i64 = $foo::$f();
+ let _: i64 = $e;
+}
+
+fn main() {
+ m!(foo, f, foo::f());
+ let _: i64 = foo::f();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+mod bar {
+ mod baz {
+ pub fn f() {}
+ }
+
+ pub macro m($f:ident) {
+ baz::f();
+ let _: i32 = $f();
+ {
+ fn $f() -> u32 { 0 }
+ let _: u32 = $f();
+ }
+ }
+}
+
+fn main() {
+ fn f() -> i32 { 0 }
+ bar::m!(f);
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+macro m($T:ident, $f:ident) {
+ pub trait $T {
+ fn f(&self) -> u32 { 0 }
+ fn $f(&self) -> i32 { 0 }
+ }
+ impl $T for () {}
+
+ let _: u32 = ().f();
+ let _: i32 = ().$f();
+}
+
+fn main() {
+ m!(T, f);
+ let _: i32 = ().f();
+}
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty pretty-printing is unhygienic
+
+#![feature(decl_macro)]
+
+macro m($T:ident) {
+ fn f<T, $T>(t: T, t2: $T) -> (T, $T) {
+ (t, t2)
+ }
+}
+
+m!(T);
+
+fn main() {}
fn foo<F: FnOnce()>(_f: F) { }
fn main() {
- let mut var = Vec::new();;
+ let mut var = Vec::new();
foo(move|| {
var.push(1);
});
--- /dev/null
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue_42007_s.rs
+
+extern crate issue_42007_s;
+
+enum I {
+ E(issue_42007_s::E),
+}
+
+fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(relaxed_adts)]
-
struct S(u8, u16);
fn main() {
short.next();
assert_eq!(long.size_hint(), (255, Some(255)));
assert_eq!(short.size_hint(), (0, Some(0)));
- assert_eq!(short, RangeInclusive::Empty { at: 42 });
+ assert_eq!(short, 1...0);
assert_eq!(long.len(), 255);
assert_eq!(short.len(), 0);
for i in 3...251 {
assert_eq!(long.next(), Some(i));
}
- assert_eq!(long, RangeInclusive::Empty { at: 251 });
+ assert_eq!(long, 1...0);
// check underflow
let mut narrow = 1...0;
assert_eq!(narrow.next_back(), None);
- assert_eq!(narrow, RangeInclusive::Empty { at: 0 });
+ assert_eq!(narrow, 1...0);
let mut zero = 0u8...0;
assert_eq!(zero.next_back(), Some(0));
assert_eq!(zero.next_back(), None);
- assert_eq!(zero, RangeInclusive::Empty { at: 0 });
+ assert_eq!(zero, 1...0);
let mut high = 255u8...255;
assert_eq!(high.next_back(), Some(255));
assert_eq!(high.next_back(), None);
- assert_eq!(high, RangeInclusive::Empty { at: 255 });
+ assert_eq!(high, 1...0);
// what happens if you have a nonsense range?
let mut nonsense = 10...5;
assert_eq!(nonsense.next(), None);
- assert_eq!(nonsense, RangeInclusive::Empty { at: 10 });
+ assert_eq!(nonsense, 10...5);
// output
assert_eq!(format!("{:?}", 0...10), "0...10");
assert_eq!(format!("{:?}", ...10), "...10");
- assert_eq!(format!("{:?}", long), "[empty range @ 251]");
+ assert_eq!(format!("{:?}", long), "1...0");
}
15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable
| ^ cannot move out of captured outer variable in an `Fn` closure
-error: aborting due to previous error
+error: aborting due to previous error(s)
21 | y.into_iter();
| ^ cannot move out of captured outer variable in an `Fn` closure
-error: aborting due to previous error
+error: aborting due to previous error(s)
49 | match Some(A) {
| ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
15 | impl C { fn f() {} }
| --------- other definition for `f`
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | unsafe impl Send for &'static Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
100 | let y = &mut x;
| ^ cannot borrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
101 | }
| - first borrow ends here
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
| | second mutable borrow occurs here
| first mutable borrow occurs here
-error: aborting due to previous error
+error: aborting due to previous error(s)
43 | fn baz(&self) {}
| ---------------- other definition for `baz`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
| | hint: to prevent move, use `ref _s` or `ref mut _s`
| cannot move out of here
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | \tbar;
| \t^^^ not found in this scope
-error: aborting due to previous error
+error: aborting due to previous error(s)
-error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́`
+error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́`
--> $DIR/unicode.rs:11:8
|
11 | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | x + 1;
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
-error: aborting due to previous error
+error: aborting due to previous error(s)
22 | | }
| |_____^ impl has extra requirement `'a: 'b`
-error: aborting due to previous error
+error: aborting due to previous error(s)
22 | fn foo() where 'a: 'b { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `fn(&E, F) -> F`
found type `fn(&E, G) -> G`
-error: aborting due to previous error
+error: aborting due to previous error(s)
25 | fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } //~ ERROR E0276
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync`
-error: aborting due to previous error
+error: aborting due to previous error(s)
76 | fn method<G: Getter<usize>>(&self) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter<usize>`
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
26 | | }
| |_____^ impl has extra requirement `U: Iterator<B>`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | z: fn() -> Foo + 'a,
| ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses?
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
<Bar as Foo<i32>>
<Bar as Foo<u8>>
-error: aborting due to previous error
+error: aborting due to previous error(s)
<Bar as Foo<u8>>
and 2 others
-error: aborting due to previous error
+error: aborting due to previous error(s)
23 | (&mut self).bar();
| ^^^^ cannot borrow mutably
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
| try removing `&mut` here
| cannot reborrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
| try removing `&mut` here
| cannot reborrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
30 | s.x += 1;
| ^^^^^^^^ cannot mutably borrow immutable field
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
17 | f.baz;
| ^^^ did you mean `bar`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | f.zz;
| ^^ unknown field
-error: aborting due to previous error
+error: aborting due to previous error(s)
| try removing `&mut` here
| cannot reborrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | use Foo1;
| ^^^^ no `Foo1` in the root
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
27 | self.s.push('x');
| ^^^^^^ assignment into an immutable reference
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | self.s.push('x');
| ^^^^^^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | self.s.push('x');
| ^^^^^^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | f.s.push('x');
| ^^^ assignment into an immutable reference
-error: aborting due to previous error
+error: aborting due to previous error(s)
58 | *x.0 = 1;
| ^^^^^^^^ cannot borrow as mutable
-error: aborting due to 12 previous errors
+error: aborting due to previous error(s)
and 2 others
= note: required by `Foo::bar`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: method `xxx` has no receiver
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
13 | buf.iter_mut();
| ^^^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `!` instead of `~` if you meant to perform bitwise negation
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: required because it appears within the type `A`
= note: required by `is_send`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `&Bottom`
found type `&Top`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: the trait cannot require that `Self : Sized`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
43 | | }
| |_^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
= note: if you intended to print `}`, you can escape it using `}}`
= note: this error originates in a macro outside of the current crate
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= help: closure was moved because it only implements `FnOnce`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `impl Foo` (i32)
found type `impl Foo` (u32)
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
11 | pub mod baz;
| ^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
| help: consider using a reference instead `&f.v[0]`
| cannot move out of indexed content
-error: aborting due to previous error
+error: aborting due to previous error(s)
| | ...and here (use `ref b` or `ref mut b`)
| hint: to prevent move, use `ref a` or `ref mut a`
-error: aborting due to previous error
+error: aborting due to previous error(s)
note: candidate #1 is defined in the trait `issue_41652_b::Tr`
= help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | | }
| |_^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | | }
| |_^
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | | }
| |_^
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | x.push(z);
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | let a: &mut Vec<Ref<i32>> = x;
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | let a: &mut Vec<Ref<i32>> = x;
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `-D non-snake-case` implied by `-D bad-style`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `-F non-snake-case` implied by `-F bad-style`
-error: aborting due to previous error
+error: aborting due to previous error(s)
28 | #![warn(bad_style)]
| ^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
22 | break 22
| ^^^^^^^^ can only break with a value inside `loop`
-error: aborting due to previous error
+error: aborting due to previous error(s)
12 | println!(3 + 4);
| ^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
= help: `$NAME` should be written as `{NAME}`
= note: shell formatting not supported; see the documentation for `std::fmt`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
56 | let _ = fake_anon_field_expr!();
| ----------------------- in this macro invocation
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
28 | call_nested_expr_sum!();
| ------------------------ in this macro invocation
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
28 | myprintln!("{}");
| ----------------- in this macro invocation
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `fn(&Bar)`
found type `fn(&mut Bar)`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `foo`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `&{integer}`
found type `{integer}`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `X<X<_, std::string::String>, _>`
found type `X<X<_, {integer}>, _>`
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
|
= help: the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
81 | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
| ^
-error: aborting due to 34 previous errors
+error: aborting due to previous error(s)
| |
| expected closure that takes 2 arguments
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
= note: required by `baz`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
21 | const fn f() -> u32 { 22 }
| ^^^^^ trait fns cannot be const
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `apply`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `()`
found type `*mut Trait`
-error: aborting due to previous error
+error: aborting due to previous error(s)
38 | cast!(2);
| --------- in this macro invocation
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `bool` (type parameter)
found type `bool` (bool)
-error: aborting due to previous error
+error: aborting due to previous error(s)
| requires `for<'r> std::ops::FnOnce<(&'r &str,)>`
| expected &str, found str
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
34 | fn ugh(&[bar]: &u32) {
| ^^^^^ pattern cannot match with input type `u32`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
= note: expected type `u32`
found type `()`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: the method `unwrap` exists but the following trait bounds were not satisfied:
`Foo : std::fmt::Debug`
-error: aborting due to previous error
+error: aborting due to previous error(s)
45 | let ans = s("burma", "shave");
| ^^^^^^^^^^^^^^^^ expected 1 parameter
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
= note: expected type `std::boxed::Box<Foo + std::marker::Send + 'static>`
found type `std::boxed::Box<Foo + 'static>`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `fn(&mut Bar, &mut Bar)`
found type `fn(&mut Bar, &Bar)`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `call_it`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
21 | match proto {
| ^^^^^ pattern `C(QA)` not covered
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: `Type` from trait: `type Type;`
= note: `method` from trait: `fn(&Self, std::string::String) -> <Self as m1::X>::Type`
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | foo();
| ^^^ cannot infer type for `X`
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | pub(crate) () fn foo() {}
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | pub(crate) () foo: usize,
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | pub (.) fn afn() {}
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
33 | pub (in x) non_parent_invalid: usize,
| ^
-error: aborting due to 5 previous errors
+error: aborting due to previous error(s)
13 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^^
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
25 | let x: [usize; 2] = [22, return];
| ^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
36 | *{return; &mut i} = 22;
| ^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
13 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
28 | bar(return);
| ^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^^
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
31 | Foo.bar(return);
| ^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
40 | let x = Foo { a: 22, b: return };
| ^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
25 | let x: (usize, usize) = (2, return);
| ^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
18 | let x: ! = ! { return; 22 };
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
= note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types
= note: this error is the result of a recent bug fix; for more information, see issue #33685 <https://github.com/rust-lang/rust/issues/33685>
-error: aborting due to previous error
+error: aborting due to previous error(s)
help: possible candidate is found in another module, you can import it into scope
| use namespaced_enums::Foo::C;
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 25 previous errors
+error: aborting due to previous error(s)
| use std::io::Result;
| use std::thread::Result;
-error: aborting due to previous error
+error: aborting due to previous error(s)
help: possible candidate is found in another module, you can import it into scope
| use SomeEnum::E;
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | let f = Foo::Variant(42);
| ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
22 | let homura = issue_19452_aux::Homura::Madoka;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`?
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^^^^^
= note: ...which then again requires processing `<impl at $DIR/issue-23305.rs:15:1: 15:20>`, completing the cycle.
-error: aborting due to previous error
+error: aborting due to previous error(s)
122 | self += 1;
| ^^^^ `self` value is only available in methods with `self` parameter
-error: aborting due to 17 previous errors
+error: aborting due to previous error(s)
11 | fn foo(_: Self) {
| ^^^^ `Self` is only available in traits and impls
-error: aborting due to previous error
+error: aborting due to previous error(s)
20 | let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar`
| ^^^ not a value
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: method `bar` has no receiver
-error: aborting due to previous error
+error: aborting due to previous error(s)
| did you mean `handle`?
| did you mean `Handle { /* fields */ }`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
= help: the trait `std::marker::Sized` is not implemented for `I + 'static`
= note: all local variables must have a statically known size
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | let _m = Monster(); //~ ERROR expected function, found struct `Monster`
| ^^^^^^^ did you mean `Monster { /* fields */ }`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
32 | let b: m::first = m::second; // Misspelled item in module.
| ^^^^^^ did you mean `Second`?
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
45 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
| ^^^^^^^^^^^^^^^
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
52 | method;
| ^^^^^^ did you mean `self.method(...)`?
-error: aborting due to 9 previous errors
+error: aborting due to previous error(s)
12 | assert(true);
| ^^^^^^ did you mean `assert!(...)`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
38 | method();
| ^^^^^^ did you mean `self.method(...)`?
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 10 previous errors
+error: aborting due to previous error(s)
14 | if foo {
| ^^^ not found in this scope
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `()`
found type `std::result::Result<bool, std::io::Error>`
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | foo(bar(;
| ^^^ not found in this scope
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
| did you mean `S`?
| did you mean `A { /* fields */ }`?
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
| did you mean `self.cx`?
| `self` value is only available in methods with `self` parameter
-error: aborting due to previous error
+error: aborting due to previous error(s)
18 | impl Foo for Bar {}
| ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
-error: aborting due to previous error
+error: aborting due to previous error(s)
15 | let c = f(2, 3); //~ ERROR E0057
| ^^^^ expected 1 parameter
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
-error: aborting due to previous error
+error: aborting due to previous error(s)
31 | Bar(&'a mut bool),
| ------------- this field does not implement `Copy`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
27 | const F : Foo = Foo { a : 0 };
| ^^^^^^^^^^^^^ constants cannot have destructors
-error: aborting due to previous error
+error: aborting due to previous error(s)
11 | #[inline(unknown)] //~ ERROR E0535
| ^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
11 | #[cfg(not())] //~ ERROR E0536
| ^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
11 | #[cfg(unknown())] //~ ERROR E0537
| ^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
143 | *x.y_mut() = 3; //~ ERROR cannot borrow
| ^ cannot borrow as mutable
-error: aborting due to 10 previous errors
+error: aborting due to previous error(s)
63 | **x = 3; //~ ERROR cannot borrow
| ^^ cannot borrow as mutable
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
72 | foo(f);
| ^ cannot move out of captured outer variable in an `FnMut` closure
-error: aborting due to 5 previous errors
+error: aborting due to previous error(s)
27 | x.h(); //~ ERROR cannot borrow
| ^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | x.push(format!("this is broken"));
| ^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
29 | x.borrowed_mut(); //~ ERROR cannot borrow
| ^ cannot borrow as mutable
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `_`
found type `std::boxed::Box<_>`
-error: aborting due to 5 previous errors
+error: aborting due to previous error(s)
| |
| `*a` dropped here while still borrowed
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
|
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
23 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
| |
| `y` dropped here while still borrowed
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: `Item` from trait: `type Item;`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `Output` from trait: `type Output;`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `Target` from trait: `type Target;`
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | #![deny(warnings)]
| ^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `&Self`
found type `&SomeType`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `Tr::C`
-error: aborting due to previous error
+error: aborting due to previous error(s)
found type `std::string::String`
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
19 | bar(1, 2, 3);
| ^^^^^^^ expected 2 parameters
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^
= help: to disambiguate the method call, write `F::foo(a)` instead
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: an implementation of `std::ops::Add` might be missing for `World`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
= help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `is_str`, perhaps you need to implement it:
= help: candidate #1: `ManyImplTrait`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
44 | | }
| |_^
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `()`
found type `[closure@$DIR/move-closure.rs:15:17: 15:27]`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: the trait `std::ops::Add<()>` is not implemented for `u32`
-error: aborting due to previous error
+error: aborting due to previous error(s)
25 | a.push_str("foo");
| ^ cannot borrow as mutable
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
20 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | pub(crate) bar: u8,
| ^^^^^^^^^^^^^^^^^^ field already declared
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
21 | }
| - borrowed value needs to live until here
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
20 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
23 | }
| - temporary value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
| |
| `tmp0` dropped here while still borrowed
-error: aborting due to previous error
+error: aborting due to previous error(s)
23 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
24 | x += 1; //~ ERROR cannot assign
| ^^^^^^ assignment to borrowed `x` occurs here
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
30 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
35 | }
| - borrowed value needs to live until here
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
44 | }
| - borrowed value needs to live until here
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
49 | drop(y); //~ ERROR cannot move out
| ^ move out of `y` occurs here
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
19 | }
| - temporary value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | println!("☃{}", tup[0]);
| ^^^^^^ help: to access tuple elements, use `tup.0`
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | fn homura<T: Deref<Trget = i32>>(_: T) {}
| ^^^^^^^^^^^ associated type `Trget` not found
-error: aborting due to previous error
+error: aborting due to previous error(s)
18 | println!("Hello {}", fob);
| ^^^ did you mean `foo`?
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
33 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: type must satisfy the static lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `(o.closure)(...)` if you meant to call the function stored in the `closure` field
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `((*self.container).f3)(...)` if you meant to call the function stored in the `f3` field
-error: aborting due to 11 previous errors
+error: aborting due to previous error(s)
|
= help: use `(demo.example)(...)` if you meant to call the function stored in the `example` field
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr` field
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
26 | let dog_age = dog.dog_age();
| ^^^^^^^ private field, not a method
-error: aborting due to previous error
+error: aborting due to previous error(s)
| | unexpected token
| help: try parenthesizing the first index `((1, (2, 3)).1).1`
-error: aborting due to previous error
+error: aborting due to previous error(s)
15 | FAIL
| ^^^^ expected one of `!` or `::` here
-error: aborting due to previous error
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
37 | ignored_pat!() => (), //~ NOTE caused by the macro expansion here
| ^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
19 | FAIL
| ^^^^ expected one of `!` or `::` here
-error: aborting due to previous error
+error: aborting due to previous error(s)
| |
| consider giving `x` a type
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | [];
| ^^ cannot infer type for `[_; 0]`
-error: aborting due to previous error
+error: aborting due to previous error(s)
21 | | }
| |_^ cannot infer type for `&'a T`
-error: aborting due to previous error
+error: aborting due to previous error(s)
12 | let x = |_| { };
| ^ consider giving this closure parameter a type
-error: aborting due to previous error
+error: aborting due to previous error(s)
-Subproject commit 397359840ecad02d5fe69b2a0cf328e98235ffea
+Subproject commit 9fcdbb44fec18d10c086b6aba8143bc06a199761
}
let filen_underscore = filename.replace("-","_").replace(".rs","");
- test_filen_gate(&filen_underscore, &mut features);
+ let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features);
contents.truncate(0);
t!(t!(File::open(&file), &file).read_to_string(&mut contents));
},
None => continue,
};
- let found_feature = features.get_mut(feature_name)
- .map(|v| { v.has_gate_test = true; () })
- .is_some();
-
- let found_lib_feature = features.get_mut(feature_name)
- .map(|v| { v.has_gate_test = true; () })
- .is_some();
-
- if !(found_feature || found_lib_feature) {
- err(&format!("gate-test test found referencing a nonexistent feature '{}'",
- feature_name));
+ match features.get_mut(feature_name) {
+ Some(f) => {
+ if filename_is_gate_test {
+ err(&format!("The file is already marked as gate test \
+ through its name, no need for a \
+ 'gate-test-{}' comment",
+ feature_name));
+ }
+ f.has_gate_test = true;
+ }
+ None => {
+ err(&format!("gate-test test found referencing a nonexistent feature '{}'",
+ feature_name));
+ }
}
}
});
}
});
lib_features
-}
\ No newline at end of file
+}