Auto merge of #48806 - alexcrichton:rollup, r=alexcrichton
Rollup of 9 pull requests - Successful merges: #48511, #48549, #48618, #48624, #48651, #48698, #48778, #48787, #48802 - Failed merges: #48669, #48710
This commit is contained in:
commit
5430c0c5c0
88 changed files with 831 additions and 924 deletions
12
appveyor.yml
12
appveyor.yml
|
@ -19,12 +19,18 @@ environment:
|
|||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
|
||||
SCRIPT: python x.py test
|
||||
- MSYS_BITS: 32
|
||||
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i686-pc-windows-msvc
|
||||
SCRIPT: python x.py test --host i686-pc-windows-msvc --target i686-pc-windows-msvc
|
||||
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
|
||||
SCRIPT: python x.py test --exclude src/test/run-pass --exclude src/test/compile-fail
|
||||
- MSYS_BITS: 32
|
||||
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
|
||||
SCRIPT: python x.py test src/test/run-pass src/test/compile-fail
|
||||
|
||||
# MSVC aux tests
|
||||
- MSYS_BITS: 64
|
||||
RUST_CHECK_TARGET: check-aux
|
||||
RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
|
||||
- MSYS_BITS: 64
|
||||
SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
|
||||
|
||||
# MSVC tools tests
|
||||
|
|
58
src/Cargo.lock
generated
58
src/Cargo.lock
generated
|
@ -398,10 +398,12 @@ dependencies = [
|
|||
"getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -926,12 +928,11 @@ dependencies = [
|
|||
"clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xz2 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1185,6 +1186,15 @@ dependencies = [
|
|||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"socket2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miri"
|
||||
version = "0.1.0"
|
||||
|
@ -1511,15 +1521,6 @@ dependencies = [
|
|||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.0.0"
|
||||
|
@ -2225,15 +2226,6 @@ dependencies = [
|
|||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "0.1.3"
|
||||
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)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.2"
|
||||
|
@ -2779,16 +2771,6 @@ name = "void"
|
|||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "1.0.7"
|
||||
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)",
|
||||
"same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.0.1"
|
||||
|
@ -2971,6 +2953,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
|
||||
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
||||
"checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d"
|
||||
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
|
||||
"checksum nibble_vec 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62e678237a4c70c5f2b917cefd7d080dfbf800421f06e8a59d4e28ef5130fd9e"
|
||||
"checksum nix 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "47e49f6982987135c5e9620ab317623e723bd06738fd85377e8d55f57c8b6487"
|
||||
|
@ -3004,7 +2987,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum racer 2.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "034f1c4528581c40a60e96875467c03315868084e08ff4ceb46a00f7be3b16b4"
|
||||
"checksum radix_trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "211c49b6a9995cac0fd1dd9ca60b42cf3a51e151a12eb954b3a9e75513426ee8"
|
||||
"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"
|
||||
"checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf"
|
||||
"checksum rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "485541959c8ecc49865526fe6c4de9653dd6e60d829d6edf0be228167b60372d"
|
||||
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
|
||||
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
|
||||
|
@ -3027,7 +3009,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0"
|
||||
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
|
||||
"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
|
||||
"checksum schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "acece75e0f987c48863a6c792ec8b7d6c4177d4a027f8ccc72f849794f437016"
|
||||
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
|
||||
|
@ -3085,7 +3066,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b"
|
||||
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
|
||||
"checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
|
|
|
@ -16,6 +16,12 @@ Q := @
|
|||
BOOTSTRAP_ARGS :=
|
||||
endif
|
||||
|
||||
ifdef EXCLUDE_CARGO
|
||||
AUX_ARGS := src/tools/cargo src/tools/cargotest
|
||||
else
|
||||
AUX_ARGS :=
|
||||
endif
|
||||
|
||||
BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
|
||||
|
||||
all:
|
||||
|
@ -52,14 +58,13 @@ check:
|
|||
$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
|
||||
check-aux:
|
||||
$(Q)$(BOOTSTRAP) test \
|
||||
src/tools/cargo \
|
||||
src/tools/cargotest \
|
||||
src/test/pretty \
|
||||
src/test/run-pass/pretty \
|
||||
src/test/run-fail/pretty \
|
||||
src/test/run-pass-valgrind/pretty \
|
||||
src/test/run-pass-fulldeps/pretty \
|
||||
src/test/run-fail-fulldeps/pretty \
|
||||
$(AUX_ARGS) \
|
||||
$(BOOTSTRAP_ARGS)
|
||||
check-bootstrap:
|
||||
$(Q)$(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap_test.py
|
||||
|
|
|
@ -104,7 +104,7 @@ else
|
|||
travis_fold start "make-$1"
|
||||
travis_time_start
|
||||
echo "make -j $ncpus $1"
|
||||
make -j $ncpus "$1"
|
||||
make -j $ncpus $1
|
||||
local retval=$?
|
||||
travis_fold end "make-$1"
|
||||
travis_time_finish
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2013 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.
|
||||
|
||||
# This creates the tables used for distributions implemented using the
|
||||
# ziggurat algorithm in `rand::distributions;`. They are
|
||||
# (basically) the tables as used in the ZIGNOR variant (Doornik 2005).
|
||||
# They are changed rarely, so the generated file should be checked in
|
||||
# to git.
|
||||
#
|
||||
# It creates 3 tables: X as in the paper, F which is f(x_i), and
|
||||
# F_DIFF which is f(x_i) - f(x_{i-1}). The latter two are just cached
|
||||
# values which is not done in that paper (but is done in other
|
||||
# variants). Note that the adZigR table is unnecessary because of
|
||||
# algebra.
|
||||
#
|
||||
# It is designed to be compatible with Python 2 and 3.
|
||||
|
||||
from math import exp, sqrt, log, floor
|
||||
import random
|
||||
|
||||
# The order should match the return value of `tables`
|
||||
TABLE_NAMES = ['X', 'F']
|
||||
|
||||
# The actual length of the table is 1 more, to stop
|
||||
# index-out-of-bounds errors. This should match the bitwise operation
|
||||
# to find `i` in `zigurrat` in `libstd/rand/mod.rs`. Also the *_R and
|
||||
# *_V constants below depend on this value.
|
||||
TABLE_LEN = 256
|
||||
|
||||
# equivalent to `zigNorInit` in Doornik2005, but generalised to any
|
||||
# distribution. r = dR, v = dV, f = probability density function,
|
||||
# f_inv = inverse of f
|
||||
def tables(r, v, f, f_inv):
|
||||
# compute the x_i
|
||||
xvec = [0]*(TABLE_LEN+1)
|
||||
|
||||
xvec[0] = v / f(r)
|
||||
xvec[1] = r
|
||||
|
||||
for i in range(2, TABLE_LEN):
|
||||
last = xvec[i-1]
|
||||
xvec[i] = f_inv(v / last + f(last))
|
||||
|
||||
# cache the f's
|
||||
fvec = [0]*(TABLE_LEN+1)
|
||||
for i in range(TABLE_LEN+1):
|
||||
fvec[i] = f(xvec[i])
|
||||
|
||||
return xvec, fvec
|
||||
|
||||
# Distributions
|
||||
# N(0, 1)
|
||||
def norm_f(x):
|
||||
return exp(-x*x/2.0)
|
||||
def norm_f_inv(y):
|
||||
return sqrt(-2.0*log(y))
|
||||
|
||||
NORM_R = 3.6541528853610088
|
||||
NORM_V = 0.00492867323399
|
||||
|
||||
NORM = tables(NORM_R, NORM_V,
|
||||
norm_f, norm_f_inv)
|
||||
|
||||
# Exp(1)
|
||||
def exp_f(x):
|
||||
return exp(-x)
|
||||
def exp_f_inv(y):
|
||||
return -log(y)
|
||||
|
||||
EXP_R = 7.69711747013104972
|
||||
EXP_V = 0.0039496598225815571993
|
||||
|
||||
EXP = tables(EXP_R, EXP_V,
|
||||
exp_f, exp_f_inv)
|
||||
|
||||
|
||||
# Output the tables/constants/types
|
||||
|
||||
def render_static(name, type, value):
|
||||
# no space or
|
||||
return 'pub static %s: %s =%s;\n' % (name, type, value)
|
||||
|
||||
# static `name`: [`type`, .. `len(values)`] =
|
||||
# [values[0], ..., values[3],
|
||||
# values[4], ..., values[7],
|
||||
# ... ];
|
||||
def render_table(name, values):
|
||||
rows = []
|
||||
# 4 values on each row
|
||||
for i in range(0, len(values), 4):
|
||||
row = values[i:i+4]
|
||||
rows.append(', '.join('%.18f' % f for f in row))
|
||||
|
||||
rendered = '\n [%s]' % ',\n '.join(rows)
|
||||
return render_static(name, '[f64, .. %d]' % len(values), rendered)
|
||||
|
||||
|
||||
with open('ziggurat_tables.rs', 'w') as f:
|
||||
f.write('''// Copyright 2013 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.
|
||||
|
||||
// Tables for distributions which are sampled using the ziggurat
|
||||
// algorithm. Autogenerated by `ziggurat_tables.py`.
|
||||
|
||||
pub type ZigTable = &\'static [f64, .. %d];
|
||||
''' % (TABLE_LEN + 1))
|
||||
for name, tables, r in [('NORM', NORM, NORM_R),
|
||||
('EXP', EXP, EXP_R)]:
|
||||
f.write(render_static('ZIG_%s_R' % name, 'f64', ' %.18f' % r))
|
||||
for (tabname, table) in zip(TABLE_NAMES, tables):
|
||||
f.write(render_table('ZIG_%s_%s' % (name, tabname), table))
|
|
@ -829,14 +829,13 @@ impl<'a, T: Clone> Option<&'a mut T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(option_ref_mut_cloned)]
|
||||
/// let mut x = 12;
|
||||
/// let opt_x = Some(&mut x);
|
||||
/// assert_eq!(opt_x, Some(&mut 12));
|
||||
/// let cloned = opt_x.cloned();
|
||||
/// assert_eq!(cloned, Some(12));
|
||||
/// ```
|
||||
#[unstable(feature = "option_ref_mut_cloned", issue = "43738")]
|
||||
#[stable(since = "1.26.0", feature = "option_ref_mut_cloned")]
|
||||
pub fn cloned(self) -> Option<T> {
|
||||
self.map(|t| t.clone())
|
||||
}
|
||||
|
|
|
@ -559,6 +559,7 @@ define_dep_nodes!( <'tcx>
|
|||
[] IsReachableNonGeneric(DefId),
|
||||
[] IsMirAvailable(DefId),
|
||||
[] ItemAttrs(DefId),
|
||||
[] TransFnAttrs(DefId),
|
||||
[] FnArgNames(DefId),
|
||||
[] DylibDepFormats(CrateNum),
|
||||
[] IsPanicRuntime(CrateNum),
|
||||
|
@ -626,8 +627,6 @@ define_dep_nodes!( <'tcx>
|
|||
[input] AllCrateNums,
|
||||
[] ExportedSymbols(CrateNum),
|
||||
[eval_always] CollectAndPartitionTranslationItems,
|
||||
[] ExportName(DefId),
|
||||
[] ContainsExternIndicator(DefId),
|
||||
[] IsTranslatedItem(DefId),
|
||||
[] CodegenUnit(InternedString),
|
||||
[] CompileCodegenUnit(InternedString),
|
||||
|
@ -637,7 +636,6 @@ define_dep_nodes!( <'tcx>
|
|||
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
|
||||
|
||||
[input] TargetFeaturesWhitelist,
|
||||
[] TargetFeaturesEnabled(DefId),
|
||||
|
||||
[] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ struct CheckAttrVisitor<'a, 'tcx: 'a> {
|
|||
impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
|
||||
/// Check any attribute.
|
||||
fn check_attributes(&self, item: &hir::Item, target: Target) {
|
||||
self.tcx.target_features_enabled(self.tcx.hir.local_def_id(item.id));
|
||||
self.tcx.trans_fn_attrs(self.tcx.hir.local_def_id(item.id));
|
||||
|
||||
for attr in &item.attrs {
|
||||
if let Some(name) = attr.name() {
|
||||
|
|
|
@ -30,12 +30,14 @@ pub use self::Visibility::{Public, Inherited};
|
|||
use hir::def::Def;
|
||||
use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
|
||||
use util::nodemap::{NodeMap, FxHashSet};
|
||||
use mir::mono::Linkage;
|
||||
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax::codemap::{self, Spanned};
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
|
||||
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
|
||||
use syntax::attr::InlineAttr;
|
||||
use syntax::ext::hygiene::SyntaxContext;
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::{Symbol, keywords};
|
||||
|
@ -2210,3 +2212,51 @@ pub type GlobMap = NodeMap<FxHashSet<Name>>;
|
|||
pub fn provide(providers: &mut Providers) {
|
||||
providers.describe_def = map::describe_def;
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Hash)]
|
||||
pub struct TransFnAttrs {
|
||||
pub flags: TransFnAttrFlags,
|
||||
pub inline: InlineAttr,
|
||||
pub export_name: Option<Symbol>,
|
||||
pub target_features: Vec<Symbol>,
|
||||
pub linkage: Option<Linkage>,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
pub struct TransFnAttrFlags: u8 {
|
||||
const COLD = 0b0000_0001;
|
||||
const ALLOCATOR = 0b0000_0010;
|
||||
const UNWIND = 0b0000_0100;
|
||||
const RUSTC_ALLOCATOR_NOUNWIND = 0b0000_1000;
|
||||
const NAKED = 0b0001_0000;
|
||||
const NO_MANGLE = 0b0010_0000;
|
||||
const RUSTC_STD_INTERNAL_SYMBOL = 0b0100_0000;
|
||||
}
|
||||
}
|
||||
|
||||
impl TransFnAttrs {
|
||||
pub fn new() -> TransFnAttrs {
|
||||
TransFnAttrs {
|
||||
flags: TransFnAttrFlags::empty(),
|
||||
inline: InlineAttr::None,
|
||||
export_name: None,
|
||||
target_features: vec![],
|
||||
linkage: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// True if `#[inline]` or `#[inline(always)]` is present.
|
||||
pub fn requests_inline(&self) -> bool {
|
||||
match self.inline {
|
||||
InlineAttr::Hint | InlineAttr::Always => true,
|
||||
InlineAttr::None | InlineAttr::Never => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// True if `#[no_mangle]` or `#[export_name(...)]` is present.
|
||||
pub fn contains_extern_indicator(&self) -> bool {
|
||||
self.flags.contains(TransFnAttrFlags::NO_MANGLE) || self.export_name.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
|
|||
StableHasher, StableHasherResult};
|
||||
use std::mem;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
|
||||
impl<'gcx> HashStable<StableHashingContext<'gcx>> for DefId {
|
||||
#[inline]
|
||||
|
@ -1138,6 +1139,43 @@ impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for hir::TraitCandidate {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrs
|
||||
{
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'hir>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
let hir::TransFnAttrs {
|
||||
flags,
|
||||
inline,
|
||||
export_name,
|
||||
ref target_features,
|
||||
linkage,
|
||||
} = *self;
|
||||
|
||||
flags.hash_stable(hcx, hasher);
|
||||
inline.hash_stable(hcx, hasher);
|
||||
export_name.hash_stable(hcx, hasher);
|
||||
target_features.hash_stable(hcx, hasher);
|
||||
linkage.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::TransFnAttrFlags
|
||||
{
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'hir>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
self.bits().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'hir> HashStable<StableHashingContext<'hir>> for attr::InlineAttr {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'hir>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
mem::discriminant(self).hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct hir::Freevar {
|
||||
def,
|
||||
|
|
|
@ -244,7 +244,6 @@ impl_stable_hash_for!(enum ty::Visibility {
|
|||
|
||||
impl_stable_hash_for!(struct ty::TraitRef<'tcx> { def_id, substs });
|
||||
impl_stable_hash_for!(struct ty::TraitPredicate<'tcx> { trait_ref });
|
||||
impl_stable_hash_for!(tuple_struct ty::EquatePredicate<'tcx> { t1, t2 });
|
||||
impl_stable_hash_for!(struct ty::SubtypePredicate<'tcx> { a_is_expected, a, b });
|
||||
|
||||
impl<'gcx, A, B> HashStable<StableHashingContext<'gcx>>
|
||||
|
@ -274,9 +273,6 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::Predicate<'gcx> {
|
|||
ty::Predicate::Trait(ref pred) => {
|
||||
pred.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::Predicate::Equate(ref pred) => {
|
||||
pred.hash_stable(hcx, hasher);
|
||||
}
|
||||
ty::Predicate::Subtype(ref pred) => {
|
||||
pred.hash_stable(hcx, hasher);
|
||||
}
|
||||
|
|
|
@ -1280,7 +1280,6 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
}),
|
||||
IfExpression => Error0308("if and else have incompatible types"),
|
||||
IfExpressionWithNoElse => Error0317("if may be missing an else clause"),
|
||||
EquatePredicate => Error0308("equality predicate not satisfied"),
|
||||
MainFunctionType => Error0580("main function has wrong type"),
|
||||
StartFunctionType => Error0308("start function has wrong type"),
|
||||
IntrinsicType => Error0308("intrinsic has wrong type"),
|
||||
|
@ -1309,7 +1308,6 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
},
|
||||
IfExpression => "if and else have compatible types",
|
||||
IfExpressionWithNoElse => "if missing an else returns ()",
|
||||
EquatePredicate => "equality where clause is satisfied",
|
||||
MainFunctionType => "`main` function has the correct type",
|
||||
StartFunctionType => "`start` function has the correct type",
|
||||
IntrinsicType => "intrinsic has the correct type",
|
||||
|
|
|
@ -943,23 +943,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.borrow_region_constraints().make_subregion(origin, a, b);
|
||||
}
|
||||
|
||||
pub fn equality_predicate(&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
predicate: &ty::PolyEquatePredicate<'tcx>)
|
||||
-> InferResult<'tcx, ()>
|
||||
{
|
||||
self.commit_if_ok(|snapshot| {
|
||||
let (ty::EquatePredicate(a, b), skol_map) =
|
||||
self.skolemize_late_bound_regions(predicate, snapshot);
|
||||
let cause_span = cause.span;
|
||||
let eqty_ok = self.at(cause, param_env).eq(b, a)?;
|
||||
self.leak_check(false, cause_span, &skol_map, snapshot)?;
|
||||
self.pop_skolemized(skol_map, snapshot);
|
||||
Ok(eqty_ok.unit())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn subtype_predicate(&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
|
|
@ -117,7 +117,6 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
assert!(!obligation.has_escaping_regions());
|
||||
match obligation.predicate {
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
|
@ -204,7 +203,6 @@ pub fn explicit_outlives_bounds<'tcx>(
|
|||
.filter_map(move |predicate| match predicate {
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
|
|
|
@ -36,13 +36,12 @@ use session::search_paths::PathKind;
|
|||
use std::any::Any;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use rustc_data_structures::owning_ref::ErasedBoxRef;
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
use rustc_back::target::Target;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::sync::{MetadataRef, Lrc};
|
||||
|
||||
pub use self::NativeLibraryKind::*;
|
||||
|
||||
|
@ -186,11 +185,11 @@ pub trait MetadataLoader {
|
|||
fn get_rlib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String>;
|
||||
-> Result<MetadataRef, String>;
|
||||
fn get_dylib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String>;
|
||||
-> Result<MetadataRef, String>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
// makes all other generics or inline functions that it references
|
||||
// reachable as well.
|
||||
|
||||
use hir::TransFnAttrs;
|
||||
use hir::map as hir_map;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{DefId, CrateNum};
|
||||
|
@ -43,8 +44,8 @@ fn generics_require_inlining(generics: &hir::Generics) -> bool {
|
|||
// Returns true if the given item must be inlined because it may be
|
||||
// monomorphized or it was marked with `#[inline]`. This will only return
|
||||
// true for functions.
|
||||
fn item_might_be_inlined(item: &hir::Item) -> bool {
|
||||
if attr::requests_inline(&item.attrs) {
|
||||
fn item_might_be_inlined(item: &hir::Item, attrs: TransFnAttrs) -> bool {
|
||||
if attrs.requests_inline() {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -60,14 +61,15 @@ fn item_might_be_inlined(item: &hir::Item) -> bool {
|
|||
fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_item: &hir::ImplItem,
|
||||
impl_src: DefId) -> bool {
|
||||
if attr::requests_inline(&impl_item.attrs) ||
|
||||
let trans_fn_attrs = tcx.trans_fn_attrs(impl_item.hir_id.owner_def_id());
|
||||
if trans_fn_attrs.requests_inline() ||
|
||||
generics_require_inlining(&impl_item.generics) {
|
||||
return true
|
||||
}
|
||||
if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) {
|
||||
match tcx.hir.find(impl_node_id) {
|
||||
Some(hir_map::NodeItem(item)) =>
|
||||
item_might_be_inlined(&item),
|
||||
item_might_be_inlined(&item, trans_fn_attrs),
|
||||
Some(..) | None =>
|
||||
span_bug!(impl_item.span, "impl did is not an item")
|
||||
}
|
||||
|
@ -160,7 +162,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
match self.tcx.hir.find(node_id) {
|
||||
Some(hir_map::NodeItem(item)) => {
|
||||
match item.node {
|
||||
hir::ItemFn(..) => item_might_be_inlined(&item),
|
||||
hir::ItemFn(..) =>
|
||||
item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -176,8 +179,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
match impl_item.node {
|
||||
hir::ImplItemKind::Const(..) => true,
|
||||
hir::ImplItemKind::Method(..) => {
|
||||
let attrs = self.tcx.trans_fn_attrs(def_id);
|
||||
if generics_require_inlining(&impl_item.generics) ||
|
||||
attr::requests_inline(&impl_item.attrs) {
|
||||
attrs.requests_inline() {
|
||||
true
|
||||
} else {
|
||||
let impl_did = self.tcx
|
||||
|
@ -229,7 +233,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
false
|
||||
};
|
||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||
let is_extern = self.tcx.contains_extern_indicator(def_id);
|
||||
let is_extern = self.tcx.trans_fn_attrs(def_id).contains_extern_indicator();
|
||||
if reachable || is_extern {
|
||||
self.reachable_symbols.insert(search_item);
|
||||
}
|
||||
|
@ -246,7 +250,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
|
|||
hir_map::NodeItem(item) => {
|
||||
match item.node {
|
||||
hir::ItemFn(.., body) => {
|
||||
if item_might_be_inlined(&item) {
|
||||
let def_id = self.tcx.hir.local_def_id(item.id);
|
||||
if item_might_be_inlined(&item, self.tcx.trans_fn_attrs(def_id)) {
|
||||
self.visit_nested_body(body);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ pub struct CodegenUnit<'tcx> {
|
|||
size_estimate: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum Linkage {
|
||||
External,
|
||||
AvailableExternally,
|
||||
|
|
|
@ -631,16 +631,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
|
||||
}
|
||||
|
||||
ty::Predicate::Equate(ref predicate) => {
|
||||
let predicate = self.resolve_type_vars_if_possible(predicate);
|
||||
let err = self.equality_predicate(&obligation.cause,
|
||||
obligation.param_env,
|
||||
&predicate).err().unwrap();
|
||||
struct_span_err!(self.tcx.sess, span, E0278,
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate, err)
|
||||
}
|
||||
|
||||
ty::Predicate::RegionOutlives(ref predicate) => {
|
||||
let predicate = self.resolve_type_vars_if_possible(predicate);
|
||||
let err = self.region_outlives_predicate(&obligation.cause,
|
||||
|
@ -1270,7 +1260,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
ObligationCauseCode::MatchExpressionArm { .. } |
|
||||
ObligationCauseCode::IfExpression |
|
||||
ObligationCauseCode::IfExpressionWithNoElse |
|
||||
ObligationCauseCode::EquatePredicate |
|
||||
ObligationCauseCode::MainFunctionType |
|
||||
ObligationCauseCode::StartFunctionType |
|
||||
ObligationCauseCode::IntrinsicType |
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use infer::{RegionObligation, InferCtxt, InferOk};
|
||||
use infer::{RegionObligation, InferCtxt};
|
||||
use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate};
|
||||
use ty::error::ExpectedFound;
|
||||
use rustc_data_structures::obligation_forest::{ObligationForest, Error};
|
||||
|
@ -380,17 +380,6 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
ty::Predicate::Equate(ref binder) => {
|
||||
match selcx.infcx().equality_predicate(&obligation.cause,
|
||||
obligation.param_env,
|
||||
binder) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
Ok(Some(obligations))
|
||||
},
|
||||
Err(_) => Err(CodeSelectionError(Unimplemented)),
|
||||
}
|
||||
}
|
||||
|
||||
ty::Predicate::RegionOutlives(ref binder) => {
|
||||
match selcx.infcx().region_outlives_predicate(&obligation.cause, binder) {
|
||||
Ok(()) => Ok(Some(Vec::new())),
|
||||
|
|
|
@ -204,9 +204,6 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
/// Computing common supertype of an if expression with no else counter-part
|
||||
IfExpressionWithNoElse,
|
||||
|
||||
/// `where a == b`
|
||||
EquatePredicate,
|
||||
|
||||
/// `main` has wrong type
|
||||
MainFunctionType,
|
||||
|
||||
|
@ -854,19 +851,6 @@ impl<'tcx, N> Vtable<'tcx, N> {
|
|||
}
|
||||
}
|
||||
|
||||
fn nested_obligations_mut(&mut self) -> &mut Vec<N> {
|
||||
match self {
|
||||
&mut VtableImpl(ref mut i) => &mut i.nested,
|
||||
&mut VtableParam(ref mut n) => n,
|
||||
&mut VtableBuiltin(ref mut i) => &mut i.nested,
|
||||
&mut VtableAutoImpl(ref mut d) => &mut d.nested,
|
||||
&mut VtableGenerator(ref mut c) => &mut c.nested,
|
||||
&mut VtableClosure(ref mut c) => &mut c.nested,
|
||||
&mut VtableObject(ref mut d) => &mut d.nested,
|
||||
&mut VtableFnPointer(ref mut d) => &mut d.nested,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map<M, F>(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M {
|
||||
match self {
|
||||
VtableImpl(i) => VtableImpl(VtableImplData {
|
||||
|
|
|
@ -175,7 +175,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::ClosureKind(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::ConstEvaluatable(..) => {
|
||||
false
|
||||
}
|
||||
|
@ -204,7 +203,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
|
|
|
@ -44,12 +44,10 @@ use ty::relate::TypeRelation;
|
|||
use middle::lang_items;
|
||||
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec};
|
||||
use std::iter;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use syntax::abi::Abi;
|
||||
|
@ -57,14 +55,6 @@ use hir;
|
|||
use lint;
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
|
||||
struct InferredObligationsSnapshotVecDelegate<'tcx> {
|
||||
phantom: PhantomData<&'tcx i32>,
|
||||
}
|
||||
impl<'tcx> SnapshotVecDelegate for InferredObligationsSnapshotVecDelegate<'tcx> {
|
||||
type Value = PredicateObligation<'tcx>;
|
||||
type Undo = ();
|
||||
fn reverse(_: &mut Vec<Self::Value>, _: Self::Undo) {}
|
||||
}
|
||||
|
||||
pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
|
@ -92,8 +82,6 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
|||
/// would satisfy it. This avoids crippling inference, basically.
|
||||
intercrate: Option<IntercrateMode>,
|
||||
|
||||
inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
|
||||
|
||||
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
|
||||
|
||||
/// Controls whether or not to filter out negative impls when selecting.
|
||||
|
@ -429,7 +417,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: None,
|
||||
inferred_obligations: SnapshotVec::new(),
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
}
|
||||
|
@ -442,7 +429,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: Some(mode),
|
||||
inferred_obligations: SnapshotVec::new(),
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
}
|
||||
|
@ -455,7 +441,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: None,
|
||||
inferred_obligations: SnapshotVec::new(),
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls,
|
||||
}
|
||||
|
@ -498,8 +483,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
fn in_snapshot<R, F>(&mut self, f: F) -> R
|
||||
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
|
||||
{
|
||||
// The irrefutable nature of the operation means we don't need to snapshot the
|
||||
// inferred_obligations vector.
|
||||
self.infcx.in_snapshot(|snapshot| f(self, snapshot))
|
||||
}
|
||||
|
||||
|
@ -508,10 +491,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
fn probe<R, F>(&mut self, f: F) -> R
|
||||
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
|
||||
{
|
||||
let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot();
|
||||
let result = self.infcx.probe(|snapshot| f(self, snapshot));
|
||||
self.inferred_obligations.rollback_to(inferred_obligations_snapshot);
|
||||
result
|
||||
self.infcx.probe(|snapshot| f(self, snapshot))
|
||||
}
|
||||
|
||||
/// Wraps a commit_if_ok s.t. obligations collected during it are not returned in selection if
|
||||
|
@ -519,17 +499,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
fn commit_if_ok<T, E, F>(&mut self, f: F) -> Result<T, E> where
|
||||
F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> Result<T, E>
|
||||
{
|
||||
let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot();
|
||||
match self.infcx.commit_if_ok(|snapshot| f(self, snapshot)) {
|
||||
Ok(ok) => {
|
||||
self.inferred_obligations.commit(inferred_obligations_snapshot);
|
||||
Ok(ok)
|
||||
},
|
||||
Err(err) => {
|
||||
self.inferred_obligations.rollback_to(inferred_obligations_snapshot);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
self.infcx.commit_if_ok(|snapshot| f(self, snapshot))
|
||||
}
|
||||
|
||||
|
||||
|
@ -560,12 +530,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
|
||||
let ret = match self.candidate_from_obligation(&stack)? {
|
||||
None => None,
|
||||
Some(candidate) => {
|
||||
let mut candidate = self.confirm_candidate(obligation, candidate)?;
|
||||
let inferred_obligations = (*self.inferred_obligations).into_iter().cloned();
|
||||
candidate.nested_obligations_mut().extend(inferred_obligations);
|
||||
Some(candidate)
|
||||
},
|
||||
Some(candidate) => Some(self.confirm_candidate(obligation, candidate)?)
|
||||
};
|
||||
|
||||
// Test whether this is a `()` which was produced by defaulting a
|
||||
|
@ -658,7 +623,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
stack: TraitObligationStackList<'o, 'tcx>,
|
||||
predicates: I)
|
||||
-> EvaluationResult
|
||||
where I : Iterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
|
||||
where I : IntoIterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
|
||||
{
|
||||
let mut result = EvaluatedToOk;
|
||||
for obligation in predicates {
|
||||
|
@ -691,22 +656,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
self.evaluate_trait_predicate_recursively(previous_stack, obligation)
|
||||
}
|
||||
|
||||
ty::Predicate::Equate(ref p) => {
|
||||
// does this code ever run?
|
||||
match self.infcx.equality_predicate(&obligation.cause, obligation.param_env, p) {
|
||||
Ok(InferOk { obligations, .. }) => {
|
||||
self.inferred_obligations.extend(obligations);
|
||||
EvaluatedToOk
|
||||
},
|
||||
Err(_) => EvaluatedToErr
|
||||
}
|
||||
}
|
||||
|
||||
ty::Predicate::Subtype(ref p) => {
|
||||
// does this code ever run?
|
||||
match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
|
||||
Some(Ok(InferOk { obligations, .. })) => {
|
||||
self.inferred_obligations.extend(obligations);
|
||||
self.evaluate_predicates_recursively(previous_stack, &obligations);
|
||||
EvaluatedToOk
|
||||
},
|
||||
Some(Err(_)) => EvaluatedToErr,
|
||||
|
@ -1553,12 +1507,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
-> bool
|
||||
{
|
||||
assert!(!skol_trait_ref.has_escaping_regions());
|
||||
match self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.sup(ty::Binder(skol_trait_ref), trait_bound) {
|
||||
Ok(InferOk { obligations, .. }) => {
|
||||
self.inferred_obligations.extend(obligations);
|
||||
}
|
||||
Err(_) => { return false; }
|
||||
if let Err(_) = self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.sup(ty::Binder(skol_trait_ref), trait_bound) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.infcx.leak_check(false, obligation.cause.span, skol_map, snapshot).is_ok()
|
||||
|
@ -2644,6 +2595,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
};
|
||||
|
||||
let mut upcast_trait_ref = None;
|
||||
let mut nested = vec![];
|
||||
let vtable_base;
|
||||
|
||||
{
|
||||
|
@ -2662,7 +2614,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
self.commit_if_ok(
|
||||
|this, _| this.match_poly_trait_ref(obligation, t))
|
||||
{
|
||||
Ok(_) => { upcast_trait_ref = Some(t); false }
|
||||
Ok(obligations) => {
|
||||
upcast_trait_ref = Some(t);
|
||||
nested.extend(obligations);
|
||||
false
|
||||
}
|
||||
Err(_) => { true }
|
||||
}
|
||||
});
|
||||
|
@ -2680,7 +2636,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
VtableObjectData {
|
||||
upcast_trait_ref: upcast_trait_ref.unwrap(),
|
||||
vtable_base,
|
||||
nested: vec![]
|
||||
nested,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2737,7 +2693,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
self.generator_trait_ref_unnormalized(obligation, closure_def_id, substs);
|
||||
let Normalized {
|
||||
value: trait_ref,
|
||||
obligations
|
||||
mut obligations
|
||||
} = normalize_with_depth(self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
|
@ -2749,10 +2705,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
trait_ref,
|
||||
obligations);
|
||||
|
||||
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
||||
obligation.param_env,
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
trait_ref)?;
|
||||
obligations.extend(
|
||||
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
||||
obligation.param_env,
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
trait_ref)?);
|
||||
|
||||
Ok(VtableGeneratorData {
|
||||
closure_def_id: closure_def_id,
|
||||
|
@ -2798,10 +2755,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
trait_ref,
|
||||
obligations);
|
||||
|
||||
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
||||
obligation.param_env,
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
trait_ref)?;
|
||||
obligations.extend(
|
||||
self.confirm_poly_trait_refs(obligation.cause.clone(),
|
||||
obligation.param_env,
|
||||
obligation.predicate.to_poly_trait_ref(),
|
||||
trait_ref)?);
|
||||
|
||||
obligations.push(Obligation::new(
|
||||
obligation.cause.clone(),
|
||||
|
@ -2845,13 +2803,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
obligation_param_env: ty::ParamEnv<'tcx>,
|
||||
obligation_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
expected_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Result<(), SelectionError<'tcx>>
|
||||
-> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>>
|
||||
{
|
||||
let obligation_trait_ref = obligation_trait_ref.clone();
|
||||
self.infcx
|
||||
.at(&obligation_cause, obligation_param_env)
|
||||
.sup(obligation_trait_ref, expected_trait_ref)
|
||||
.map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
|
||||
.map(|InferOk { obligations, .. }| obligations)
|
||||
.map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
|
||||
}
|
||||
|
||||
|
@ -2888,7 +2846,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.eq(target, new_trait)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
self.inferred_obligations.extend(obligations);
|
||||
nested.extend(obligations);
|
||||
|
||||
// Register one obligation for 'a: 'b.
|
||||
let cause = ObligationCause::new(obligation.cause.span,
|
||||
|
@ -2950,7 +2908,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.eq(b, a)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
self.inferred_obligations.extend(obligations);
|
||||
nested.extend(obligations);
|
||||
}
|
||||
|
||||
// Struct<T> -> Struct<U>.
|
||||
|
@ -3014,7 +2972,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.eq(target, new_struct)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
self.inferred_obligations.extend(obligations);
|
||||
nested.extend(obligations);
|
||||
|
||||
// Construct the nested Field<T>: Unsize<Field<U>> predicate.
|
||||
nested.push(tcx.predicate_for_trait_def(
|
||||
|
@ -3045,7 +3003,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.eq(target, new_tuple)
|
||||
.map_err(|_| Unimplemented)?;
|
||||
self.inferred_obligations.extend(obligations);
|
||||
nested.extend(obligations);
|
||||
|
||||
// Construct the nested T: Unsize<U> predicate.
|
||||
nested.push(tcx.predicate_for_trait_def(
|
||||
|
@ -3118,7 +3076,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
|
||||
impl_substs);
|
||||
|
||||
let impl_trait_ref =
|
||||
let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
|
||||
project::normalize_with_depth(self,
|
||||
obligation.param_env,
|
||||
obligation.cause.clone(),
|
||||
|
@ -3134,12 +3092,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
|
||||
let InferOk { obligations, .. } =
|
||||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.eq(skol_obligation_trait_ref, impl_trait_ref.value)
|
||||
.eq(skol_obligation_trait_ref, impl_trait_ref)
|
||||
.map_err(|e| {
|
||||
debug!("match_impl: failed eq_trait_refs due to `{}`", e);
|
||||
()
|
||||
})?;
|
||||
self.inferred_obligations.extend(obligations);
|
||||
nested_obligations.extend(obligations);
|
||||
|
||||
if let Err(e) = self.infcx.leak_check(false,
|
||||
obligation.cause.span,
|
||||
|
@ -3152,7 +3110,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
debug!("match_impl: success impl_substs={:?}", impl_substs);
|
||||
Ok((Normalized {
|
||||
value: impl_substs,
|
||||
obligations: impl_trait_ref.obligations
|
||||
obligations: nested_obligations
|
||||
}, skol_map))
|
||||
}
|
||||
|
||||
|
@ -3189,8 +3147,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Result<Vec<PredicateObligation<'tcx>>,()>
|
||||
{
|
||||
self.match_poly_trait_ref(obligation, where_clause_trait_ref)?;
|
||||
Ok(Vec::new())
|
||||
self.match_poly_trait_ref(obligation, where_clause_trait_ref)
|
||||
}
|
||||
|
||||
/// Returns `Ok` if `poly_trait_ref` being true implies that the
|
||||
|
@ -3198,7 +3155,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
fn match_poly_trait_ref(&mut self,
|
||||
obligation: &TraitObligation<'tcx>,
|
||||
poly_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Result<(),()>
|
||||
-> Result<Vec<PredicateObligation<'tcx>>,()>
|
||||
{
|
||||
debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
|
||||
obligation,
|
||||
|
@ -3206,7 +3163,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
|||
|
||||
self.infcx.at(&obligation.cause, obligation.param_env)
|
||||
.sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
|
||||
.map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
|
||||
.map(|InferOk { obligations, .. }| obligations)
|
||||
.map_err(|_| ())
|
||||
}
|
||||
|
||||
|
|
|
@ -236,7 +236,6 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
|
|||
}
|
||||
super::IfExpression => Some(super::IfExpression),
|
||||
super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse),
|
||||
super::EquatePredicate => Some(super::EquatePredicate),
|
||||
super::MainFunctionType => Some(super::MainFunctionType),
|
||||
super::StartFunctionType => Some(super::StartFunctionType),
|
||||
super::IntrinsicType => Some(super::IntrinsicType),
|
||||
|
@ -512,7 +511,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
|
|||
super::MatchExpressionArm { arm_span: _, source: _ } |
|
||||
super::IfExpression |
|
||||
super::IfExpressionWithNoElse |
|
||||
super::EquatePredicate |
|
||||
super::MainFunctionType |
|
||||
super::StartFunctionType |
|
||||
super::IntrinsicType |
|
||||
|
@ -561,7 +559,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> {
|
|||
super::MatchExpressionArm { arm_span: _, source: _ } |
|
||||
super::IfExpression |
|
||||
super::IfExpressionWithNoElse |
|
||||
super::EquatePredicate |
|
||||
super::MainFunctionType |
|
||||
super::StartFunctionType |
|
||||
super::IntrinsicType |
|
||||
|
|
|
@ -25,9 +25,6 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
ty::Predicate::Trait(ref data) =>
|
||||
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data)),
|
||||
|
||||
ty::Predicate::Equate(ref data) =>
|
||||
ty::Predicate::Equate(tcx.anonymize_late_bound_regions(data)),
|
||||
|
||||
ty::Predicate::RegionOutlives(ref data) =>
|
||||
ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data)),
|
||||
|
||||
|
@ -163,11 +160,6 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
|
|||
// Currently, we do not elaborate object-safe
|
||||
// predicates.
|
||||
}
|
||||
ty::Predicate::Equate(..) => {
|
||||
// Currently, we do not "elaborate" predicates like
|
||||
// `X == Y`, though conceivably we might. For example,
|
||||
// `&X == &Y` implies that `X == Y`.
|
||||
}
|
||||
ty::Predicate::Subtype(..) => {
|
||||
// Currently, we do not "elaborate" predicates like `X
|
||||
// <: Y`, though conceivably we might.
|
||||
|
|
|
@ -96,7 +96,6 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||
) -> bool {
|
||||
use syntax::attr::requests_inline;
|
||||
if self.is_inline(tcx) {
|
||||
return true
|
||||
}
|
||||
|
@ -106,8 +105,8 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
// available to normal end-users.
|
||||
return true
|
||||
}
|
||||
requests_inline(&self.attrs(tcx)[..]) ||
|
||||
tcx.is_const_fn(self.def_id())
|
||||
let trans_fn_attrs = tcx.trans_fn_attrs(self.def_id());
|
||||
trans_fn_attrs.requests_inline() || tcx.is_const_fn(self.def_id())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1203,7 +1203,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||
}
|
||||
|
||||
let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
|
||||
if pointee.is_sized(tcx, param_env, DUMMY_SP) {
|
||||
if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
|
||||
return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
|
||||
}
|
||||
|
||||
|
@ -1428,7 +1428,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
|
|||
let param_env = tcx.param_env(def.did);
|
||||
let last_field = def.variants[v].fields.last().unwrap();
|
||||
let always_sized = tcx.type_of(last_field.did)
|
||||
.is_sized(tcx, param_env, DUMMY_SP);
|
||||
.is_sized(tcx.at(DUMMY_SP), param_env);
|
||||
if !always_sized { StructKind::MaybeUnsized }
|
||||
else { StructKind::AlwaysSized }
|
||||
};
|
||||
|
|
|
@ -687,8 +687,8 @@ impl_disk_cacheable_query!(borrowck, |def_id| def_id.is_local());
|
|||
impl_disk_cacheable_query!(mir_borrowck, |def_id| def_id.is_local());
|
||||
impl_disk_cacheable_query!(mir_const_qualif, |def_id| def_id.is_local());
|
||||
impl_disk_cacheable_query!(check_match, |def_id| def_id.is_local());
|
||||
impl_disk_cacheable_query!(contains_extern_indicator, |_| true);
|
||||
impl_disk_cacheable_query!(def_symbol_name, |_| true);
|
||||
impl_disk_cacheable_query!(type_of, |def_id| def_id.is_local());
|
||||
impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local());
|
||||
impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local());
|
||||
impl_disk_cacheable_query!(trans_fn_attrs, |_| true);
|
||||
|
|
|
@ -12,7 +12,7 @@ use dep_graph::{DepConstructor, DepNode};
|
|||
use errors::DiagnosticBuilder;
|
||||
use hir::def_id::{CrateNum, DefId, DefIndex};
|
||||
use hir::def::{Def, Export};
|
||||
use hir::{self, TraitCandidate, ItemLocalId};
|
||||
use hir::{self, TraitCandidate, ItemLocalId, TransFnAttrs};
|
||||
use hir::svh::Svh;
|
||||
use lint;
|
||||
use middle::borrowck::BorrowCheckResult;
|
||||
|
@ -235,6 +235,7 @@ define_maps! { <'tcx>
|
|||
[] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>,
|
||||
[] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option<DeprecationEntry>,
|
||||
[] fn item_attrs: ItemAttrs(DefId) -> Lrc<[ast::Attribute]>,
|
||||
[] fn trans_fn_attrs: trans_fn_attrs(DefId) -> TransFnAttrs,
|
||||
[] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
|
||||
[] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
|
||||
[] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
|
||||
|
@ -362,8 +363,6 @@ define_maps! { <'tcx>
|
|||
[] fn collect_and_partition_translation_items:
|
||||
collect_and_partition_translation_items_node(CrateNum)
|
||||
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
|
||||
[] fn export_name: ExportName(DefId) -> Option<Symbol>,
|
||||
[] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool,
|
||||
[] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel,
|
||||
[] fn is_translated_item: IsTranslatedItem(DefId) -> bool,
|
||||
[] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
|
||||
|
@ -385,7 +384,6 @@ define_maps! { <'tcx>
|
|||
|
||||
[] fn target_features_whitelist:
|
||||
target_features_whitelist_node(CrateNum) -> Lrc<FxHashSet<String>>,
|
||||
[] fn target_features_enabled: TargetFeaturesEnabled(DefId) -> Lrc<Vec<String>>,
|
||||
|
||||
// Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
|
||||
[] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>)
|
||||
|
@ -403,6 +401,10 @@ fn features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
|
|||
DepConstructor::Features
|
||||
}
|
||||
|
||||
fn trans_fn_attrs<'tcx>(id: DefId) -> DepConstructor<'tcx> {
|
||||
DepConstructor::TransFnAttrs { 0: id }
|
||||
}
|
||||
|
||||
fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
|
||||
DepConstructor::EraseRegionsTy { ty }
|
||||
}
|
||||
|
|
|
@ -217,9 +217,9 @@ impl<'sess> OnDiskCache<'sess> {
|
|||
encode_query_results::<mir_const_qualif, _>(tcx, enc, qri)?;
|
||||
encode_query_results::<def_symbol_name, _>(tcx, enc, qri)?;
|
||||
encode_query_results::<const_is_rvalue_promotable_to_static, _>(tcx, enc, qri)?;
|
||||
encode_query_results::<contains_extern_indicator, _>(tcx, enc, qri)?;
|
||||
encode_query_results::<symbol_name, _>(tcx, enc, qri)?;
|
||||
encode_query_results::<check_match, _>(tcx, enc, qri)?;
|
||||
encode_query_results::<trans_fn_attrs, _>(tcx, enc, qri)?;
|
||||
}
|
||||
|
||||
// Encode diagnostics
|
||||
|
|
|
@ -854,6 +854,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
|||
DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
|
||||
DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
|
||||
DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
|
||||
DepKind::TransFnAttrs => { force!(trans_fn_attrs, def_id!()); }
|
||||
DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
|
||||
DepKind::DylibDepFormats => { force!(dylib_dependency_formats, krate!()); }
|
||||
DepKind::IsPanicRuntime => { force!(is_panic_runtime, krate!()); }
|
||||
|
@ -925,15 +926,10 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
|||
DepKind::CollectAndPartitionTranslationItems => {
|
||||
force!(collect_and_partition_translation_items, LOCAL_CRATE);
|
||||
}
|
||||
DepKind::ExportName => { force!(export_name, def_id!()); }
|
||||
DepKind::ContainsExternIndicator => {
|
||||
force!(contains_extern_indicator, def_id!());
|
||||
}
|
||||
DepKind::IsTranslatedItem => { force!(is_translated_item, def_id!()); }
|
||||
DepKind::OutputFilenames => { force!(output_filenames, LOCAL_CRATE); }
|
||||
|
||||
DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
|
||||
DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
|
||||
|
||||
DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
|
||||
DepKind::Features => { force!(features_query, LOCAL_CRATE); }
|
||||
|
@ -997,10 +993,10 @@ impl_load_from_cache!(
|
|||
MirConstQualif => mir_const_qualif,
|
||||
SymbolName => def_symbol_name,
|
||||
ConstIsRvaluePromotableToStatic => const_is_rvalue_promotable_to_static,
|
||||
ContainsExternIndicator => contains_extern_indicator,
|
||||
CheckMatch => check_match,
|
||||
TypeOfItem => type_of,
|
||||
GenericsOfItem => generics_of,
|
||||
PredicatesOfItem => predicates_of,
|
||||
UsedTraitImports => used_trait_imports,
|
||||
TransFnAttrs => trans_fn_attrs,
|
||||
);
|
||||
|
|
|
@ -912,9 +912,6 @@ pub enum Predicate<'tcx> {
|
|||
/// would be the type parameters.
|
||||
Trait(PolyTraitPredicate<'tcx>),
|
||||
|
||||
/// where `T1 == T2`.
|
||||
Equate(PolyEquatePredicate<'tcx>),
|
||||
|
||||
/// where 'a : 'b
|
||||
RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
|
||||
|
||||
|
@ -1023,8 +1020,6 @@ impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
|
|||
match *self {
|
||||
Predicate::Trait(ty::Binder(ref data)) =>
|
||||
Predicate::Trait(ty::Binder(data.subst(tcx, substs))),
|
||||
Predicate::Equate(ty::Binder(ref data)) =>
|
||||
Predicate::Equate(ty::Binder(data.subst(tcx, substs))),
|
||||
Predicate::Subtype(ty::Binder(ref data)) =>
|
||||
Predicate::Subtype(ty::Binder(data.subst(tcx, substs))),
|
||||
Predicate::RegionOutlives(ty::Binder(ref data)) =>
|
||||
|
@ -1072,10 +1067,6 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1`
|
||||
pub type PolyEquatePredicate<'tcx> = ty::Binder<EquatePredicate<'tcx>>;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
|
||||
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
|
||||
|
@ -1166,12 +1157,6 @@ impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PolyEquatePredicate<'tcx> {
|
||||
fn to_predicate(&self) -> Predicate<'tcx> {
|
||||
Predicate::Equate(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
|
||||
fn to_predicate(&self) -> Predicate<'tcx> {
|
||||
Predicate::RegionOutlives(self.clone())
|
||||
|
@ -1199,9 +1184,6 @@ impl<'tcx> Predicate<'tcx> {
|
|||
ty::Predicate::Trait(ref data) => {
|
||||
data.skip_binder().input_types().collect()
|
||||
}
|
||||
ty::Predicate::Equate(ty::Binder(ref data)) => {
|
||||
vec![data.0, data.1]
|
||||
}
|
||||
ty::Predicate::Subtype(ty::Binder(SubtypePredicate { a, b, a_is_expected: _ })) => {
|
||||
vec![a, b]
|
||||
}
|
||||
|
@ -1242,7 +1224,6 @@ impl<'tcx> Predicate<'tcx> {
|
|||
Some(t.to_poly_trait_ref())
|
||||
}
|
||||
Predicate::Projection(..) |
|
||||
Predicate::Equate(..) |
|
||||
Predicate::Subtype(..) |
|
||||
Predicate::RegionOutlives(..) |
|
||||
Predicate::WellFormed(..) |
|
||||
|
@ -1262,7 +1243,6 @@ impl<'tcx> Predicate<'tcx> {
|
|||
}
|
||||
Predicate::Trait(..) |
|
||||
Predicate::Projection(..) |
|
||||
Predicate::Equate(..) |
|
||||
Predicate::Subtype(..) |
|
||||
Predicate::RegionOutlives(..) |
|
||||
Predicate::WellFormed(..) |
|
||||
|
|
|
@ -282,14 +282,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::EquatePredicate<'a> {
|
||||
type Lifted = ty::EquatePredicate<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
|
||||
-> Option<ty::EquatePredicate<'tcx>> {
|
||||
tcx.lift(&(self.0, self.1)).map(|(a, b)| ty::EquatePredicate(a, b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::SubtypePredicate<'a> {
|
||||
type Lifted = ty::SubtypePredicate<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
|
||||
|
@ -355,9 +347,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> {
|
|||
ty::Predicate::Trait(ref binder) => {
|
||||
tcx.lift(binder).map(ty::Predicate::Trait)
|
||||
}
|
||||
ty::Predicate::Equate(ref binder) => {
|
||||
tcx.lift(binder).map(ty::Predicate::Equate)
|
||||
}
|
||||
ty::Predicate::Subtype(ref binder) => {
|
||||
tcx.lift(binder).map(ty::Predicate::Subtype)
|
||||
}
|
||||
|
@ -1049,8 +1038,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
|||
match *self {
|
||||
ty::Predicate::Trait(ref a) =>
|
||||
ty::Predicate::Trait(a.fold_with(folder)),
|
||||
ty::Predicate::Equate(ref binder) =>
|
||||
ty::Predicate::Equate(binder.fold_with(folder)),
|
||||
ty::Predicate::Subtype(ref binder) =>
|
||||
ty::Predicate::Subtype(binder.fold_with(folder)),
|
||||
ty::Predicate::RegionOutlives(ref binder) =>
|
||||
|
@ -1073,7 +1060,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
|||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ty::Predicate::Trait(ref a) => a.visit_with(visitor),
|
||||
ty::Predicate::Equate(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::Subtype(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::RegionOutlives(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor),
|
||||
|
@ -1111,16 +1097,6 @@ BraceStructTypeFoldableImpl! {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::EquatePredicate(self.0.fold_with(folder), self.1.fold_with(folder))
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.0.visit_with(visitor) || self.1.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::SubtypePredicate<'tcx> {
|
||||
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::SubtypePredicate {
|
||||
|
|
|
@ -20,6 +20,7 @@ use traits::{self, Reveal};
|
|||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::fold::TypeVisitor;
|
||||
use ty::subst::{Subst, UnpackedKind};
|
||||
use ty::maps::TyCtxtAt;
|
||||
use ty::TypeVariants::*;
|
||||
use util::common::ErrorReported;
|
||||
use middle::lang_items;
|
||||
|
@ -385,7 +386,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
match predicate {
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::Trait(..) |
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::WellFormed(..) |
|
||||
ty::Predicate::ObjectSafe(..) |
|
||||
|
@ -864,11 +864,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
|
|||
}
|
||||
|
||||
pub fn is_sized(&'tcx self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span)-> bool
|
||||
tcx_at: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>)-> bool
|
||||
{
|
||||
tcx.at(span).is_sized_raw(param_env.and(self))
|
||||
tcx_at.is_sized_raw(param_env.and(self))
|
||||
}
|
||||
|
||||
pub fn is_freeze(&'tcx self,
|
||||
|
|
|
@ -77,10 +77,6 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
|
|||
ty::Predicate::Trait(ref t) => {
|
||||
wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
|
||||
}
|
||||
ty::Predicate::Equate(ref t) => {
|
||||
wf.compute(t.skip_binder().0);
|
||||
wf.compute(t.skip_binder().1);
|
||||
}
|
||||
ty::Predicate::RegionOutlives(..) => {
|
||||
}
|
||||
ty::Predicate::TypeOutlives(ref t) => {
|
||||
|
|
|
@ -939,7 +939,6 @@ define_print_multi! {
|
|||
('tcx) ty::Binder<ty::TraitRef<'tcx>>,
|
||||
('tcx) ty::Binder<ty::FnSig<'tcx>>,
|
||||
('tcx) ty::Binder<ty::TraitPredicate<'tcx>>,
|
||||
('tcx) ty::Binder<ty::EquatePredicate<'tcx>>,
|
||||
('tcx) ty::Binder<ty::SubtypePredicate<'tcx>>,
|
||||
('tcx) ty::Binder<ty::ProjectionPredicate<'tcx>>,
|
||||
('tcx) ty::Binder<ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
|
||||
|
@ -1217,14 +1216,6 @@ define_print! {
|
|||
}
|
||||
}
|
||||
|
||||
define_print! {
|
||||
('tcx) ty::EquatePredicate<'tcx>, (self, f, cx) {
|
||||
display {
|
||||
print!(f, cx, print(self.0), write(" == "), print(self.1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define_print! {
|
||||
('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) {
|
||||
display {
|
||||
|
@ -1292,7 +1283,6 @@ define_print! {
|
|||
display {
|
||||
match *self {
|
||||
ty::Predicate::Trait(ref data) => data.print(f, cx),
|
||||
ty::Predicate::Equate(ref predicate) => predicate.print(f, cx),
|
||||
ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx),
|
||||
ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx),
|
||||
ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx),
|
||||
|
@ -1317,7 +1307,6 @@ define_print! {
|
|||
debug {
|
||||
match *self {
|
||||
ty::Predicate::Trait(ref a) => a.print(f, cx),
|
||||
ty::Predicate::Equate(ref pair) => pair.print(f, cx),
|
||||
ty::Predicate::Subtype(ref pair) => pair.print(f, cx),
|
||||
ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx),
|
||||
ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx),
|
||||
|
|
|
@ -243,6 +243,7 @@ fn main() {
|
|||
```
|
||||
*/
|
||||
|
||||
use std::mem;
|
||||
pub use stable_deref_trait::{StableDeref as StableAddress, CloneStableDeref as CloneStableAddress};
|
||||
|
||||
/// An owning reference.
|
||||
|
@ -279,7 +280,7 @@ pub struct OwningRefMut<O, T: ?Sized> {
|
|||
pub trait Erased {}
|
||||
impl<T> Erased for T {}
|
||||
|
||||
/// Helper trait for erasing the concrete type of what an owner derferences to,
|
||||
/// Helper trait for erasing the concrete type of what an owner dereferences to,
|
||||
/// for example `Box<T> -> Box<Erased>`. This would be unneeded with
|
||||
/// higher kinded types support in the language.
|
||||
pub unsafe trait IntoErased<'a> {
|
||||
|
@ -289,10 +290,20 @@ pub unsafe trait IntoErased<'a> {
|
|||
fn into_erased(self) -> Self::Erased;
|
||||
}
|
||||
|
||||
/// Helper trait for erasing the concrete type of what an owner derferences to,
|
||||
/// Helper trait for erasing the concrete type of what an owner dereferences to,
|
||||
/// for example `Box<T> -> Box<Erased + Send>`. This would be unneeded with
|
||||
/// higher kinded types support in the language.
|
||||
pub unsafe trait IntoErasedSend<'a> {
|
||||
/// Owner with the dereference type substituted to `Erased + Send`.
|
||||
type Erased: Send;
|
||||
/// Perform the type erasure.
|
||||
fn into_erased_send(self) -> Self::Erased;
|
||||
}
|
||||
|
||||
/// Helper trait for erasing the concrete type of what an owner dereferences to,
|
||||
/// for example `Box<T> -> Box<Erased + Send + Sync>`. This would be unneeded with
|
||||
/// higher kinded types support in the language.
|
||||
pub unsafe trait IntoErasedSendSync<'a>: Send + Sync {
|
||||
pub unsafe trait IntoErasedSendSync<'a> {
|
||||
/// Owner with the dereference type substituted to `Erased + Send + Sync`.
|
||||
type Erased: Send + Sync;
|
||||
/// Perform the type erasure.
|
||||
|
@ -472,6 +483,18 @@ impl<O, T: ?Sized> OwningRef<O, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Erases the concrete base type of the owner with a trait object which implements `Send`.
|
||||
///
|
||||
/// This allows mixing of owned references with different owner base types.
|
||||
pub fn erase_send_owner<'a>(self) -> OwningRef<O::Erased, T>
|
||||
where O: IntoErasedSend<'a>,
|
||||
{
|
||||
OwningRef {
|
||||
reference: self.reference,
|
||||
owner: self.owner.into_erased_send(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Erases the concrete base type of the owner with a trait object which implements `Send` and `Sync`.
|
||||
///
|
||||
/// This allows mixing of owned references with different owner base types.
|
||||
|
@ -1161,13 +1184,25 @@ unsafe impl<'a, T: 'a> IntoErased<'a> for Arc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Box<T> {
|
||||
type Erased = Box<Erased + Send + Sync + 'a>;
|
||||
fn into_erased_send_sync(self) -> Self::Erased {
|
||||
unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box<T> {
|
||||
type Erased = Box<Erased + Send + 'a>;
|
||||
fn into_erased_send(self) -> Self::Erased {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box<T> {
|
||||
type Erased = Box<Erased + Sync + Send + 'a>;
|
||||
fn into_erased_send_sync(self) -> Self::Erased {
|
||||
let result: Box<Erased + Send + 'a> = self;
|
||||
// This is safe since Erased can always implement Sync
|
||||
// Only the destructor is available and it takes &mut self
|
||||
unsafe {
|
||||
mem::transmute(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc<T> {
|
||||
type Erased = Arc<Erased + Send + Sync + 'a>;
|
||||
fn into_erased_send_sync(self) -> Self::Erased {
|
||||
|
|
|
@ -177,7 +177,7 @@ cfg_if! {
|
|||
macro_rules! rustc_erase_owner {
|
||||
($v:expr) => {{
|
||||
let v = $v;
|
||||
::rustc_data_structures::sync::assert_send_sync_val(&v);
|
||||
::rustc_data_structures::sync::assert_send_val(&v);
|
||||
v.erase_send_sync_owner()
|
||||
}}
|
||||
}
|
||||
|
@ -262,6 +262,7 @@ cfg_if! {
|
|||
}
|
||||
|
||||
pub fn assert_sync<T: ?Sized + Sync>() {}
|
||||
pub fn assert_send_val<T: ?Sized + Send>(_t: &T) {}
|
||||
pub fn assert_send_sync_val<T: ?Sized + Sync + Send>(_t: &T) {}
|
||||
|
||||
#[macro_export]
|
||||
|
|
|
@ -22,6 +22,8 @@ pub struct ArchiveRO {
|
|||
ptr: ArchiveRef,
|
||||
}
|
||||
|
||||
unsafe impl Send for ArchiveRO {}
|
||||
|
||||
pub struct Iter<'a> {
|
||||
archive: &'a ArchiveRO,
|
||||
ptr: ::ArchiveIteratorRef,
|
||||
|
|
|
@ -221,6 +221,8 @@ pub struct ObjectFile {
|
|||
pub llof: ObjectFileRef,
|
||||
}
|
||||
|
||||
unsafe impl Send for ObjectFile {}
|
||||
|
||||
impl ObjectFile {
|
||||
// This will take ownership of llmb
|
||||
pub fn new(llmb: MemoryBufferRef) -> Option<ObjectFile> {
|
||||
|
|
|
@ -24,7 +24,6 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
|
|||
|
||||
use std::cell::{RefCell, Cell};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::owning_ref::ErasedBoxRef;
|
||||
use syntax::{ast, attr};
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
|
@ -42,7 +41,9 @@ pub use cstore_impl::{provide, provide_extern};
|
|||
// own crate numbers.
|
||||
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
|
||||
|
||||
pub struct MetadataBlob(pub ErasedBoxRef<[u8]>);
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
pub struct MetadataBlob(pub MetadataRef);
|
||||
|
||||
/// Holds information about a syntax_pos::FileMap imported from another crate.
|
||||
/// See `imported_filemaps()` for more information.
|
||||
|
|
|
@ -832,7 +832,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||
} else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let types = generics.parent_types as usize + generics.types.len();
|
||||
let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
|
||||
let needs_inline = types > 0 || tcx.trans_fn_attrs(def_id).requests_inline();
|
||||
let is_const_fn = sig.constness == hir::Constness::Const;
|
||||
let ast = if is_const_fn { Some(body) } else { None };
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
|
@ -1123,7 +1123,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||
hir::ItemConst(..) => self.encode_optimized_mir(def_id),
|
||||
hir::ItemFn(_, _, constness, _, ref generics, _) => {
|
||||
let has_tps = generics.ty_params().next().is_some();
|
||||
let needs_inline = has_tps || attr::requests_inline(&item.attrs);
|
||||
let needs_inline = has_tps || tcx.trans_fn_attrs(def_id).requests_inline();
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
if needs_inline || constness == hir::Constness::Const || always_encode_mir {
|
||||
self.encode_optimized_mir(def_id)
|
||||
|
|
|
@ -39,6 +39,7 @@ extern crate proc_macro;
|
|||
#[macro_use]
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
#[macro_use]
|
||||
extern crate rustc_data_structures;
|
||||
|
||||
mod diagnostics;
|
||||
|
|
|
@ -219,7 +219,7 @@
|
|||
//! no means all of the necessary details. Take a look at the rest of
|
||||
//! metadata::locator or metadata::creader for all the juicy details!
|
||||
|
||||
use cstore::MetadataBlob;
|
||||
use cstore::{MetadataRef, MetadataBlob};
|
||||
use creader::Library;
|
||||
use schema::{METADATA_HEADER, rustc_version};
|
||||
|
||||
|
@ -243,8 +243,8 @@ use std::path::{Path, PathBuf};
|
|||
use std::time::Instant;
|
||||
|
||||
use flate2::read::DeflateDecoder;
|
||||
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
|
||||
|
||||
use rustc_data_structures::owning_ref::OwningRef;
|
||||
pub struct CrateMismatch {
|
||||
path: PathBuf,
|
||||
got: String,
|
||||
|
@ -842,7 +842,7 @@ fn get_metadata_section_imp(target: &Target,
|
|||
if !filename.exists() {
|
||||
return Err(format!("no such file: '{}'", filename.display()));
|
||||
}
|
||||
let raw_bytes: ErasedBoxRef<[u8]> = match flavor {
|
||||
let raw_bytes: MetadataRef = match flavor {
|
||||
CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
|
||||
CrateFlavor::Dylib => {
|
||||
let buf = loader.get_dylib_metadata(target, filename)?;
|
||||
|
@ -862,7 +862,7 @@ fn get_metadata_section_imp(target: &Target,
|
|||
match DeflateDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
|
||||
Ok(_) => {
|
||||
let buf = unsafe { OwningRef::new_assert_stable_address(inflated) };
|
||||
buf.map_owner_box().erase_owner()
|
||||
rustc_erase_owner!(buf.map_owner_box())
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(format!("failed to decompress metadata: {}", filename.display()));
|
||||
|
@ -872,7 +872,7 @@ fn get_metadata_section_imp(target: &Target,
|
|||
CrateFlavor::Rmeta => {
|
||||
let buf = fs::read(filename).map_err(|_|
|
||||
format!("failed to read rmeta metadata: '{}'", filename.display()))?;
|
||||
OwningRef::new(buf).map_owner_box().erase_owner()
|
||||
rustc_erase_owner!(OwningRef::new(buf).map_owner_box())
|
||||
}
|
||||
};
|
||||
let blob = MetadataBlob(raw_bytes);
|
||||
|
|
|
@ -1208,7 +1208,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
// shouldn't affect `is_sized`.
|
||||
let gcx = self.tcx().global_tcx();
|
||||
let erased_ty = gcx.lift(&self.tcx().erase_regions(&ty)).unwrap();
|
||||
if !erased_ty.is_sized(gcx, self.param_env, span) {
|
||||
if !erased_ty.is_sized(gcx.at(span), self.param_env) {
|
||||
// in current MIR construction, all non-control-flow rvalue
|
||||
// expressions evaluate through `as_temp` or `into` a return
|
||||
// slot or local, so to find all unsized rvalues it is enough
|
||||
|
|
|
@ -286,7 +286,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
}
|
||||
|
||||
pub(super) fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
|
||||
ty.is_sized(self.tcx, self.param_env, DUMMY_SP)
|
||||
ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env)
|
||||
}
|
||||
|
||||
pub fn load_mir(
|
||||
|
|
|
@ -188,7 +188,7 @@
|
|||
//! this is not implemented however: a mono item will be produced
|
||||
//! regardless of whether it is actually needed or not.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::{self, TransFnAttrFlags};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
|
||||
use rustc::hir::map as hir_map;
|
||||
|
@ -211,8 +211,6 @@ use monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode};
|
|||
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
|
||||
use syntax::attr;
|
||||
|
||||
use std::iter;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
|
||||
|
@ -796,7 +794,7 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
|
||||
let type_has_metadata = |ty: Ty<'tcx>| -> bool {
|
||||
use syntax_pos::DUMMY_SP;
|
||||
if ty.is_sized(tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) {
|
||||
if ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::empty(traits::Reveal::All)) {
|
||||
return false;
|
||||
}
|
||||
let tail = tcx.struct_tail(ty);
|
||||
|
@ -985,8 +983,8 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
|
|||
MonoItemCollectionMode::Lazy => {
|
||||
self.entry_fn == Some(def_id) ||
|
||||
self.tcx.is_reachable_non_generic(def_id) ||
|
||||
attr::contains_name(&self.tcx.get_attrs(def_id),
|
||||
"rustc_std_internal_symbol")
|
||||
self.tcx.trans_fn_attrs(def_id).flags.contains(
|
||||
TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ use rustc::session::config::OptLevel;
|
|||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Substs;
|
||||
use syntax::ast;
|
||||
use syntax::attr::{self, InlineAttr};
|
||||
use syntax::attr::InlineAttr;
|
||||
use std::fmt::{self, Write};
|
||||
use std::iter;
|
||||
use rustc::mir::mono::Linkage;
|
||||
|
@ -29,33 +29,6 @@ use syntax_pos::symbol::Symbol;
|
|||
use syntax::codemap::Span;
|
||||
pub use rustc::mir::mono::MonoItem;
|
||||
|
||||
pub fn linkage_by_name(name: &str) -> Option<Linkage> {
|
||||
use rustc::mir::mono::Linkage::*;
|
||||
|
||||
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
|
||||
// applicable to variable declarations and may not really make sense for
|
||||
// Rust code in the first place but whitelist them anyway and trust that
|
||||
// the user knows what s/he's doing. Who knows, unanticipated use cases
|
||||
// may pop up in the future.
|
||||
//
|
||||
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
|
||||
// and don't have to be, LLVM treats them as no-ops.
|
||||
match name {
|
||||
"appending" => Some(Appending),
|
||||
"available_externally" => Some(AvailableExternally),
|
||||
"common" => Some(Common),
|
||||
"extern_weak" => Some(ExternalWeak),
|
||||
"external" => Some(External),
|
||||
"internal" => Some(Internal),
|
||||
"linkonce" => Some(LinkOnceAny),
|
||||
"linkonce_odr" => Some(LinkOnceODR),
|
||||
"private" => Some(Private),
|
||||
"weak" => Some(WeakAny),
|
||||
"weak_odr" => Some(WeakODR),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes how a translation item will be instantiated in object files.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
|
||||
pub enum InstantiationMode {
|
||||
|
@ -141,8 +114,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
|||
// creating one copy of this `#[inline]` function which may
|
||||
// conflict with upstream crates as it could be an exported
|
||||
// symbol.
|
||||
let attrs = instance.def.attrs(tcx);
|
||||
match attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs) {
|
||||
match tcx.trans_fn_attrs(instance.def_id()).inline {
|
||||
InlineAttr::Always => InstantiationMode::LocalCopy,
|
||||
_ => {
|
||||
InstantiationMode::GloballyShared { may_conflict: true }
|
||||
|
@ -165,21 +137,8 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
|||
MonoItem::GlobalAsm(..) => return None,
|
||||
};
|
||||
|
||||
let attributes = tcx.get_attrs(def_id);
|
||||
if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
|
||||
if let Some(linkage) = linkage_by_name(&name.as_str()) {
|
||||
Some(linkage)
|
||||
} else {
|
||||
let span = tcx.hir.span_if_local(def_id);
|
||||
if let Some(span) = span {
|
||||
tcx.sess.span_fatal(span, "invalid linkage specified")
|
||||
} else {
|
||||
tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let trans_fn_attrs = tcx.trans_fn_attrs(def_id);
|
||||
trans_fn_attrs.linkage
|
||||
}
|
||||
|
||||
/// Returns whether this instance is instantiable - whether it has no unsatisfied
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
//! Inlining pass for MIR functions
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::TransFnAttrFlags;
|
||||
use rustc::hir::def_id::DefId;
|
||||
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
|
@ -206,10 +207,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
|
||||
let attrs = tcx.get_attrs(callsite.callee);
|
||||
let hint = attr::find_inline_attr(None, &attrs[..]);
|
||||
let trans_fn_attrs = tcx.trans_fn_attrs(callsite.callee);
|
||||
|
||||
let hinted = match hint {
|
||||
let hinted = match trans_fn_attrs.inline {
|
||||
// Just treat inline(always) as a hint for now,
|
||||
// there are cases that prevent inlining that we
|
||||
// need to check for first.
|
||||
|
@ -239,7 +239,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
};
|
||||
|
||||
// Significantly lower the threshold for inlining cold functions
|
||||
if attr::contains_name(&attrs[..], "cold") {
|
||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::COLD) {
|
||||
threshold /= 5;
|
||||
}
|
||||
|
||||
|
@ -344,7 +344,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let attr::InlineAttr::Always = hint {
|
||||
if let attr::InlineAttr::Always = trans_fn_attrs.inline {
|
||||
debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost);
|
||||
true
|
||||
} else {
|
||||
|
|
|
@ -1665,17 +1665,23 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
|
|||
if !self.span.filter_generated(sub_span, ex.span) {
|
||||
let span =
|
||||
self.span_from_span(sub_span.expect("No span found for var ref"));
|
||||
let ref_id =
|
||||
::id_from_def_id(def.non_enum_variant().fields[idx.node].did);
|
||||
self.dumper.dump_ref(Ref {
|
||||
kind: RefKind::Variable,
|
||||
span,
|
||||
ref_id,
|
||||
});
|
||||
if let Some(field) = def.non_enum_variant().fields.get(idx.node) {
|
||||
let ref_id = ::id_from_def_id(field.did);
|
||||
self.dumper.dump_ref(Ref {
|
||||
kind: RefKind::Variable,
|
||||
span,
|
||||
ref_id,
|
||||
});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::TyTuple(..) => {}
|
||||
_ => span_bug!(ex.span, "Expected struct or tuple type, found {:?}", ty),
|
||||
_ => {
|
||||
debug!("Expected struct or tuple type, found {:?}", ty);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprKind::Closure(_, _, ref decl, ref body, _fn_decl_span) => {
|
||||
|
|
|
@ -11,19 +11,16 @@
|
|||
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use rustc::hir::Unsafety;
|
||||
use rustc::hir::TransFnAttrFlags;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::session::config::Sanitizer;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
||||
use llvm::{self, Attribute, ValueRef};
|
||||
use llvm::AttributePlace::Function;
|
||||
use llvm_util;
|
||||
pub use syntax::attr::{self, InlineAttr};
|
||||
use syntax::ast;
|
||||
use context::CodegenCx;
|
||||
|
||||
/// Mark LLVM function to use provided inline heuristic.
|
||||
|
@ -102,31 +99,42 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) {
|
|||
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
|
||||
/// attributes.
|
||||
pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) {
|
||||
use syntax::attr::*;
|
||||
let attrs = cx.tcx.get_attrs(id);
|
||||
inline(llfn, find_inline_attr(Some(cx.sess().diagnostic()), &attrs));
|
||||
let trans_fn_attrs = cx.tcx.trans_fn_attrs(id);
|
||||
|
||||
inline(llfn, trans_fn_attrs.inline);
|
||||
|
||||
set_frame_pointer_elimination(cx, llfn);
|
||||
set_probestack(cx, llfn);
|
||||
|
||||
for attr in attrs.iter() {
|
||||
if attr.check_name("cold") {
|
||||
Attribute::Cold.apply_llfn(Function, llfn);
|
||||
} else if attr.check_name("naked") {
|
||||
naked(llfn, true);
|
||||
} else if attr.check_name("allocator") {
|
||||
Attribute::NoAlias.apply_llfn(
|
||||
llvm::AttributePlace::ReturnValue, llfn);
|
||||
} else if attr.check_name("unwind") {
|
||||
unwind(llfn, true);
|
||||
} else if attr.check_name("rustc_allocator_nounwind") {
|
||||
unwind(llfn, false);
|
||||
}
|
||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::COLD) {
|
||||
Attribute::Cold.apply_llfn(Function, llfn);
|
||||
}
|
||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::NAKED) {
|
||||
naked(llfn, true);
|
||||
}
|
||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::ALLOCATOR) {
|
||||
Attribute::NoAlias.apply_llfn(
|
||||
llvm::AttributePlace::ReturnValue, llfn);
|
||||
}
|
||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::UNWIND) {
|
||||
unwind(llfn, true);
|
||||
}
|
||||
if trans_fn_attrs.flags.contains(TransFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) {
|
||||
unwind(llfn, false);
|
||||
}
|
||||
|
||||
let target_features = cx.tcx.target_features_enabled(id);
|
||||
if !target_features.is_empty() {
|
||||
let val = CString::new(target_features.join(",")).unwrap();
|
||||
let features =
|
||||
trans_fn_attrs.target_features
|
||||
.iter()
|
||||
.map(|f| {
|
||||
let feature = &*f.as_str();
|
||||
format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join(",");
|
||||
|
||||
if !features.is_empty() {
|
||||
let val = CString::new(features).unwrap();
|
||||
llvm::AddFunctionAttrStringValue(
|
||||
llfn, llvm::AttributePlace::Function,
|
||||
cstr("target-features\0"), &val);
|
||||
|
@ -145,89 +153,4 @@ pub fn provide(providers: &mut Providers) {
|
|||
.map(|c| c.to_string())
|
||||
.collect())
|
||||
};
|
||||
|
||||
providers.target_features_enabled = |tcx, id| {
|
||||
let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
|
||||
let mut target_features = Vec::new();
|
||||
for attr in tcx.get_attrs(id).iter() {
|
||||
if !attr.check_name("target_feature") {
|
||||
continue
|
||||
}
|
||||
if let Some(val) = attr.value_str() {
|
||||
for feat in val.as_str().split(",").map(|f| f.trim()) {
|
||||
if !feat.is_empty() && !feat.contains('\0') {
|
||||
target_features.push(feat.to_string());
|
||||
}
|
||||
}
|
||||
let msg = "#[target_feature = \"..\"] is deprecated and will \
|
||||
eventually be removed, use \
|
||||
#[target_feature(enable = \"..\")] instead";
|
||||
tcx.sess.span_warn(attr.span, &msg);
|
||||
continue
|
||||
}
|
||||
|
||||
if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
|
||||
let msg = "#[target_feature(..)] can only be applied to \
|
||||
`unsafe` function";
|
||||
tcx.sess.span_err(attr.span, msg);
|
||||
}
|
||||
from_target_feature(tcx, attr, &whitelist, &mut target_features);
|
||||
}
|
||||
Lrc::new(target_features)
|
||||
};
|
||||
}
|
||||
|
||||
fn from_target_feature(
|
||||
tcx: TyCtxt,
|
||||
attr: &ast::Attribute,
|
||||
whitelist: &FxHashSet<String>,
|
||||
target_features: &mut Vec<String>,
|
||||
) {
|
||||
let list = match attr.meta_item_list() {
|
||||
Some(list) => list,
|
||||
None => {
|
||||
let msg = "#[target_feature] attribute must be of the form \
|
||||
#[target_feature(..)]";
|
||||
tcx.sess.span_err(attr.span, &msg);
|
||||
return
|
||||
}
|
||||
};
|
||||
|
||||
for item in list {
|
||||
if !item.check_name("enable") {
|
||||
let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
|
||||
currently";
|
||||
tcx.sess.span_err(item.span, &msg);
|
||||
continue
|
||||
}
|
||||
let value = match item.value_str() {
|
||||
Some(list) => list,
|
||||
None => {
|
||||
let msg = "#[target_feature] attribute must be of the form \
|
||||
#[target_feature(enable = \"..\")]";
|
||||
tcx.sess.span_err(item.span, &msg);
|
||||
continue
|
||||
}
|
||||
};
|
||||
let value = value.as_str();
|
||||
for feature in value.split(',') {
|
||||
if whitelist.contains(feature) {
|
||||
let llvm_feature = llvm_util::to_llvm_feature(&tcx.sess, feature);
|
||||
target_features.push(format!("+{}", llvm_feature));
|
||||
continue
|
||||
}
|
||||
|
||||
let msg = format!("the feature named `{}` is not valid for \
|
||||
this target", feature);
|
||||
let mut err = tcx.sess.struct_span_err(item.span, &msg);
|
||||
|
||||
if feature.starts_with("+") {
|
||||
let valid = whitelist.contains(&feature[1..]);
|
||||
if valid {
|
||||
err.help("consider removing the leading `+` in the feature name");
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use std::sync::Arc;
|
|||
|
||||
use monomorphize::Instance;
|
||||
use rustc::hir;
|
||||
use rustc::hir::TransFnAttrFlags;
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name};
|
||||
|
@ -21,7 +22,6 @@ use rustc::ty::{TyCtxt, SymbolName};
|
|||
use rustc::ty::maps::Providers;
|
||||
use rustc::util::nodemap::{FxHashMap, DefIdSet};
|
||||
use rustc_allocator::ALLOCATOR_METHODS;
|
||||
use syntax::attr;
|
||||
|
||||
pub type ExportedSymbols = FxHashMap<
|
||||
CrateNum,
|
||||
|
@ -256,9 +256,10 @@ fn symbol_export_level_provider(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportL
|
|||
// special symbols in the standard library for various plumbing between
|
||||
// core/std/allocators/etc. For example symbols used to hook up allocation
|
||||
// are not considered for export
|
||||
let is_extern = tcx.contains_extern_indicator(sym_def_id);
|
||||
let std_internal = attr::contains_name(&tcx.get_attrs(sym_def_id),
|
||||
"rustc_std_internal_symbol");
|
||||
let trans_fn_attrs = tcx.trans_fn_attrs(sym_def_id);
|
||||
let is_extern = trans_fn_attrs.contains_extern_indicator();
|
||||
let std_internal = trans_fn_attrs.flags.contains(TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||
|
||||
if is_extern && !std_internal {
|
||||
SymbolExportLevel::C
|
||||
} else {
|
||||
|
|
|
@ -90,7 +90,6 @@ use syntax::ast;
|
|||
use mir::operand::OperandValue;
|
||||
|
||||
pub use rustc_trans_utils::check_for_rustc_errors_attr;
|
||||
pub use rustc_mir::monomorphize::item::linkage_by_name;
|
||||
|
||||
pub struct StatRecorder<'a, 'tcx: 'a> {
|
||||
cx: &'a CodegenCx<'a, 'tcx>,
|
||||
|
|
|
@ -44,7 +44,7 @@ pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> b
|
|||
}
|
||||
|
||||
pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
ty.is_sized(tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP)
|
||||
ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::empty(traits::Reveal::All))
|
||||
}
|
||||
|
||||
pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
|
|
|
@ -146,20 +146,12 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
|
|||
hir_map::NodeForeignItem(&hir::ForeignItem {
|
||||
ref attrs, span, node: hir::ForeignItemStatic(..), ..
|
||||
}) => {
|
||||
|
||||
let g = if let Some(name) =
|
||||
attr::first_attr_value_str_by_name(&attrs, "linkage") {
|
||||
let g = if let Some(linkage) = cx.tcx.trans_fn_attrs(def_id).linkage {
|
||||
// If this is a static with a linkage specified, then we need to handle
|
||||
// it a little specially. The typesystem prevents things like &T and
|
||||
// extern "C" fn() from being non-null, so we can't just declare a
|
||||
// static and call it a day. Some linkages (like weak) will make it such
|
||||
// that the static actually has a null value.
|
||||
let linkage = match base::linkage_by_name(&name.as_str()) {
|
||||
Some(linkage) => linkage,
|
||||
None => {
|
||||
cx.sess().span_fatal(span, "invalid linkage specified");
|
||||
}
|
||||
};
|
||||
let llty2 = match ty.sty {
|
||||
ty::TyRawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx),
|
||||
_ => {
|
||||
|
|
|
@ -435,7 +435,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
|
|||
|
||||
pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
|
||||
use syntax_pos::DUMMY_SP;
|
||||
if ty.is_sized(self.tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP) {
|
||||
if ty.is_sized(self.tcx.at(DUMMY_SP), ty::ParamEnv::empty(traits::Reveal::All)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ extern crate rustc_allocator;
|
|||
extern crate rustc_apfloat;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_data_structures;
|
||||
#[macro_use] extern crate rustc_data_structures;
|
||||
extern crate rustc_demangle;
|
||||
extern crate rustc_incremental;
|
||||
extern crate rustc_llvm as llvm;
|
||||
|
|
|
@ -15,17 +15,19 @@ use llvm;
|
|||
use llvm::{False, ObjectFile, mk_section_iter};
|
||||
use llvm::archive_ro::ArchiveRO;
|
||||
|
||||
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
|
||||
use rustc_data_structures::owning_ref::OwningRef;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
pub const METADATA_FILENAME: &str = "rust.metadata.bin";
|
||||
|
||||
pub struct LlvmMetadataLoader;
|
||||
|
||||
impl MetadataLoader for LlvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
||||
// Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
|
||||
// internally to read the file. We also avoid even using a memcpy by
|
||||
// just keeping the archive along while the metadata is in use.
|
||||
|
@ -47,13 +49,13 @@ impl MetadataLoader for LlvmMetadataLoader {
|
|||
filename.display())
|
||||
})
|
||||
})?;
|
||||
Ok(buf.erase_owner())
|
||||
Ok(rustc_erase_owner!(buf))
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(&self,
|
||||
target: &Target,
|
||||
filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String> {
|
||||
-> Result<MetadataRef, String> {
|
||||
unsafe {
|
||||
let buf = common::path2cstr(filename);
|
||||
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
|
||||
|
@ -65,7 +67,7 @@ impl MetadataLoader for LlvmMetadataLoader {
|
|||
.ok_or_else(|| format!("provided path not an object file: '{}'",
|
||||
filename.display()))?;
|
||||
let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
|
||||
Ok(buf.erase_owner())
|
||||
Ok(rustc_erase_owner!(buf))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
register_long_diagnostics! {
|
||||
|
||||
E0558: r##"
|
||||
The `export_name` attribute was malformed.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
|
||||
#[export_name] // error: export_name attribute has invalid format
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
The `export_name` attribute expects a string in order to determine the name of
|
||||
the exported symbol. Example:
|
||||
|
||||
```
|
||||
#[export_name = "some_function"] // ok!
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
"##,
|
||||
|
||||
}
|
|
@ -37,16 +37,14 @@ extern crate rustc;
|
|||
extern crate rustc_back;
|
||||
extern crate rustc_mir;
|
||||
extern crate rustc_incremental;
|
||||
#[macro_use]
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
extern crate rustc_data_structures;
|
||||
#[macro_use] extern crate rustc_data_structures;
|
||||
|
||||
pub extern crate rustc as __rustc;
|
||||
|
||||
use rustc::ty::TyCtxt;
|
||||
|
||||
pub mod diagnostics;
|
||||
pub mod link;
|
||||
pub mod trans_crate;
|
||||
pub mod symbol_names;
|
||||
|
|
|
@ -120,29 +120,6 @@ pub fn provide(providers: &mut Providers) {
|
|||
def_symbol_name,
|
||||
symbol_name,
|
||||
|
||||
export_name: |tcx, id| {
|
||||
tcx.get_attrs(id).iter().fold(None, |ia, attr| {
|
||||
if attr.check_name("export_name") {
|
||||
if let s @ Some(_) = attr.value_str() {
|
||||
s
|
||||
} else {
|
||||
struct_span_err!(tcx.sess, attr.span, E0558,
|
||||
"export_name attribute has invalid format")
|
||||
.span_label(attr.span, "did you mean #[export_name=\"*\"]?")
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
} else {
|
||||
ia
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
contains_extern_indicator: |tcx, id| {
|
||||
attr::contains_name(&tcx.get_attrs(id), "no_mangle") ||
|
||||
tcx.export_name(id).is_some()
|
||||
},
|
||||
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
@ -287,7 +264,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
|
|||
return tcx.item_name(def_id).to_string();
|
||||
}
|
||||
|
||||
if let Some(name) = tcx.export_name(def_id) {
|
||||
if let Some(name) = tcx.trans_fn_attrs(def_id).export_name {
|
||||
// Use provided name
|
||||
return name.to_string();
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ use std::fs::File;
|
|||
use std::path::Path;
|
||||
use std::sync::mpsc;
|
||||
|
||||
use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
|
||||
use rustc_data_structures::owning_ref::OwningRef;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use ar::{Archive, Builder, Header};
|
||||
use flate2::Compression;
|
||||
|
@ -44,9 +44,12 @@ use rustc::middle::cstore::EncodedMetadata;
|
|||
use rustc::middle::cstore::MetadataLoader;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc_back::target::Target;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_mir::monomorphize::collector;
|
||||
use link::{build_link_meta, out_filename};
|
||||
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
pub trait TransCrate {
|
||||
fn init(&self, _sess: &Session) {}
|
||||
fn print(&self, _req: PrintRequest, _sess: &Session) {}
|
||||
|
@ -119,7 +122,7 @@ impl MetadataLoader for DummyMetadataLoader {
|
|||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
) -> Result<MetadataRef, String> {
|
||||
bug!("DummyMetadataLoader::get_rlib_metadata");
|
||||
}
|
||||
|
||||
|
@ -127,7 +130,7 @@ impl MetadataLoader for DummyMetadataLoader {
|
|||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
) -> Result<MetadataRef, String> {
|
||||
bug!("DummyMetadataLoader::get_dylib_metadata");
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +138,7 @@ impl MetadataLoader for DummyMetadataLoader {
|
|||
pub struct NoLlvmMetadataLoader;
|
||||
|
||||
impl MetadataLoader for NoLlvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
|
||||
let file = File::open(filename)
|
||||
.map_err(|e| format!("metadata file open err: {:?}", e))?;
|
||||
let mut archive = Archive::new(file);
|
||||
|
@ -147,7 +150,7 @@ impl MetadataLoader for NoLlvmMetadataLoader {
|
|||
let mut buf = Vec::new();
|
||||
io::copy(&mut entry, &mut buf).unwrap();
|
||||
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
|
||||
return Ok(buf.map_owner_box().erase_owner());
|
||||
return Ok(rustc_erase_owner!(buf.map_owner_box()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,7 +161,7 @@ impl MetadataLoader for NoLlvmMetadataLoader {
|
|||
&self,
|
||||
_target: &Target,
|
||||
_filename: &Path,
|
||||
) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
) -> Result<MetadataRef, String> {
|
||||
// FIXME: Support reading dylibs from llvm enabled rustc
|
||||
self.get_rlib_metadata(_target, _filename)
|
||||
}
|
||||
|
@ -198,8 +201,9 @@ impl TransCrate for MetadataOnlyTransCrate {
|
|||
|
||||
fn provide(&self, providers: &mut Providers) {
|
||||
::symbol_names::provide(providers);
|
||||
providers.target_features_enabled = |_tcx, _id| {
|
||||
Lrc::new(Vec::new()) // Just a dummy
|
||||
|
||||
providers.target_features_whitelist = |_tcx, _cnum| {
|
||||
Lrc::new(FxHashSet()) // Just a dummy
|
||||
};
|
||||
}
|
||||
fn provide_extern(&self, _providers: &mut Providers) {}
|
||||
|
@ -233,12 +237,8 @@ impl TransCrate for MetadataOnlyTransCrate {
|
|||
MonoItem::Fn(inst) => {
|
||||
let def_id = inst.def_id();
|
||||
if def_id.is_local() {
|
||||
let _ = tcx.export_name(def_id);
|
||||
let _ = tcx.contains_extern_indicator(def_id);
|
||||
let _ = inst.def.is_inline(tcx);
|
||||
let attrs = inst.def.attrs(tcx);
|
||||
let _ =
|
||||
::syntax::attr::find_inline_attr(Some(tcx.sess.diagnostic()), &attrs);
|
||||
let _ = tcx.trans_fn_attrs(def_id);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -255,7 +255,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let opt_trait_ref = match obligation.predicate {
|
||||
ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref(self.tcx)),
|
||||
ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()),
|
||||
ty::Predicate::Equate(..) => None,
|
||||
ty::Predicate::Subtype(..) => None,
|
||||
ty::Predicate::RegionOutlives(..) => None,
|
||||
ty::Predicate::TypeOutlives(..) => None,
|
||||
|
|
|
@ -635,7 +635,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::Subtype(..) |
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
|
|
|
@ -30,25 +30,29 @@ use constrained_type_params as ctp;
|
|||
use middle::lang_items::SizedTraitLangItem;
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::resolve_lifetime as rl;
|
||||
use rustc::mir::mono::Linkage;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{ToPredicate, ReprOptions};
|
||||
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
|
||||
use syntax::{abi, ast};
|
||||
use syntax::ast::MetaItemKind;
|
||||
use syntax::attr::{InlineAttr, list_contains_name, mark_used};
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax::symbol::{Symbol, keywords};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use rustc::hir::{self, map as hir_map};
|
||||
use rustc::hir::{self, map as hir_map, TransFnAttrs, TransFnAttrFlags, Unsafety};
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Main entry point
|
||||
|
@ -71,6 +75,7 @@ pub fn provide(providers: &mut Providers) {
|
|||
impl_trait_ref,
|
||||
impl_polarity,
|
||||
is_foreign_item,
|
||||
trans_fn_attrs,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
@ -1723,3 +1728,186 @@ fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
_ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id)
|
||||
}
|
||||
}
|
||||
|
||||
fn from_target_feature(
|
||||
tcx: TyCtxt,
|
||||
attr: &ast::Attribute,
|
||||
whitelist: &FxHashSet<String>,
|
||||
target_features: &mut Vec<Symbol>,
|
||||
) {
|
||||
let list = match attr.meta_item_list() {
|
||||
Some(list) => list,
|
||||
None => {
|
||||
let msg = "#[target_feature] attribute must be of the form \
|
||||
#[target_feature(..)]";
|
||||
tcx.sess.span_err(attr.span, &msg);
|
||||
return
|
||||
}
|
||||
};
|
||||
|
||||
for item in list {
|
||||
if !item.check_name("enable") {
|
||||
let msg = "#[target_feature(..)] only accepts sub-keys of `enable` \
|
||||
currently";
|
||||
tcx.sess.span_err(item.span, &msg);
|
||||
continue
|
||||
}
|
||||
let value = match item.value_str() {
|
||||
Some(list) => list,
|
||||
None => {
|
||||
let msg = "#[target_feature] attribute must be of the form \
|
||||
#[target_feature(enable = \"..\")]";
|
||||
tcx.sess.span_err(item.span, &msg);
|
||||
continue
|
||||
}
|
||||
};
|
||||
let value = value.as_str();
|
||||
for feature in value.split(',') {
|
||||
if whitelist.contains(feature) {
|
||||
target_features.push(Symbol::intern(feature));
|
||||
continue
|
||||
}
|
||||
|
||||
let msg = format!("the feature named `{}` is not valid for \
|
||||
this target", feature);
|
||||
let mut err = tcx.sess.struct_span_err(item.span, &msg);
|
||||
|
||||
if feature.starts_with("+") {
|
||||
let valid = whitelist.contains(&feature[1..]);
|
||||
if valid {
|
||||
err.help("consider removing the leading `+` in the feature name");
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn linkage_by_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, name: &str) -> Linkage {
|
||||
use rustc::mir::mono::Linkage::*;
|
||||
|
||||
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
|
||||
// applicable to variable declarations and may not really make sense for
|
||||
// Rust code in the first place but whitelist them anyway and trust that
|
||||
// the user knows what s/he's doing. Who knows, unanticipated use cases
|
||||
// may pop up in the future.
|
||||
//
|
||||
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
|
||||
// and don't have to be, LLVM treats them as no-ops.
|
||||
match name {
|
||||
"appending" => Appending,
|
||||
"available_externally" => AvailableExternally,
|
||||
"common" => Common,
|
||||
"extern_weak" => ExternalWeak,
|
||||
"external" => External,
|
||||
"internal" => Internal,
|
||||
"linkonce" => LinkOnceAny,
|
||||
"linkonce_odr" => LinkOnceODR,
|
||||
"private" => Private,
|
||||
"weak" => WeakAny,
|
||||
"weak_odr" => WeakODR,
|
||||
_ => {
|
||||
let span = tcx.hir.span_if_local(def_id);
|
||||
if let Some(span) = span {
|
||||
tcx.sess.span_fatal(span, "invalid linkage specified")
|
||||
} else {
|
||||
tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> TransFnAttrs {
|
||||
let attrs = tcx.get_attrs(id);
|
||||
|
||||
let mut trans_fn_attrs = TransFnAttrs::new();
|
||||
|
||||
let whitelist = tcx.target_features_whitelist(LOCAL_CRATE);
|
||||
|
||||
for attr in attrs.iter() {
|
||||
if attr.check_name("cold") {
|
||||
trans_fn_attrs.flags |= TransFnAttrFlags::COLD;
|
||||
} else if attr.check_name("allocator") {
|
||||
trans_fn_attrs.flags |= TransFnAttrFlags::ALLOCATOR;
|
||||
} else if attr.check_name("unwind") {
|
||||
trans_fn_attrs.flags |= TransFnAttrFlags::UNWIND;
|
||||
} else if attr.check_name("rustc_allocator_nounwind") {
|
||||
trans_fn_attrs.flags |= TransFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND;
|
||||
} else if attr.check_name("naked") {
|
||||
trans_fn_attrs.flags |= TransFnAttrFlags::NAKED;
|
||||
} else if attr.check_name("no_mangle") {
|
||||
trans_fn_attrs.flags |= TransFnAttrFlags::NO_MANGLE;
|
||||
} else if attr.check_name("rustc_std_internal_symbol") {
|
||||
trans_fn_attrs.flags |= TransFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||
} else if attr.check_name("inline") {
|
||||
trans_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
|
||||
if attr.path != "inline" {
|
||||
return ia;
|
||||
}
|
||||
let meta = match attr.meta() {
|
||||
Some(meta) => meta.node,
|
||||
None => return ia,
|
||||
};
|
||||
match meta {
|
||||
MetaItemKind::Word => {
|
||||
mark_used(attr);
|
||||
InlineAttr::Hint
|
||||
}
|
||||
MetaItemKind::List(ref items) => {
|
||||
mark_used(attr);
|
||||
if items.len() != 1 {
|
||||
span_err!(tcx.sess.diagnostic(), attr.span, E0534,
|
||||
"expected one argument");
|
||||
InlineAttr::None
|
||||
} else if list_contains_name(&items[..], "always") {
|
||||
InlineAttr::Always
|
||||
} else if list_contains_name(&items[..], "never") {
|
||||
InlineAttr::Never
|
||||
} else {
|
||||
span_err!(tcx.sess.diagnostic(), items[0].span, E0535,
|
||||
"invalid argument");
|
||||
|
||||
InlineAttr::None
|
||||
}
|
||||
}
|
||||
_ => ia,
|
||||
}
|
||||
});
|
||||
} else if attr.check_name("export_name") {
|
||||
if let s @ Some(_) = attr.value_str() {
|
||||
trans_fn_attrs.export_name = s;
|
||||
} else {
|
||||
struct_span_err!(tcx.sess, attr.span, E0558,
|
||||
"export_name attribute has invalid format")
|
||||
.span_label(attr.span, "did you mean #[export_name=\"*\"]?")
|
||||
.emit();
|
||||
}
|
||||
} else if attr.check_name("target_feature") {
|
||||
if let Some(val) = attr.value_str() {
|
||||
for feat in val.as_str().split(",").map(|f| f.trim()) {
|
||||
if !feat.is_empty() && !feat.contains('\0') {
|
||||
trans_fn_attrs.target_features.push(Symbol::intern(feat));
|
||||
}
|
||||
}
|
||||
let msg = "#[target_feature = \"..\"] is deprecated and will \
|
||||
eventually be removed, use \
|
||||
#[target_feature(enable = \"..\")] instead";
|
||||
tcx.sess.span_warn(attr.span, &msg);
|
||||
continue
|
||||
}
|
||||
|
||||
if tcx.fn_sig(id).unsafety() == Unsafety::Normal {
|
||||
let msg = "#[target_feature(..)] can only be applied to \
|
||||
`unsafe` function";
|
||||
tcx.sess.span_err(attr.span, msg);
|
||||
}
|
||||
from_target_feature(tcx, attr, &whitelist, &mut trans_fn_attrs.target_features);
|
||||
} else if attr.check_name("linkage") {
|
||||
if let Some(val) = attr.value_str() {
|
||||
trans_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trans_fn_attrs
|
||||
}
|
||||
|
|
|
@ -3705,6 +3705,98 @@ match r {
|
|||
```
|
||||
"##,
|
||||
|
||||
E0534: r##"
|
||||
The `inline` attribute was malformed.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```ignore (compile_fail not working here; see Issue #43707)
|
||||
#[inline()] // error: expected one argument
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
The parenthesized `inline` attribute requires the parameter to be specified:
|
||||
|
||||
```
|
||||
#[inline(always)]
|
||||
fn something() {}
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```
|
||||
#[inline(never)]
|
||||
fn something() {}
|
||||
```
|
||||
|
||||
Alternatively, a paren-less version of the attribute may be used to hint the
|
||||
compiler about inlining opportunity:
|
||||
|
||||
```
|
||||
#[inline]
|
||||
fn something() {}
|
||||
```
|
||||
|
||||
For more information about the inline attribute, read:
|
||||
https://doc.rust-lang.org/reference.html#inline-attributes
|
||||
"##,
|
||||
|
||||
E0535: r##"
|
||||
An unknown argument was given to the `inline` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```ignore (compile_fail not working here; see Issue #43707)
|
||||
#[inline(unknown)] // error: invalid argument
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
The `inline` attribute only supports two arguments:
|
||||
|
||||
* always
|
||||
* never
|
||||
|
||||
All other arguments given to the `inline` attribute will return this error.
|
||||
Example:
|
||||
|
||||
```
|
||||
#[inline(never)] // ok!
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
For more information about the inline attribute, https:
|
||||
read://doc.rust-lang.org/reference.html#inline-attributes
|
||||
"##,
|
||||
|
||||
E0558: r##"
|
||||
The `export_name` attribute was malformed.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail)
|
||||
#[export_name] // error: export_name attribute has invalid format
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
The `export_name` attribute expects a string in order to determine the name of
|
||||
the exported symbol. Example:
|
||||
|
||||
```
|
||||
#[export_name = "some_function"] // ok!
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0559: r##"
|
||||
An unknown field was specified into an enum's structure variant.
|
||||
|
||||
|
|
|
@ -1535,7 +1535,6 @@ impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
|
|||
|
||||
match *self {
|
||||
Predicate::Trait(ref pred) => pred.clean(cx),
|
||||
Predicate::Equate(ref pred) => pred.clean(cx),
|
||||
Predicate::Subtype(ref pred) => pred.clean(cx),
|
||||
Predicate::RegionOutlives(ref pred) => pred.clean(cx),
|
||||
Predicate::TypeOutlives(ref pred) => pred.clean(cx),
|
||||
|
@ -1557,16 +1556,6 @@ impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> WherePredicate {
|
||||
let ty::EquatePredicate(ref lhs, ref rhs) = *self;
|
||||
WherePredicate::EqPredicate {
|
||||
lhs: lhs.clean(cx),
|
||||
rhs: rhs.clean(cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
|
||||
fn clean(&self, _cx: &DocContext) -> WherePredicate {
|
||||
panic!("subtype predicates are an internal rustc artifact \
|
||||
|
|
|
@ -28,6 +28,7 @@ pub struct Page<'a> {
|
|||
pub root_path: &'a str,
|
||||
pub description: &'a str,
|
||||
pub keywords: &'a str,
|
||||
pub resource_suffix: &'a str,
|
||||
}
|
||||
|
||||
pub fn render<T: fmt::Display, S: fmt::Display>(
|
||||
|
@ -47,12 +48,13 @@ r##"<!DOCTYPE html>
|
|||
|
||||
<title>{title}</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}normalize.css">
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}rustdoc.css" id="mainThemeStyle">
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}normalize{suffix}.css">
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}rustdoc{suffix}.css"
|
||||
id="mainThemeStyle">
|
||||
{themes}
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}dark.css">
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}main.css" id="themeStyle">
|
||||
<script src="{root_path}storage.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}dark{suffix}.css">
|
||||
<link rel="stylesheet" type="text/css" href="{root_path}main{suffix}.css" id="themeStyle">
|
||||
<script src="{root_path}storage{suffix}.js"></script>
|
||||
{css_extension}
|
||||
|
||||
{favicon}
|
||||
|
@ -76,11 +78,11 @@ r##"<!DOCTYPE html>
|
|||
|
||||
<div class="theme-picker">
|
||||
<button id="theme-picker" aria-label="Pick another theme!">
|
||||
<img src="{root_path}brush.svg" width="18" alt="Pick another theme!">
|
||||
<img src="{root_path}brush{suffix}.svg" width="18" alt="Pick another theme!">
|
||||
</button>
|
||||
<div id="theme-choices"></div>
|
||||
</div>
|
||||
<script src="{root_path}theme.js"></script>
|
||||
<script src="{root_path}theme{suffix}.js"></script>
|
||||
<nav class="sub">
|
||||
<form class="search-form js-only">
|
||||
<div class="search-container">
|
||||
|
@ -153,13 +155,14 @@ r##"<!DOCTYPE html>
|
|||
window.rootPath = "{root_path}";
|
||||
window.currentCrate = "{krate}";
|
||||
</script>
|
||||
<script src="{root_path}main.js"></script>
|
||||
<script src="{root_path}main{suffix}.js"></script>
|
||||
<script defer src="{root_path}search-index.js"></script>
|
||||
</body>
|
||||
</html>"##,
|
||||
css_extension = if css_file_extension {
|
||||
format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}theme.css\">",
|
||||
root_path = page.root_path)
|
||||
format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}theme{suffix}.css\">",
|
||||
root_path = page.root_path,
|
||||
suffix=page.resource_suffix)
|
||||
} else {
|
||||
"".to_owned()
|
||||
},
|
||||
|
@ -191,8 +194,10 @@ r##"<!DOCTYPE html>
|
|||
.filter_map(|t| t.file_stem())
|
||||
.filter_map(|t| t.to_str())
|
||||
.map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}">"#,
|
||||
page.root_path, t))
|
||||
page.root_path,
|
||||
t.replace(".css", &format!("{}.css", page.resource_suffix))))
|
||||
.collect::<String>(),
|
||||
suffix=page.resource_suffix,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
//! for creating the corresponding search index and source file renderings.
|
||||
//! These threads are not parallelized (they haven't been a bottleneck yet), and
|
||||
//! both occur before the crate is rendered.
|
||||
|
||||
pub use self::ExternalLocation::*;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
@ -128,6 +129,9 @@ pub struct SharedContext {
|
|||
pub sort_modules_alphabetically: bool,
|
||||
/// Additional themes to be added to the generated docs.
|
||||
pub themes: Vec<PathBuf>,
|
||||
/// Suffix to be added on resource files (if suffix is "-v2" then "main.css" becomes
|
||||
/// "main-v2.css").
|
||||
pub resource_suffix: String,
|
||||
}
|
||||
|
||||
impl SharedContext {
|
||||
|
@ -492,6 +496,7 @@ pub fn run(mut krate: clean::Crate,
|
|||
external_html: &ExternalHtml,
|
||||
playground_url: Option<String>,
|
||||
dst: PathBuf,
|
||||
resource_suffix: String,
|
||||
passes: FxHashSet<String>,
|
||||
css_file_extension: Option<PathBuf>,
|
||||
renderinfo: RenderInfo,
|
||||
|
@ -520,6 +525,7 @@ pub fn run(mut krate: clean::Crate,
|
|||
created_dirs: RefCell::new(FxHashSet()),
|
||||
sort_modules_alphabetically,
|
||||
themes,
|
||||
resource_suffix,
|
||||
};
|
||||
|
||||
// If user passed in `--playground-url` arg, we fill in crate name here
|
||||
|
@ -734,7 +740,7 @@ fn write_shared(cx: &Context,
|
|||
// Add all the static files. These may already exist, but we just
|
||||
// overwrite them anyway to make sure that they're fresh and up-to-date.
|
||||
|
||||
write(cx.dst.join("rustdoc.css"),
|
||||
write(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/rustdoc.css"))?;
|
||||
|
||||
// To avoid "main.css" to be overwritten, we'll first run over the received themes and only
|
||||
|
@ -746,16 +752,19 @@ fn write_shared(cx: &Context,
|
|||
|
||||
let mut f = try_err!(File::open(&entry), &entry);
|
||||
try_err!(f.read_to_end(&mut content), &entry);
|
||||
write(cx.dst.join(try_none!(entry.file_name(), &entry)), content.as_slice())?;
|
||||
themes.insert(try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry).to_owned());
|
||||
let theme = try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry);
|
||||
let extension = try_none!(try_none!(entry.extension(), &entry).to_str(), &entry);
|
||||
write(cx.dst.join(format!("{}{}.{}", theme, cx.shared.resource_suffix, extension)),
|
||||
content.as_slice())?;
|
||||
themes.insert(theme.to_owned());
|
||||
}
|
||||
|
||||
write(cx.dst.join("brush.svg"),
|
||||
write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/brush.svg"))?;
|
||||
write(cx.dst.join("main.css"),
|
||||
write(cx.dst.join(&format!("main{}.css", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/themes/main.css"))?;
|
||||
themes.insert("main".to_owned());
|
||||
write(cx.dst.join("dark.css"),
|
||||
write(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/themes/dark.css"))?;
|
||||
themes.insert("dark".to_owned());
|
||||
|
||||
|
@ -763,7 +772,8 @@ fn write_shared(cx: &Context,
|
|||
themes.sort();
|
||||
// To avoid theme switch latencies as much as possible, we put everything theme related
|
||||
// at the beginning of the html files into another js file.
|
||||
write(cx.dst.join("theme.js"), format!(
|
||||
write(cx.dst.join(&format!("theme{}.js", cx.shared.resource_suffix)),
|
||||
format!(
|
||||
r#"var themes = document.getElementById("theme-choices");
|
||||
var themePicker = document.getElementById("theme-picker");
|
||||
themePicker.onclick = function() {{
|
||||
|
@ -785,19 +795,28 @@ themePicker.onclick = function() {{
|
|||
}};
|
||||
themes.appendChild(but);
|
||||
}});
|
||||
"#, themes.iter()
|
||||
.map(|s| format!("\"{}\"", s))
|
||||
.collect::<Vec<String>>()
|
||||
.join(",")).as_bytes())?;
|
||||
"#,
|
||||
themes.iter()
|
||||
.map(|s| format!("\"{}\"", s))
|
||||
.collect::<Vec<String>>()
|
||||
.join(",")).as_bytes(),
|
||||
)?;
|
||||
|
||||
write(cx.dst.join("main.js"), include_bytes!("static/main.js"))?;
|
||||
write(cx.dst.join("storage.js"), include_bytes!("static/storage.js"))?;
|
||||
write(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/main.js"))?;
|
||||
|
||||
{
|
||||
let mut data = format!("var resourcesSuffix = \"{}\";\n",
|
||||
cx.shared.resource_suffix).into_bytes();
|
||||
data.extend_from_slice(include_bytes!("static/storage.js"));
|
||||
write(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)), &data)?;
|
||||
}
|
||||
|
||||
if let Some(ref css) = cx.shared.css_file_extension {
|
||||
let out = cx.dst.join("theme.css");
|
||||
let out = cx.dst.join(&format!("theme{}.css", cx.shared.resource_suffix));
|
||||
try_err!(fs::copy(css, out), css);
|
||||
}
|
||||
write(cx.dst.join("normalize.css"),
|
||||
write(cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)),
|
||||
include_bytes!("static/normalize.css"))?;
|
||||
write(cx.dst.join("FiraSans-Regular.woff"),
|
||||
include_bytes!("static/FiraSans-Regular.woff"))?;
|
||||
|
@ -1084,6 +1103,7 @@ impl<'a> SourceCollector<'a> {
|
|||
root_path: &root_path,
|
||||
description: &desc,
|
||||
keywords: BASIC_KEYWORDS,
|
||||
resource_suffix: &self.scx.resource_suffix,
|
||||
};
|
||||
layout::render(&mut w, &self.scx.layout,
|
||||
&page, &(""), &Source(contents),
|
||||
|
@ -1446,6 +1466,7 @@ impl Context {
|
|||
title: &title,
|
||||
description: &desc,
|
||||
keywords: &keywords,
|
||||
resource_suffix: &self.shared.resource_suffix,
|
||||
};
|
||||
|
||||
reset_ids(true);
|
||||
|
|
|
@ -41,7 +41,9 @@ function getCurrentValue(name) {
|
|||
}
|
||||
|
||||
function switchTheme(styleElem, mainStyleElem, newTheme) {
|
||||
var newHref = mainStyleElem.href.replace("rustdoc.css", newTheme + ".css");
|
||||
var fullBasicCss = "rustdoc" + resourcesSuffix + ".css";
|
||||
var fullNewTheme = newTheme + resourcesSuffix + ".css";
|
||||
var newHref = mainStyleElem.href.replace(fullBasicCss, fullNewTheme);
|
||||
var found = false;
|
||||
|
||||
if (savedHref.length === 0) {
|
||||
|
|
|
@ -261,6 +261,13 @@ pub fn opts() -> Vec<RustcOptGroup> {
|
|||
"check if given theme is valid",
|
||||
"FILES")
|
||||
}),
|
||||
unstable("resource-suffix", |o| {
|
||||
o.optopt("",
|
||||
"resource-suffix",
|
||||
"suffix to add to CSS and JavaScript files, e.g. \"main.css\" will become \
|
||||
\"main-suffix.css\"",
|
||||
"PATH")
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -417,6 +424,7 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
let display_warnings = matches.opt_present("display-warnings");
|
||||
let linker = matches.opt_str("linker").map(PathBuf::from);
|
||||
let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
|
||||
let resource_suffix = matches.opt_str("resource-suffix");
|
||||
|
||||
match (should_test, markdown_input) {
|
||||
(true, true) => {
|
||||
|
@ -442,6 +450,7 @@ pub fn main_args(args: &[String]) -> isize {
|
|||
Some("html") | None => {
|
||||
html::render::run(krate, &external_html, playground_url,
|
||||
output.unwrap_or(PathBuf::from("doc")),
|
||||
resource_suffix.unwrap_or(String::new()),
|
||||
passes.into_iter().collect(),
|
||||
css_file_extension,
|
||||
renderinfo,
|
||||
|
|
|
@ -1080,14 +1080,45 @@ impl fmt::Display for ExitStatus {
|
|||
}
|
||||
}
|
||||
|
||||
/// This is ridiculously unstable, as it's a completely-punted-upon part
|
||||
/// of the `?`-in-`main` RFC. It's here only to allow experimenting with
|
||||
/// returning a code directly from main. It will definitely change
|
||||
/// drastically before being stabilized, if it doesn't just get deleted.
|
||||
#[doc(hidden)]
|
||||
/// This type represents the status code a process can return to its
|
||||
/// parent under normal termination.
|
||||
///
|
||||
/// Numeric values used in this type don't have portable meanings, and
|
||||
/// different platforms may mask different amounts of them.
|
||||
///
|
||||
/// For the platform's canonical successful and unsuccessful codes, see
|
||||
/// the [`SUCCESS`] and [`FAILURE`] associated items.
|
||||
///
|
||||
/// [`SUCCESS`]: #associatedconstant.SUCCESS
|
||||
/// [`FAILURE`]: #associatedconstant.FAILURE
|
||||
///
|
||||
/// **Warning**: While various forms of this were discussed in [RFC #1937],
|
||||
/// it was ultimately cut from that RFC, and thus this type is more subject
|
||||
/// to change even than the usual unstable item churn.
|
||||
///
|
||||
/// [RFC #1937]: https://github.com/rust-lang/rfcs/pull/1937
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "43301")]
|
||||
pub struct ExitCode(pub i32);
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
pub struct ExitCode(imp::ExitCode);
|
||||
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
impl ExitCode {
|
||||
/// The canonical ExitCode for successful termination on this platform.
|
||||
///
|
||||
/// Note that a `()`-returning `main` implicitly results in a successful
|
||||
/// termination, so there's no need to return this from `main` unless
|
||||
/// you're also returning other possible codes.
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
pub const SUCCESS: ExitCode = ExitCode(imp::ExitCode::SUCCESS);
|
||||
|
||||
/// The canonical ExitCode for unsuccessful termination on this platform.
|
||||
///
|
||||
/// If you're only returning this and `SUCCESS` from `main`, consider
|
||||
/// instead returning `Err(_)` and `Ok(())` respectively, which will
|
||||
/// return the same codes (but will also `eprintln!` the error).
|
||||
#[unstable(feature = "process_exitcode_placeholder", issue = "48711")]
|
||||
pub const FAILURE: ExitCode = ExitCode(imp::ExitCode::FAILURE);
|
||||
}
|
||||
|
||||
impl Child {
|
||||
/// Forces the child to exit. This is equivalent to sending a
|
||||
|
@ -1401,18 +1432,6 @@ pub fn id() -> u32 {
|
|||
::sys::os::getpid()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
mod exit {
|
||||
pub const SUCCESS: i32 = 0;
|
||||
pub const FAILURE: i32 = 1;
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod exit {
|
||||
use libc;
|
||||
pub const SUCCESS: i32 = libc::EXIT_SUCCESS;
|
||||
pub const FAILURE: i32 = libc::EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/// A trait for implementing arbitrary return types in the `main` function.
|
||||
///
|
||||
/// The c-main function only supports to return integers as return type.
|
||||
|
@ -1433,18 +1452,15 @@ pub trait Termination {
|
|||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
impl Termination for () {
|
||||
fn report(self) -> i32 { exit::SUCCESS }
|
||||
fn report(self) -> i32 { ExitCode::SUCCESS.report() }
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
impl<E: fmt::Debug> Termination for Result<(), E> {
|
||||
fn report(self) -> i32 {
|
||||
match self {
|
||||
Ok(val) => val.report(),
|
||||
Err(err) => {
|
||||
eprintln!("Error: {:?}", err);
|
||||
exit::FAILURE
|
||||
}
|
||||
Ok(()) => ().report(),
|
||||
Err(err) => Err::<!, _>(err).report(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1459,15 +1475,14 @@ impl<E: fmt::Debug> Termination for Result<!, E> {
|
|||
fn report(self) -> i32 {
|
||||
let Err(err) = self;
|
||||
eprintln!("Error: {:?}", err);
|
||||
exit::FAILURE
|
||||
ExitCode::FAILURE.report()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "termination_trait_lib", issue = "43301")]
|
||||
impl Termination for ExitCode {
|
||||
fn report(self) -> i32 {
|
||||
let ExitCode(code) = self;
|
||||
code
|
||||
self.0.as_i32()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,18 @@ impl fmt::Display for ExitStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(bool);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(false);
|
||||
pub const FAILURE: ExitCode = ExitCode(true);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Process(Void);
|
||||
|
||||
impl Process {
|
||||
|
|
|
@ -13,6 +13,7 @@ use ffi::OsStr;
|
|||
use os::unix::ffi::OsStrExt;
|
||||
use fmt;
|
||||
use io::{self, Error, ErrorKind};
|
||||
use libc::{EXIT_SUCCESS, EXIT_FAILURE};
|
||||
use path::{Path, PathBuf};
|
||||
use sys::fd::FileDesc;
|
||||
use sys::fs::{File, OpenOptions};
|
||||
|
@ -480,6 +481,18 @@ impl fmt::Display for ExitStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(u8);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
|
||||
pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
/// The unique id of the process (this should never be negative).
|
||||
pub struct Process {
|
||||
pid: usize,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub use self::process_common::{Command, ExitStatus, Stdio, StdioPipes};
|
||||
pub use self::process_common::{Command, ExitStatus, ExitCode, Stdio, StdioPipes};
|
||||
pub use self::process_inner::Process;
|
||||
|
||||
mod process_common;
|
||||
|
|
|
@ -13,7 +13,7 @@ use os::unix::prelude::*;
|
|||
use ffi::{OsString, OsStr, CString, CStr};
|
||||
use fmt;
|
||||
use io;
|
||||
use libc::{self, c_int, gid_t, uid_t, c_char};
|
||||
use libc::{self, c_int, gid_t, uid_t, c_char, EXIT_SUCCESS, EXIT_FAILURE};
|
||||
use ptr;
|
||||
use sys::fd::FileDesc;
|
||||
use sys::fs::{File, OpenOptions};
|
||||
|
@ -393,6 +393,18 @@ impl fmt::Display for ExitStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(u8);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
|
||||
pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, not(target_os = "emscripten")))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -129,6 +129,18 @@ impl fmt::Display for ExitStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(bool);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(false);
|
||||
pub const FAILURE: ExitCode = ExitCode(true);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Process(Void);
|
||||
|
||||
impl Process {
|
||||
|
|
|
@ -18,7 +18,7 @@ use ffi::{OsString, OsStr};
|
|||
use fmt;
|
||||
use fs;
|
||||
use io::{self, Error, ErrorKind};
|
||||
use libc::c_void;
|
||||
use libc::{c_void, EXIT_SUCCESS, EXIT_FAILURE};
|
||||
use mem;
|
||||
use os::windows::ffi::OsStrExt;
|
||||
use path::Path;
|
||||
|
@ -408,6 +408,18 @@ impl fmt::Display for ExitStatus {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(c::DWORD);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(EXIT_SUCCESS as _);
|
||||
pub const FAILURE: ExitCode = ExitCode(EXIT_FAILURE as _);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
fn zeroed_startupinfo() -> c::STARTUPINFO {
|
||||
c::STARTUPINFO {
|
||||
cb: 0,
|
||||
|
|
|
@ -520,7 +520,7 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
|
|||
first_attr_value_str_by_name(attrs, "crate_name")
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, Hash, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub enum InlineAttr {
|
||||
None,
|
||||
Hint,
|
||||
|
@ -528,43 +528,6 @@ pub enum InlineAttr {
|
|||
Never,
|
||||
}
|
||||
|
||||
/// Determine what `#[inline]` attribute is present in `attrs`, if any.
|
||||
pub fn find_inline_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> InlineAttr {
|
||||
attrs.iter().fold(InlineAttr::None, |ia, attr| {
|
||||
if attr.path != "inline" {
|
||||
return ia;
|
||||
}
|
||||
let meta = match attr.meta() {
|
||||
Some(meta) => meta.node,
|
||||
None => return ia,
|
||||
};
|
||||
match meta {
|
||||
MetaItemKind::Word => {
|
||||
mark_used(attr);
|
||||
InlineAttr::Hint
|
||||
}
|
||||
MetaItemKind::List(ref items) => {
|
||||
mark_used(attr);
|
||||
if items.len() != 1 {
|
||||
diagnostic.map(|d|{ span_err!(d, attr.span, E0534, "expected one argument"); });
|
||||
InlineAttr::None
|
||||
} else if list_contains_name(&items[..], "always") {
|
||||
InlineAttr::Always
|
||||
} else if list_contains_name(&items[..], "never") {
|
||||
InlineAttr::Never
|
||||
} else {
|
||||
diagnostic.map(|d| {
|
||||
span_err!(d, items[0].span, E0535, "invalid argument");
|
||||
});
|
||||
|
||||
InlineAttr::None
|
||||
}
|
||||
}
|
||||
_ => ia,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum UnwindAttr {
|
||||
Allowed,
|
||||
|
@ -610,13 +573,6 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
|
|||
})
|
||||
}
|
||||
|
||||
/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
|
||||
pub fn requests_inline(attrs: &[Attribute]) -> bool {
|
||||
match find_inline_attr(None, attrs) {
|
||||
InlineAttr::Hint | InlineAttr::Always => true,
|
||||
InlineAttr::None | InlineAttr::Never => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) -> bool {
|
||||
|
|
|
@ -37,75 +37,6 @@ More details can be found in [RFC 438].
|
|||
[RFC 438]: https://github.com/rust-lang/rfcs/pull/438
|
||||
"##,
|
||||
|
||||
E0534: r##"
|
||||
The `inline` attribute was malformed.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```ignore (compile_fail not working here; see Issue #43707)
|
||||
#[inline()] // error: expected one argument
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
The parenthesized `inline` attribute requires the parameter to be specified:
|
||||
|
||||
```
|
||||
#[inline(always)]
|
||||
fn something() {}
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
```
|
||||
#[inline(never)]
|
||||
fn something() {}
|
||||
```
|
||||
|
||||
Alternatively, a paren-less version of the attribute may be used to hint the
|
||||
compiler about inlining opportunity:
|
||||
|
||||
```
|
||||
#[inline]
|
||||
fn something() {}
|
||||
```
|
||||
|
||||
For more information about the inline attribute, read:
|
||||
https://doc.rust-lang.org/reference.html#inline-attributes
|
||||
"##,
|
||||
|
||||
E0535: r##"
|
||||
An unknown argument was given to the `inline` attribute.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```ignore (compile_fail not working here; see Issue #43707)
|
||||
#[inline(unknown)] // error: invalid argument
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
The `inline` attribute only supports two arguments:
|
||||
|
||||
* always
|
||||
* never
|
||||
|
||||
All other arguments given to the `inline` attribute will return this error.
|
||||
Example:
|
||||
|
||||
```
|
||||
#[inline(never)] // ok!
|
||||
pub fn something() {}
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
For more information about the inline attribute, https:
|
||||
read://doc.rust-lang.org/reference.html#inline-attributes
|
||||
"##,
|
||||
|
||||
E0536: r##"
|
||||
The `not` cfg-predicate was malformed.
|
||||
|
||||
|
|
2
src/llvm
2
src/llvm
|
@ -1 +1 @@
|
|||
Subproject commit ba2edd794c7def715007931fcd1b4ce62aa711c8
|
||||
Subproject commit 0903c72cbbc3dafcb5c88820e4a8a98c3a764cf3
|
|
@ -1,4 +1,4 @@
|
|||
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
|
||||
# The actual contents of this file do not matter, but to trigger a change on the
|
||||
# build bots then the contents should be changed so git updates the mtime.
|
||||
2018-02-09
|
||||
2018-03-06
|
||||
|
|
|
@ -459,3 +459,10 @@ struct Rls699 {
|
|||
fn new(f: u32) -> Rls699 {
|
||||
Rls699 { fs }
|
||||
}
|
||||
|
||||
fn invalid_tuple_struct_access() {
|
||||
bar.0;
|
||||
|
||||
struct S;
|
||||
S.0;
|
||||
}
|
||||
|
|
|
@ -14,5 +14,5 @@
|
|||
use std::process::ExitCode;
|
||||
|
||||
fn main() -> ExitCode {
|
||||
ExitCode(0)
|
||||
ExitCode::SUCCESS
|
||||
}
|
||||
|
|
|
@ -10,11 +10,13 @@ filetime = "0.1"
|
|||
getopts = "0.2"
|
||||
log = "0.4"
|
||||
regex = "0.2"
|
||||
rustc-serialize = "0.3"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
miow = "0.2"
|
||||
winapi = "0.2"
|
||||
miow = "0.3"
|
||||
winapi = { version = "0.3", features = ["winerror"] }
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use errors::{Error, ErrorKind};
|
||||
use rustc_serialize::json;
|
||||
use serde_json;
|
||||
use std::str::FromStr;
|
||||
use std::path::Path;
|
||||
use runtest::ProcRes;
|
||||
|
@ -17,17 +17,16 @@ use runtest::ProcRes;
|
|||
// These structs are a subset of the ones found in
|
||||
// `syntax::json`.
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable)]
|
||||
#[derive(Deserialize)]
|
||||
struct Diagnostic {
|
||||
message: String,
|
||||
code: Option<DiagnosticCode>,
|
||||
level: String,
|
||||
spans: Vec<DiagnosticSpan>,
|
||||
children: Vec<Diagnostic>,
|
||||
rendered: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Clone)]
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct DiagnosticSpan {
|
||||
file_name: String,
|
||||
line_start: usize,
|
||||
|
@ -40,7 +39,7 @@ struct DiagnosticSpan {
|
|||
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Clone)]
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct DiagnosticSpanMacroExpansion {
|
||||
/// span where macro was applied to generate this code
|
||||
span: DiagnosticSpan,
|
||||
|
@ -49,7 +48,7 @@ struct DiagnosticSpanMacroExpansion {
|
|||
macro_decl_name: String,
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Clone)]
|
||||
#[derive(Deserialize, Clone)]
|
||||
struct DiagnosticCode {
|
||||
/// The code itself.
|
||||
code: String,
|
||||
|
@ -67,7 +66,7 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
|
|||
// The compiler sometimes intermingles non-JSON stuff into the
|
||||
// output. This hack just skips over such lines. Yuck.
|
||||
if line.starts_with('{') {
|
||||
match json::decode::<Diagnostic>(line) {
|
||||
match serde_json::from_str::<Diagnostic>(line) {
|
||||
Ok(diagnostic) => {
|
||||
let mut expected_errors = vec![];
|
||||
push_expected_errors(&mut expected_errors, &diagnostic, &[], file_name);
|
||||
|
|
|
@ -21,8 +21,10 @@ extern crate getopts;
|
|||
extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate rustc_serialize;
|
||||
extern crate regex;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate serde_json;
|
||||
extern crate test;
|
||||
|
||||
use std::env;
|
||||
|
|
|
@ -119,7 +119,7 @@ mod imp {
|
|||
use self::miow::iocp::{CompletionPort, CompletionStatus};
|
||||
use self::miow::pipe::NamedPipe;
|
||||
use self::miow::Overlapped;
|
||||
use self::winapi::ERROR_BROKEN_PIPE;
|
||||
use self::winapi::shared::winerror::ERROR_BROKEN_PIPE;
|
||||
|
||||
struct Pipe<'a> {
|
||||
dst: &'a mut Vec<u8>,
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b55e0fc77590cf5d23a01dedeb2104d8cbb48efc
|
||||
Subproject commit 118e078c5badd520d18b92813fd88789c8d341ab
|
Loading…
Add table
Reference in a new issue