Merge branch 'master' into rustfmt-update
This commit is contained in:
commit
d284815f72
@ -84,7 +84,7 @@ pub fn find(build: &mut Build) {
|
||||
if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
|
||||
cfg.compiler(cc);
|
||||
} else {
|
||||
set_compiler(&mut cfg, "gcc", target, config, build);
|
||||
set_compiler(&mut cfg, Language::C, target, config, build);
|
||||
}
|
||||
|
||||
let compiler = cfg.get_compiler();
|
||||
@ -112,7 +112,7 @@ pub fn find(build: &mut Build) {
|
||||
if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) {
|
||||
cfg.compiler(cxx);
|
||||
} else {
|
||||
set_compiler(&mut cfg, "g++", host, config, build);
|
||||
set_compiler(&mut cfg, Language::CPlusPlus, host, config, build);
|
||||
}
|
||||
let compiler = cfg.get_compiler();
|
||||
build.verbose(&format!("CXX_{} = {:?}", host, compiler.path()));
|
||||
@ -121,7 +121,7 @@ pub fn find(build: &mut Build) {
|
||||
}
|
||||
|
||||
fn set_compiler(cfg: &mut cc::Build,
|
||||
gnu_compiler: &str,
|
||||
compiler: Language,
|
||||
target: Interned<String>,
|
||||
config: Option<&Target>,
|
||||
build: &Build) {
|
||||
@ -132,7 +132,7 @@ fn set_compiler(cfg: &mut cc::Build,
|
||||
t if t.contains("android") => {
|
||||
if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) {
|
||||
let target = target.replace("armv7", "arm");
|
||||
let compiler = format!("{}-{}", target, gnu_compiler);
|
||||
let compiler = format!("{}-{}", target, compiler.clang());
|
||||
cfg.compiler(ndk.join("bin").join(compiler));
|
||||
}
|
||||
}
|
||||
@ -141,6 +141,7 @@ fn set_compiler(cfg: &mut cc::Build,
|
||||
// which is a gcc version from ports, if this is the case.
|
||||
t if t.contains("openbsd") => {
|
||||
let c = cfg.get_compiler();
|
||||
let gnu_compiler = compiler.gcc();
|
||||
if !c.path().ends_with(gnu_compiler) {
|
||||
return
|
||||
}
|
||||
@ -183,3 +184,29 @@ fn set_compiler(cfg: &mut cc::Build,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// The target programming language for a native compiler.
|
||||
enum Language {
|
||||
/// The compiler is targeting C.
|
||||
C,
|
||||
/// The compiler is targeting C++.
|
||||
CPlusPlus,
|
||||
}
|
||||
|
||||
impl Language {
|
||||
/// Obtains the name of a compiler in the GCC collection.
|
||||
fn gcc(self) -> &'static str {
|
||||
match self {
|
||||
Language::C => "gcc",
|
||||
Language::CPlusPlus => "g++",
|
||||
}
|
||||
}
|
||||
|
||||
/// Obtains the name of a compiler in the clang suite.
|
||||
fn clang(self) -> &'static str {
|
||||
match self {
|
||||
Language::C => "clang",
|
||||
Language::CPlusPlus => "clang++",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,21 +5,27 @@ RUN sh /scripts/android-base-apt-get.sh
|
||||
|
||||
COPY scripts/android-ndk.sh /scripts/
|
||||
RUN . /scripts/android-ndk.sh && \
|
||||
download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm 9
|
||||
download_and_make_toolchain android-ndk-r15c-linux-x86_64.zip arm 14
|
||||
|
||||
# Note:
|
||||
# Do not upgrade to `openjdk-9-jre-headless`, as it will cause certificate error
|
||||
# when installing the Android SDK (see PR #45193). This is unfortunate, but
|
||||
# every search result suggested either disabling HTTPS or replacing JDK 9 by
|
||||
# JDK 8 as the solution (e.g. https://stackoverflow.com/q/41421340). :|
|
||||
RUN dpkg --add-architecture i386 && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
libgl1-mesa-glx \
|
||||
libpulse0 \
|
||||
libstdc++6:i386 \
|
||||
openjdk-9-jre-headless \
|
||||
openjdk-8-jre-headless \
|
||||
tzdata
|
||||
|
||||
COPY scripts/android-sdk.sh /scripts/
|
||||
RUN . /scripts/android-sdk.sh && \
|
||||
download_and_create_avd tools_r25.2.5-linux.zip armeabi-v7a 18
|
||||
download_and_create_avd 4333796 armeabi-v7a 18
|
||||
|
||||
ENV PATH=$PATH:/android/sdk/emulator
|
||||
ENV PATH=$PATH:/android/sdk/tools
|
||||
ENV PATH=$PATH:/android/sdk/platform-tools
|
||||
|
||||
@ -27,7 +33,7 @@ ENV TARGETS=arm-linux-androideabi
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=$TARGETS \
|
||||
--arm-linux-androideabi-ndk=/android/ndk/arm-9
|
||||
--arm-linux-androideabi-ndk=/android/ndk/arm-14
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
|
||||
|
@ -5,7 +5,7 @@ RUN sh /scripts/android-base-apt-get.sh
|
||||
|
||||
COPY scripts/android-ndk.sh /scripts/
|
||||
RUN . /scripts/android-ndk.sh && \
|
||||
download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm64 21
|
||||
download_and_make_toolchain android-ndk-r15c-linux-x86_64.zip arm64 21
|
||||
|
||||
ENV PATH=$PATH:/android/ndk/arm64-21/bin
|
||||
|
||||
|
@ -5,17 +5,17 @@ RUN sh /scripts/android-base-apt-get.sh
|
||||
|
||||
COPY scripts/android-ndk.sh /scripts/
|
||||
RUN . /scripts/android-ndk.sh && \
|
||||
download_ndk android-ndk-r13b-linux-x86_64.zip && \
|
||||
make_standalone_toolchain arm 9 && \
|
||||
download_ndk android-ndk-r15c-linux-x86_64.zip && \
|
||||
make_standalone_toolchain arm 14 && \
|
||||
make_standalone_toolchain arm 21 && \
|
||||
remove_ndk
|
||||
|
||||
RUN chmod 777 /android/ndk && \
|
||||
ln -s /android/ndk/arm-21 /android/ndk/arm
|
||||
|
||||
ENV PATH=$PATH:/android/ndk/arm-9/bin
|
||||
ENV PATH=$PATH:/android/ndk/arm-14/bin
|
||||
|
||||
ENV DEP_Z_ROOT=/android/ndk/arm-9/sysroot/usr/
|
||||
ENV DEP_Z_ROOT=/android/ndk/arm-14/sysroot/usr/
|
||||
|
||||
ENV HOSTS=armv7-linux-androideabi
|
||||
|
||||
@ -27,18 +27,18 @@ ENV RUST_CONFIGURE_ARGS \
|
||||
--enable-extended \
|
||||
--enable-cargo-openssl-static
|
||||
|
||||
# We support api level 9, but api level 21 is required to build llvm. To
|
||||
# We support api level 14, but api level 21 is required to build llvm. To
|
||||
# overcome this problem we use a ndk with api level 21 to build llvm and then
|
||||
# switch to a ndk with api level 9 to complete the build. When the linker is
|
||||
# switch to a ndk with api level 14 to complete the build. When the linker is
|
||||
# invoked there are missing symbols (like sigsetempty, not available with api
|
||||
# level 9), the default linker behavior is to generate an error, to allow the
|
||||
# level 14), the default linker behavior is to generate an error, to allow the
|
||||
# build to finish we use --warn-unresolved-symbols. Note that the missing
|
||||
# symbols does not affect std, only the compiler (llvm) and cargo (openssl).
|
||||
ENV SCRIPT \
|
||||
python2.7 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
|
||||
(export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
|
||||
rm /android/ndk/arm && \
|
||||
ln -s /android/ndk/arm-9 /android/ndk/arm && \
|
||||
ln -s /android/ndk/arm-14 /android/ndk/arm && \
|
||||
python2.7 ../x.py dist --host $HOSTS --target $HOSTS)
|
||||
|
||||
COPY scripts/sccache.sh /scripts/
|
||||
|
@ -5,17 +5,17 @@ RUN sh /scripts/android-base-apt-get.sh
|
||||
|
||||
COPY scripts/android-ndk.sh /scripts/
|
||||
RUN . /scripts/android-ndk.sh && \
|
||||
download_ndk android-ndk-r13b-linux-x86_64.zip && \
|
||||
make_standalone_toolchain x86 9 && \
|
||||
download_ndk android-ndk-r15c-linux-x86_64.zip && \
|
||||
make_standalone_toolchain x86 14 && \
|
||||
make_standalone_toolchain x86 21 && \
|
||||
remove_ndk
|
||||
|
||||
RUN chmod 777 /android/ndk && \
|
||||
ln -s /android/ndk/x86-21 /android/ndk/x86
|
||||
|
||||
ENV PATH=$PATH:/android/ndk/x86-9/bin
|
||||
ENV PATH=$PATH:/android/ndk/x86-14/bin
|
||||
|
||||
ENV DEP_Z_ROOT=/android/ndk/x86-9/sysroot/usr/
|
||||
ENV DEP_Z_ROOT=/android/ndk/x86-14/sysroot/usr/
|
||||
|
||||
ENV HOSTS=i686-linux-android
|
||||
|
||||
@ -27,18 +27,18 @@ ENV RUST_CONFIGURE_ARGS \
|
||||
--enable-extended \
|
||||
--enable-cargo-openssl-static
|
||||
|
||||
# We support api level 9, but api level 21 is required to build llvm. To
|
||||
# We support api level 14, but api level 21 is required to build llvm. To
|
||||
# overcome this problem we use a ndk with api level 21 to build llvm and then
|
||||
# switch to a ndk with api level 9 to complete the build. When the linker is
|
||||
# switch to a ndk with api level 14 to complete the build. When the linker is
|
||||
# invoked there are missing symbols (like sigsetempty, not available with api
|
||||
# level 9), the default linker behavior is to generate an error, to allow the
|
||||
# level 14), the default linker behavior is to generate an error, to allow the
|
||||
# build to finish we use --warn-unresolved-symbols. Note that the missing
|
||||
# symbols does not affect std, only the compiler (llvm) and cargo (openssl).
|
||||
ENV SCRIPT \
|
||||
python2.7 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
|
||||
(export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
|
||||
rm /android/ndk/x86 && \
|
||||
ln -s /android/ndk/x86-9 /android/ndk/x86 && \
|
||||
ln -s /android/ndk/x86-14 /android/ndk/x86 && \
|
||||
python2.7 ../x.py dist --host $HOSTS --target $HOSTS)
|
||||
|
||||
COPY scripts/sccache.sh /scripts/
|
||||
|
@ -5,7 +5,7 @@ RUN sh /scripts/android-base-apt-get.sh
|
||||
|
||||
COPY scripts/android-ndk.sh /scripts/
|
||||
RUN . /scripts/android-ndk.sh && \
|
||||
download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip x86_64 21
|
||||
download_and_make_toolchain android-ndk-r15c-linux-x86_64.zip x86_64 21
|
||||
|
||||
ENV PATH=$PATH:/android/ndk/x86_64-21/bin
|
||||
|
||||
|
@ -6,9 +6,9 @@ RUN sh /scripts/android-base-apt-get.sh
|
||||
# ndk
|
||||
COPY scripts/android-ndk.sh /scripts/
|
||||
RUN . /scripts/android-ndk.sh && \
|
||||
download_ndk android-ndk-r13b-linux-x86_64.zip && \
|
||||
make_standalone_toolchain arm 9 && \
|
||||
make_standalone_toolchain x86 9 && \
|
||||
download_ndk android-ndk-r15c-linux-x86_64.zip && \
|
||||
make_standalone_toolchain arm 14 && \
|
||||
make_standalone_toolchain x86 14 && \
|
||||
make_standalone_toolchain arm64 21 && \
|
||||
make_standalone_toolchain x86_64 21 && \
|
||||
remove_ndk
|
||||
@ -23,9 +23,9 @@ ENV TARGETS=$TARGETS,x86_64-linux-android
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=$TARGETS \
|
||||
--enable-extended \
|
||||
--arm-linux-androideabi-ndk=/android/ndk/arm-9 \
|
||||
--armv7-linux-androideabi-ndk=/android/ndk/arm-9 \
|
||||
--i686-linux-android-ndk=/android/ndk/x86-9 \
|
||||
--arm-linux-androideabi-ndk=/android/ndk/arm-14 \
|
||||
--armv7-linux-androideabi-ndk=/android/ndk/arm-14 \
|
||||
--i686-linux-android-ndk=/android/ndk/x86-14 \
|
||||
--aarch64-linux-android-ndk=/android/ndk/arm64-21 \
|
||||
--x86_64-linux-android-ndk=/android/ndk/x86_64-21
|
||||
|
||||
|
@ -10,40 +10,40 @@
|
||||
|
||||
set -ex
|
||||
|
||||
URL=https://dl.google.com/android/repository
|
||||
export ANDROID_HOME=/android/sdk
|
||||
PATH=$PATH:"${ANDROID_HOME}/tools/bin"
|
||||
|
||||
download_sdk() {
|
||||
mkdir -p /android/sdk
|
||||
cd /android/sdk
|
||||
curl -fO $URL/$1
|
||||
unzip -q $1
|
||||
rm -rf $1
|
||||
mkdir -p /android
|
||||
curl -fo sdk.zip "https://dl.google.com/android/repository/sdk-tools-linux-$1.zip"
|
||||
unzip -q sdk.zip -d "$ANDROID_HOME"
|
||||
rm -f sdk.zip
|
||||
}
|
||||
|
||||
download_sysimage() {
|
||||
# See https://developer.android.com/studio/tools/help/android.html
|
||||
abi=$1
|
||||
api=$2
|
||||
|
||||
filter="platform-tools,android-$api"
|
||||
filter="$filter,sys-img-$abi-android-$api"
|
||||
|
||||
# Keep printing yes to accept the licenses
|
||||
while true; do echo yes; sleep 10; done | \
|
||||
/android/sdk/tools/android update sdk -a --no-ui \
|
||||
--filter "$filter" --no-https
|
||||
# See https://developer.android.com/studio/command-line/sdkmanager.html for
|
||||
# usage of `sdkmanager`.
|
||||
#
|
||||
# The output from sdkmanager is so noisy that it will occupy all of the 4 MB
|
||||
# log extremely quickly. Thus we must silence all output.
|
||||
yes | sdkmanager --licenses > /dev/null
|
||||
sdkmanager platform-tools emulator \
|
||||
"platforms;android-$api" \
|
||||
"system-images;android-$api;default;$abi" > /dev/null
|
||||
}
|
||||
|
||||
create_avd() {
|
||||
# See https://developer.android.com/studio/tools/help/android.html
|
||||
abi=$1
|
||||
api=$2
|
||||
|
||||
echo no | \
|
||||
/android/sdk/tools/android create avd \
|
||||
--name $abi-$api \
|
||||
--target android-$api \
|
||||
--abi $abi
|
||||
# See https://developer.android.com/studio/command-line/avdmanager.html for
|
||||
# usage of `avdmanager`.
|
||||
echo no | avdmanager create avd \
|
||||
-n "$abi-$api" \
|
||||
-k "system-images;android-$api;default;$abi"
|
||||
}
|
||||
|
||||
download_and_create_avd() {
|
||||
@ -51,3 +51,15 @@ download_and_create_avd() {
|
||||
download_sysimage $2 $3
|
||||
create_avd $2 $3
|
||||
}
|
||||
|
||||
# Usage:
|
||||
#
|
||||
# setup_android_sdk 4333796 armeabi-v7a 18
|
||||
#
|
||||
# 4333796 =>
|
||||
# SDK tool version.
|
||||
# Copy from https://developer.android.com/studio/index.html#command-tools
|
||||
# armeabi-v7a =>
|
||||
# System image ABI
|
||||
# 18 =>
|
||||
# Android API Level (18 = Android 4.3 = Jelly Bean MR2)
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 808f482db94391fca1e04a9692b59e9eda8cfef9
|
||||
Subproject commit 7db393dae740d84775b73f403123c866e94e3a5b
|
@ -35,6 +35,7 @@ pub enum Def {
|
||||
Variant(DefId),
|
||||
Trait(DefId),
|
||||
TyAlias(DefId),
|
||||
TyForeign(DefId),
|
||||
AssociatedTy(DefId),
|
||||
PrimTy(hir::PrimTy),
|
||||
TyParam(DefId),
|
||||
@ -152,7 +153,7 @@ impl Def {
|
||||
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
|
||||
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
|
||||
Def::AssociatedConst(id) | Def::Macro(id, ..) |
|
||||
Def::GlobalAsm(id) => {
|
||||
Def::GlobalAsm(id) | Def::TyForeign(id) => {
|
||||
id
|
||||
}
|
||||
|
||||
@ -186,6 +187,7 @@ impl Def {
|
||||
Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
|
||||
Def::Union(..) => "union",
|
||||
Def::Trait(..) => "trait",
|
||||
Def::TyForeign(..) => "foreign type",
|
||||
Def::Method(..) => "method",
|
||||
Def::Const(..) => "constant",
|
||||
Def::AssociatedConst(..) => "associated constant",
|
||||
|
@ -704,6 +704,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
|
||||
}
|
||||
}
|
||||
ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
|
||||
ForeignItemType => (),
|
||||
}
|
||||
|
||||
walk_list!(visitor, visit_attribute, &foreign_item.attrs);
|
||||
|
@ -1722,6 +1722,9 @@ impl<'a> LoweringContext<'a> {
|
||||
ForeignItemKind::Static(ref t, m) => {
|
||||
hir::ForeignItemStatic(this.lower_ty(t), m)
|
||||
}
|
||||
ForeignItemKind::Ty => {
|
||||
hir::ForeignItemType
|
||||
}
|
||||
},
|
||||
vis: this.lower_visibility(&i.vis, None),
|
||||
span: i.span,
|
||||
|
@ -1912,6 +1912,8 @@ pub enum ForeignItem_ {
|
||||
/// A foreign static item (`static ext: u8`), with optional mutability
|
||||
/// (the boolean is true when mutable)
|
||||
ForeignItemStatic(P<Ty>, bool),
|
||||
/// A foreign type
|
||||
ForeignItemType,
|
||||
}
|
||||
|
||||
impl ForeignItem_ {
|
||||
@ -1919,6 +1921,7 @@ impl ForeignItem_ {
|
||||
match *self {
|
||||
ForeignItemFn(..) => "foreign function",
|
||||
ForeignItemStatic(..) => "foreign static item",
|
||||
ForeignItemType => "foreign type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -478,6 +478,13 @@ impl<'a> State<'a> {
|
||||
self.end()?; // end the head-ibox
|
||||
self.end() // end the outer cbox
|
||||
}
|
||||
hir::ForeignItemType => {
|
||||
self.head(&visibility_qualified(&item.vis, "type"))?;
|
||||
self.print_name(item.name)?;
|
||||
self.s.word(";")?;
|
||||
self.end()?; // end the head-ibox
|
||||
self.end() // end the outer cbox
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -977,7 +977,8 @@ impl_stable_hash_for!(struct hir::ForeignItem {
|
||||
|
||||
impl_stable_hash_for!(enum hir::ForeignItem_ {
|
||||
ForeignItemFn(fn_decl, arg_names, generics),
|
||||
ForeignItemStatic(ty, is_mutbl)
|
||||
ForeignItemStatic(ty, is_mutbl),
|
||||
ForeignItemType
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum hir::Stmt_ {
|
||||
@ -1086,6 +1087,7 @@ impl_stable_hash_for!(enum hir::def::Def {
|
||||
PrimTy(prim_ty),
|
||||
TyParam(def_id),
|
||||
SelfTy(trait_def_id, impl_def_id),
|
||||
TyForeign(def_id),
|
||||
Fn(def_id),
|
||||
Const(def_id),
|
||||
Static(def_id, is_mutbl),
|
||||
|
@ -610,8 +610,7 @@ for ty::TypeVariants<'gcx>
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
closure_substs.hash_stable(hcx, hasher);
|
||||
}
|
||||
TyGenerator(def_id, closure_substs, interior)
|
||||
=> {
|
||||
TyGenerator(def_id, closure_substs, interior) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
closure_substs.hash_stable(hcx, hasher);
|
||||
interior.hash_stable(hcx, hasher);
|
||||
@ -630,6 +629,9 @@ for ty::TypeVariants<'gcx>
|
||||
TyParam(param_ty) => {
|
||||
param_ty.hash_stable(hcx, hasher);
|
||||
}
|
||||
TyForeign(def_id) => {
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
}
|
||||
TyInfer(..) => {
|
||||
bug!("ty::TypeVariants::hash_stable() - Unexpected variant {:?}.", *self)
|
||||
}
|
||||
|
@ -312,6 +312,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
|
||||
ty::TyNever |
|
||||
ty::TyTuple(..) |
|
||||
ty::TyProjection(..) |
|
||||
ty::TyForeign(..) |
|
||||
ty::TyParam(..) |
|
||||
ty::TyAnon(..) => {
|
||||
t.super_fold_with(self)
|
||||
|
@ -365,6 +365,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
hir::ForeignItemStatic(..) => {
|
||||
intravisit::walk_foreign_item(self, item);
|
||||
}
|
||||
hir::ForeignItemType => {
|
||||
intravisit::walk_foreign_item(self, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,9 @@ use hir::def::Def;
|
||||
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
|
||||
use ty::{self, TyCtxt};
|
||||
use middle::privacy::AccessLevels;
|
||||
use session::DiagnosticMessageId;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
|
||||
use syntax::ast;
|
||||
use syntax::ast::{NodeId, Attribute};
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version};
|
||||
@ -597,8 +598,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
feature.as_str(), &r),
|
||||
None => format!("use of unstable library feature '{}'", &feature)
|
||||
};
|
||||
emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
|
||||
GateIssue::Library(Some(issue)), &msg);
|
||||
|
||||
|
||||
let msp: MultiSpan = span.into();
|
||||
let cm = &self.sess.parse_sess.codemap();
|
||||
let span_key = msp.primary_span().and_then(|sp: Span|
|
||||
if sp != DUMMY_SP {
|
||||
let file = cm.lookup_char_pos(sp.lo()).file;
|
||||
if file.name.starts_with("<") && file.name.ends_with(" macros>") {
|
||||
None
|
||||
} else {
|
||||
Some(span)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
);
|
||||
|
||||
let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
|
||||
let fresh = self.sess.one_time_diagnostics.borrow_mut().insert(error_id);
|
||||
if fresh {
|
||||
emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
|
||||
GateIssue::Library(Some(issue)), &msg);
|
||||
}
|
||||
}
|
||||
Some(_) => {
|
||||
// Stable APIs are always ok to call and deprecated APIs are
|
||||
|
@ -75,10 +75,10 @@ pub struct Session {
|
||||
pub working_dir: (String, bool),
|
||||
pub lint_store: RefCell<lint::LintStore>,
|
||||
pub buffered_lints: RefCell<Option<lint::LintBuffer>>,
|
||||
/// Set of (LintId, Option<Span>, message) tuples tracking lint
|
||||
/// Set of (DiagnosticId, Option<Span>, message) tuples tracking
|
||||
/// (sub)diagnostics that have been set once, but should not be set again,
|
||||
/// in order to avoid redundantly verbose output (Issue #24690).
|
||||
pub one_time_diagnostics: RefCell<FxHashSet<(lint::LintId, Option<Span>, String)>>,
|
||||
/// in order to avoid redundantly verbose output (Issue #24690, #44953).
|
||||
pub one_time_diagnostics: RefCell<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
|
||||
pub plugin_llvm_passes: RefCell<Vec<String>>,
|
||||
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
|
||||
pub crate_types: RefCell<Vec<config::CrateType>>,
|
||||
@ -164,6 +164,13 @@ enum DiagnosticBuilderMethod {
|
||||
// add more variants as needed to support one-time diagnostics
|
||||
}
|
||||
|
||||
/// Diagnostic message id - used in order to avoid emitting the same message more than once
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum DiagnosticMessageId {
|
||||
LintId(lint::LintId),
|
||||
StabilityId(u32)
|
||||
}
|
||||
|
||||
impl Session {
|
||||
pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
|
||||
match *self.crate_disambiguator.borrow() {
|
||||
@ -360,7 +367,7 @@ impl Session {
|
||||
do_method()
|
||||
},
|
||||
_ => {
|
||||
let lint_id = lint::LintId::of(lint);
|
||||
let lint_id = DiagnosticMessageId::LintId(lint::LintId::of(lint));
|
||||
let id_span_message = (lint_id, span, message.to_owned());
|
||||
let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message);
|
||||
if fresh {
|
||||
|
@ -304,6 +304,10 @@ fn ty_is_local_constructor(ty: Ty, infer_is_local: InferIsLocal)-> bool {
|
||||
def.did.is_local()
|
||||
}
|
||||
|
||||
ty::TyForeign(did) => {
|
||||
did.is_local()
|
||||
}
|
||||
|
||||
ty::TyDynamic(ref tt, ..) => {
|
||||
tt.principal().map_or(false, |p| p.def_id().is_local())
|
||||
}
|
||||
|
@ -255,6 +255,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
AdtKind::Enum => Some(17),
|
||||
},
|
||||
ty::TyGenerator(..) => Some(18),
|
||||
ty::TyForeign(..) => Some(19),
|
||||
ty::TyInfer(..) | ty::TyError => None
|
||||
}
|
||||
}
|
||||
|
@ -1705,6 +1705,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// say nothing; a candidate may be added by
|
||||
// `assemble_candidates_from_object_ty`.
|
||||
}
|
||||
ty::TyForeign(..) => {
|
||||
// Since the contents of foreign types is unknown,
|
||||
// we don't add any `..` impl. Default traits could
|
||||
// still be provided by a manual implementation for
|
||||
// this trait and type.
|
||||
}
|
||||
ty::TyParam(..) |
|
||||
ty::TyProjection(..) => {
|
||||
// In these cases, we don't know what the actual
|
||||
@ -2022,7 +2028,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
Where(ty::Binder(Vec::new()))
|
||||
}
|
||||
|
||||
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never,
|
||||
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) | ty::TyForeign(..) => Never,
|
||||
|
||||
ty::TyTuple(tys, _) => {
|
||||
Where(ty::Binder(tys.last().into_iter().cloned().collect()))
|
||||
@ -2066,7 +2072,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
Where(ty::Binder(Vec::new()))
|
||||
}
|
||||
|
||||
ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) | ty::TyGenerator(..) |
|
||||
ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
|
||||
ty::TyGenerator(..) | ty::TyForeign(..) |
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
|
||||
Never
|
||||
}
|
||||
@ -2148,6 +2155,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
|
||||
ty::TyDynamic(..) |
|
||||
ty::TyParam(..) |
|
||||
ty::TyForeign(..) |
|
||||
ty::TyProjection(..) |
|
||||
ty::TyInfer(ty::TyVar(_)) |
|
||||
ty::TyInfer(ty::FreshTy(_)) |
|
||||
|
@ -1610,7 +1610,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
pub fn print_debug_stats(self) {
|
||||
sty_debug_print!(
|
||||
self,
|
||||
TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyGenerator,
|
||||
TyAdt, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, TyGenerator, TyForeign,
|
||||
TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon);
|
||||
|
||||
println!("Substs interner: #{}", self.interners.substs.borrow().len());
|
||||
@ -1861,6 +1861,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
self.mk_ty(TyAdt(def, substs))
|
||||
}
|
||||
|
||||
pub fn mk_foreign(self, def_id: DefId) -> Ty<'tcx> {
|
||||
self.mk_ty(TyForeign(def_id))
|
||||
}
|
||||
|
||||
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
|
||||
let adt_def = self.adt_def(def_id);
|
||||
|
@ -182,6 +182,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
|
||||
ty::TyTuple(ref tys, _) if tys.is_empty() => self.to_string(),
|
||||
|
||||
ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
|
||||
ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
|
||||
ty::TyArray(_, n) => {
|
||||
if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
|
||||
format!("array of {} elements", n)
|
||||
|
@ -49,6 +49,7 @@ pub enum SimplifiedTypeGen<D>
|
||||
AnonSimplifiedType(D),
|
||||
FunctionSimplifiedType(usize),
|
||||
ParameterSimplifiedType,
|
||||
ForeignSimplifiedType(DefId),
|
||||
}
|
||||
|
||||
/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc.
|
||||
@ -113,6 +114,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
ty::TyAnon(def_id, _) => {
|
||||
Some(AnonSimplifiedType(def_id))
|
||||
}
|
||||
ty::TyForeign(def_id) => {
|
||||
Some(ForeignSimplifiedType(def_id))
|
||||
}
|
||||
ty::TyInfer(_) | ty::TyError => None,
|
||||
}
|
||||
}
|
||||
@ -140,6 +144,7 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
|
||||
AnonSimplifiedType(d) => AnonSimplifiedType(map(d)),
|
||||
FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
|
||||
ParameterSimplifiedType => ParameterSimplifiedType,
|
||||
ForeignSimplifiedType(d) => ForeignSimplifiedType(d),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,6 +177,7 @@ impl<'gcx, D> HashStable<StableHashingContext<'gcx>> for SimplifiedTypeGen<D>
|
||||
GeneratorSimplifiedType(d) => d.hash_stable(hcx, hasher),
|
||||
AnonSimplifiedType(d) => d.hash_stable(hcx, hasher),
|
||||
FunctionSimplifiedType(n) => n.hash_stable(hcx, hasher),
|
||||
ForeignSimplifiedType(d) => d.hash_stable(hcx, hasher),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,8 @@ impl FlagComputation {
|
||||
&ty::TyFloat(_) |
|
||||
&ty::TyUint(_) |
|
||||
&ty::TyNever |
|
||||
&ty::TyStr => {
|
||||
&ty::TyStr |
|
||||
&ty::TyForeign(..) => {
|
||||
}
|
||||
|
||||
// You might think that we could just return TyError for
|
||||
|
@ -281,6 +281,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyForeign(did) => self.push_item_path(buffer, did),
|
||||
|
||||
ty::TyBool |
|
||||
ty::TyChar |
|
||||
ty::TyInt(_) |
|
||||
@ -344,8 +346,9 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
|
||||
.next(),
|
||||
|
||||
ty::TyFnDef(def_id, _) |
|
||||
ty::TyClosure(def_id, _) => Some(def_id),
|
||||
ty::TyGenerator(def_id, _, _) => Some(def_id),
|
||||
ty::TyClosure(def_id, _) |
|
||||
ty::TyGenerator(def_id, _, _) |
|
||||
ty::TyForeign(def_id) => Some(def_id),
|
||||
|
||||
ty::TyBool |
|
||||
ty::TyChar |
|
||||
|
@ -1141,14 +1141,15 @@ impl<'a, 'tcx> Layout {
|
||||
Ok(Scalar { value: Pointer, non_zero: non_zero })
|
||||
} else {
|
||||
let unsized_part = tcx.struct_tail(pointee);
|
||||
let meta = match unsized_part.sty {
|
||||
ty::TySlice(_) | ty::TyStr => {
|
||||
Int(dl.ptr_sized_integer())
|
||||
}
|
||||
ty::TyDynamic(..) => Pointer,
|
||||
_ => return Err(LayoutError::Unknown(unsized_part))
|
||||
};
|
||||
Ok(FatPointer { metadata: meta, non_zero: non_zero })
|
||||
match unsized_part.sty {
|
||||
ty::TySlice(_) | ty::TyStr => Ok(FatPointer {
|
||||
metadata: Int(dl.ptr_sized_integer()),
|
||||
non_zero: non_zero
|
||||
}),
|
||||
ty::TyDynamic(..) => Ok(FatPointer { metadata: Pointer, non_zero: non_zero }),
|
||||
ty::TyForeign(..) => Ok(Scalar { value: Pointer, non_zero: non_zero }),
|
||||
_ => Err(LayoutError::Unknown(unsized_part)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1239,7 +1240,7 @@ impl<'a, 'tcx> Layout {
|
||||
non_zero: false
|
||||
}
|
||||
}
|
||||
ty::TyDynamic(..) => {
|
||||
ty::TyDynamic(..) | ty::TyForeign(..) => {
|
||||
let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
|
||||
StructKind::AlwaysSizedUnivariant, ty)?;
|
||||
unit.sized = false;
|
||||
@ -2252,7 +2253,8 @@ impl<'a, 'tcx> TyLayout<'tcx> {
|
||||
ty::TyFnPtr(_) |
|
||||
ty::TyNever |
|
||||
ty::TyFnDef(..) |
|
||||
ty::TyDynamic(..) => {
|
||||
ty::TyDynamic(..) |
|
||||
ty::TyForeign(..) => {
|
||||
bug!("TyLayout::field_type({:?}): not applicable", self)
|
||||
}
|
||||
|
||||
|
@ -1784,7 +1784,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
|
||||
vec![]
|
||||
}
|
||||
|
||||
TyStr | TyDynamic(..) | TySlice(_) | TyError => {
|
||||
TyStr | TyDynamic(..) | TySlice(_) | TyForeign(..) | TyError => {
|
||||
// these are never sized - return the target type
|
||||
vec![ty]
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
ty::TyNever | // ...
|
||||
ty::TyAdt(..) | // OutlivesNominalType
|
||||
ty::TyAnon(..) | // OutlivesNominalType (ish)
|
||||
ty::TyForeign(..) | // OutlivesNominalType
|
||||
ty::TyStr | // OutlivesScalar (ish)
|
||||
ty::TyArray(..) | // ...
|
||||
ty::TySlice(..) | // ...
|
||||
|
@ -381,6 +381,12 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
|
||||
Ok(tcx.mk_adt(a_def, substs))
|
||||
}
|
||||
|
||||
(&ty::TyForeign(a_id), &ty::TyForeign(b_id))
|
||||
if a_id == b_id =>
|
||||
{
|
||||
Ok(tcx.mk_foreign(a_id))
|
||||
}
|
||||
|
||||
(&ty::TyDynamic(ref a_obj, ref a_region), &ty::TyDynamic(ref b_obj, ref b_region)) => {
|
||||
let region_bound = relation.with_cause(Cause::ExistentialRegionBound,
|
||||
|relation| {
|
||||
|
@ -676,7 +676,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
|
||||
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
|
||||
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
|
||||
ty::TyParam(..) | ty::TyNever => return self
|
||||
ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => return self
|
||||
};
|
||||
|
||||
if self.sty == sty {
|
||||
@ -710,7 +710,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
|
||||
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
|
||||
ty::TyParam(..) | ty::TyNever => false,
|
||||
ty::TyParam(..) | ty::TyNever | ty::TyForeign(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,8 @@ pub enum TypeVariants<'tcx> {
|
||||
/// definition and not a concrete use of it.
|
||||
TyAdt(&'tcx AdtDef, &'tcx Substs<'tcx>),
|
||||
|
||||
TyForeign(DefId),
|
||||
|
||||
/// The pointee of a string slice. Written as `str`.
|
||||
TyStr,
|
||||
|
||||
@ -1117,13 +1119,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_structural(&self) -> bool {
|
||||
match self.sty {
|
||||
TyAdt(..) | TyTuple(..) | TyArray(..) | TyClosure(..) => true,
|
||||
_ => self.is_slice() | self.is_trait(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_simd(&self) -> bool {
|
||||
match self.sty {
|
||||
@ -1347,6 +1342,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
match self.sty {
|
||||
TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()),
|
||||
TyAdt(def, _) => Some(def.did),
|
||||
TyForeign(did) => Some(did),
|
||||
TyClosure(id, _) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
@ -1396,6 +1392,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
TyRawPtr(_) |
|
||||
TyNever |
|
||||
TyTuple(..) |
|
||||
TyForeign(..) |
|
||||
TyParam(_) |
|
||||
TyInfer(_) |
|
||||
TyError => {
|
||||
|
@ -553,7 +553,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
let result = match ty.sty {
|
||||
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
|
||||
ty::TyFloat(_) | ty::TyStr | ty::TyNever |
|
||||
ty::TyFloat(_) | ty::TyStr | ty::TyNever | ty::TyForeign(..) |
|
||||
ty::TyRawPtr(..) | ty::TyRef(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) => {
|
||||
// these types never have a destructor
|
||||
Ok(ty::DtorckConstraint::empty())
|
||||
@ -714,6 +714,7 @@ impl<'a, 'gcx, 'tcx, W> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx, W>
|
||||
TyAnon(def_id, _) |
|
||||
TyFnDef(def_id, _) => self.def_id(def_id),
|
||||
TyAdt(d, _) => self.def_id(d.did),
|
||||
TyForeign(def_id) => self.def_id(def_id),
|
||||
TyFnPtr(f) => {
|
||||
self.hash(f.unsafety());
|
||||
self.hash(f.abi());
|
||||
@ -1109,6 +1110,9 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
|
||||
ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
|
||||
|
||||
// Foreign types can never have destructors
|
||||
ty::TyForeign(..) => false,
|
||||
|
||||
// Issue #22536: We first query type_moves_by_default. It sees a
|
||||
// normalized version of the type, and therefore will definitely
|
||||
// know whether the type implements Copy (and thus needs no
|
||||
|
@ -82,7 +82,8 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> AccIntoIter<TypeWalkerArray<'tcx>> {
|
||||
fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
|
||||
match parent_ty.sty {
|
||||
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
|
||||
ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => {
|
||||
ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError |
|
||||
ty::TyForeign(..) => {
|
||||
}
|
||||
ty::TyArray(ty, len) => {
|
||||
push_const(stack, len);
|
||||
|
@ -284,7 +284,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
|
||||
ty::TyError |
|
||||
ty::TyStr |
|
||||
ty::TyNever |
|
||||
ty::TyParam(_) => {
|
||||
ty::TyParam(_) |
|
||||
ty::TyForeign(..) => {
|
||||
// WfScalar, WfParameter, etc
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
|
||||
use ty::{TyBool, TyChar, TyAdt};
|
||||
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
|
||||
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
|
||||
use ty::{TyClosure, TyGenerator, TyProjection, TyAnon};
|
||||
use ty::{TyClosure, TyGenerator, TyForeign, TyProjection, TyAnon};
|
||||
use ty::{TyDynamic, TyInt, TyUint, TyInfer};
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use util::nodemap::FxHashSet;
|
||||
@ -1012,6 +1012,7 @@ define_print! {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
TyForeign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
|
||||
TyProjection(ref data) => data.print(f, cx),
|
||||
TyAnon(def_id, substs) => {
|
||||
ty::tls::with(|tcx| {
|
||||
|
@ -621,6 +621,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
||||
FfiSafe
|
||||
}
|
||||
|
||||
ty::TyForeign(..) => FfiSafe,
|
||||
|
||||
ty::TyParam(..) |
|
||||
ty::TyInfer(..) |
|
||||
ty::TyError |
|
||||
@ -723,6 +725,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
|
||||
hir::ForeignItemStatic(ref ty, _) => {
|
||||
vis.check_foreign_static(ni.id, ty.span);
|
||||
}
|
||||
hir::ForeignItemType => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -449,6 +449,7 @@ impl<'tcx> EntryKind<'tcx> {
|
||||
EntryKind::Enum(..) => Def::Enum(did),
|
||||
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
|
||||
EntryKind::GlobalAsm => Def::GlobalAsm(did),
|
||||
EntryKind::ForeignType => Def::TyForeign(did),
|
||||
|
||||
EntryKind::ForeignMod |
|
||||
EntryKind::Impl(_) |
|
||||
|
@ -1419,6 +1419,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
||||
}
|
||||
hir::ForeignItemStatic(_, true) => EntryKind::ForeignMutStatic,
|
||||
hir::ForeignItemStatic(_, false) => EntryKind::ForeignImmStatic,
|
||||
hir::ForeignItemType => EntryKind::ForeignType,
|
||||
};
|
||||
|
||||
Entry {
|
||||
|
@ -292,6 +292,7 @@ pub enum EntryKind<'tcx> {
|
||||
ForeignImmStatic,
|
||||
ForeignMutStatic,
|
||||
ForeignMod,
|
||||
ForeignType,
|
||||
GlobalAsm,
|
||||
Type,
|
||||
Enum(ReprOptions),
|
||||
@ -325,6 +326,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for EntryKind<'gcx> {
|
||||
EntryKind::ForeignMutStatic |
|
||||
EntryKind::ForeignMod |
|
||||
EntryKind::GlobalAsm |
|
||||
EntryKind::ForeignType |
|
||||
EntryKind::Field |
|
||||
EntryKind::Type => {
|
||||
// Nothing else to hash here.
|
||||
|
@ -288,7 +288,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
err.emit();
|
||||
});
|
||||
}
|
||||
ForeignItemKind::Static(..) => {}
|
||||
ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}
|
||||
}
|
||||
|
||||
visit::walk_foreign_item(self, fi)
|
||||
|
@ -85,6 +85,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
|
||||
fn item_ty_level(&self, item_def_id: DefId) -> Option<AccessLevel> {
|
||||
let ty_def_id = match self.tcx.type_of(item_def_id).sty {
|
||||
ty::TyAdt(adt, _) => adt.did,
|
||||
ty::TyForeign(did) => did,
|
||||
ty::TyDynamic(ref obj, ..) if obj.principal().is_some() =>
|
||||
obj.principal().unwrap().def_id(),
|
||||
ty::TyProjection(ref proj) => proj.trait_ref(self.tcx).def_id,
|
||||
@ -444,6 +445,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
let ty_def_id = match ty.sty {
|
||||
ty::TyAdt(adt, _) => Some(adt.did),
|
||||
ty::TyForeign(did) => Some(did),
|
||||
ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
|
||||
ty::TyProjection(ref proj) => Some(proj.item_def_id),
|
||||
ty::TyFnDef(def_id, ..) |
|
||||
@ -800,7 +802,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
||||
impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyAdt(&ty::AdtDef { did: def_id, .. }, ..) | ty::TyFnDef(def_id, ..) => {
|
||||
ty::TyAdt(&ty::AdtDef { did: def_id, .. }, ..) |
|
||||
ty::TyFnDef(def_id, ..) |
|
||||
ty::TyForeign(def_id) => {
|
||||
if !self.item_is_accessible(def_id) {
|
||||
let msg = format!("type `{}` is private", ty);
|
||||
self.tcx.sess.span_err(self.span, &msg);
|
||||
@ -1329,6 +1333,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
let ty_def_id = match ty.sty {
|
||||
ty::TyAdt(adt, _) => Some(adt.did),
|
||||
ty::TyForeign(did) => Some(did),
|
||||
ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
|
||||
ty::TyProjection(ref proj) => {
|
||||
if self.required_visibility == ty::Visibility::Invisible {
|
||||
@ -1349,8 +1354,13 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
|
||||
if let Some(def_id) = ty_def_id {
|
||||
// Non-local means public (private items can't leave their crate, modulo bugs)
|
||||
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
|
||||
let item = self.tcx.hir.expect_item(node_id);
|
||||
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
|
||||
let vis = match self.tcx.hir.find(node_id) {
|
||||
Some(hir::map::NodeItem(item)) => &item.vis,
|
||||
Some(hir::map::NodeForeignItem(item)) => &item.vis,
|
||||
_ => bug!("expected item of foreign item"),
|
||||
};
|
||||
|
||||
let vis = ty::Visibility::from_hir(vis, node_id, self.tcx);
|
||||
|
||||
if !vis.is_at_least(self.min_visibility, self.tcx) {
|
||||
self.min_visibility = vis;
|
||||
|
@ -419,17 +419,20 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
/// Constructs the reduced graph for one foreign item.
|
||||
fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) {
|
||||
let def = match item.node {
|
||||
let (def, ns) = match item.node {
|
||||
ForeignItemKind::Fn(..) => {
|
||||
Def::Fn(self.definitions.local_def_id(item.id))
|
||||
(Def::Fn(self.definitions.local_def_id(item.id)), ValueNS)
|
||||
}
|
||||
ForeignItemKind::Static(_, m) => {
|
||||
Def::Static(self.definitions.local_def_id(item.id), m)
|
||||
(Def::Static(self.definitions.local_def_id(item.id), m), ValueNS)
|
||||
}
|
||||
ForeignItemKind::Ty => {
|
||||
(Def::TyForeign(self.definitions.local_def_id(item.id)), TypeNS)
|
||||
}
|
||||
};
|
||||
let parent = self.current_module;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion));
|
||||
self.define(parent, item.ident, ns, (def, vis, item.span, expansion));
|
||||
}
|
||||
|
||||
fn build_reduced_graph_for_block(&mut self, block: &Block, expansion: Mark) {
|
||||
@ -462,7 +465,7 @@ impl<'a> Resolver<'a> {
|
||||
span);
|
||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
|
||||
}
|
||||
Def::Variant(..) | Def::TyAlias(..) => {
|
||||
Def::Variant(..) | Def::TyAlias(..) | Def::TyForeign(..) => {
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
|
||||
}
|
||||
Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
|
||||
|
@ -468,7 +468,8 @@ impl<'a> PathSource<'a> {
|
||||
PathSource::Type => match def {
|
||||
Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
|
||||
Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
|
||||
Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) => true,
|
||||
Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
|
||||
Def::TyForeign(..) => true,
|
||||
_ => false,
|
||||
},
|
||||
PathSource::Trait => match def {
|
||||
@ -707,6 +708,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
||||
HasTypeParameters(generics, ItemRibKind)
|
||||
}
|
||||
ForeignItemKind::Static(..) => NoTypeParameters,
|
||||
ForeignItemKind::Ty => NoTypeParameters,
|
||||
};
|
||||
self.with_type_parameter_rib(type_parameters, |this| {
|
||||
visit::walk_foreign_item(this, foreign_item);
|
||||
|
@ -263,6 +263,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|
||||
HirDef::Union(..) |
|
||||
HirDef::Enum(..) |
|
||||
HirDef::TyAlias(..) |
|
||||
HirDef::TyForeign(..) |
|
||||
HirDef::Trait(_) => {
|
||||
let span = self.span_from_span(sub_span.expect("No span found for type ref"));
|
||||
self.dumper.dump_ref(Ref {
|
||||
@ -1539,6 +1540,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
|
||||
|
||||
self.visit_ty(ty);
|
||||
}
|
||||
ast::ForeignItemKind::Ty => {
|
||||
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
|
||||
down_cast_data!(var_data, DefData, item.span);
|
||||
self.dumper.dump_def(item.vis == ast::Visibility::Public, var_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,6 +173,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
attributes: lower_attributes(item.attrs.clone(), self),
|
||||
}))
|
||||
}
|
||||
// FIXME(plietar): needs a new DefKind in rls-data
|
||||
ast::ForeignItemKind::Ty => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -642,6 +644,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
HirDef::Union(def_id) |
|
||||
HirDef::Enum(def_id) |
|
||||
HirDef::TyAlias(def_id) |
|
||||
HirDef::TyForeign(def_id) |
|
||||
HirDef::AssociatedTy(def_id) |
|
||||
HirDef::Trait(def_id) |
|
||||
HirDef::TyParam(def_id) => {
|
||||
|
@ -808,6 +808,23 @@ impl Sig for ast::ForeignItem {
|
||||
|
||||
Ok(extend_sig(ty_sig, text, defs, vec![]))
|
||||
}
|
||||
ast::ForeignItemKind::Ty => {
|
||||
let mut text = "type ".to_owned();
|
||||
let name = self.ident.to_string();
|
||||
let defs = vec![SigElement {
|
||||
id: id_from_node_id(self.id, scx),
|
||||
start: offset + text.len(),
|
||||
end: offset + text.len() + name.len(),
|
||||
}];
|
||||
text.push_str(&name);
|
||||
text.push(';');
|
||||
|
||||
Ok(Signature {
|
||||
text: text,
|
||||
defs: defs,
|
||||
refs: vec![],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ use rustc::session::Session;
|
||||
use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_trans_utils;
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::cell::{Cell, RefCell};
|
||||
@ -301,6 +302,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||
common::type_is_freeze(self.tcx, ty)
|
||||
}
|
||||
|
||||
pub fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
|
||||
rustc_trans_utils::common::type_has_metadata(self.tcx, ty)
|
||||
}
|
||||
|
||||
pub fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
@ -543,6 +543,11 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
trait_pointer_metadata(cx, t, None, unique_type_id),
|
||||
false)
|
||||
}
|
||||
ty::TyForeign(..) => {
|
||||
MetadataCreationResult::new(
|
||||
foreign_type_metadata(cx, t, unique_type_id),
|
||||
false)
|
||||
}
|
||||
ty::TyRawPtr(ty::TypeAndMut{ty, ..}) |
|
||||
ty::TyRef(_, ty::TypeAndMut{ty, ..}) => {
|
||||
match ptr_metadata(ty) {
|
||||
@ -752,6 +757,17 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
return ty_metadata;
|
||||
}
|
||||
|
||||
fn foreign_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
t: Ty<'tcx>,
|
||||
unique_type_id: UniqueTypeId) -> DIType {
|
||||
debug!("foreign_type_metadata: {:?}", t);
|
||||
|
||||
let llvm_type = type_of::type_of(cx, t);
|
||||
|
||||
let name = compute_debuginfo_type_name(cx, t, false);
|
||||
create_struct_stub(cx, llvm_type, &name, unique_type_id, NO_SCOPE_METADATA)
|
||||
}
|
||||
|
||||
fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
pointer_type: Ty<'tcx>,
|
||||
pointee_type_metadata: DIType)
|
||||
|
@ -48,6 +48,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
|
||||
ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
|
||||
ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),
|
||||
ty::TyForeign(def_id) => push_item_name(cx, def_id, qualified, output),
|
||||
ty::TyAdt(def, substs) => {
|
||||
push_item_name(cx, def.did, qualified, output);
|
||||
push_type_params(cx, substs, output);
|
||||
|
@ -139,13 +139,15 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||
}
|
||||
"size_of_val" => {
|
||||
let tp_ty = substs.type_at(0);
|
||||
if !bcx.ccx.shared().type_is_sized(tp_ty) {
|
||||
if bcx.ccx.shared().type_is_sized(tp_ty) {
|
||||
let lltp_ty = type_of::type_of(ccx, tp_ty);
|
||||
C_usize(ccx, machine::llsize_of_alloc(ccx, lltp_ty))
|
||||
} else if bcx.ccx.shared().type_has_metadata(tp_ty) {
|
||||
let (llsize, _) =
|
||||
glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]);
|
||||
llsize
|
||||
} else {
|
||||
let lltp_ty = type_of::type_of(ccx, tp_ty);
|
||||
C_usize(ccx, machine::llsize_of_alloc(ccx, lltp_ty))
|
||||
C_usize(ccx, 0u64)
|
||||
}
|
||||
}
|
||||
"min_align_of" => {
|
||||
@ -154,12 +156,14 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
|
||||
}
|
||||
"min_align_of_val" => {
|
||||
let tp_ty = substs.type_at(0);
|
||||
if !bcx.ccx.shared().type_is_sized(tp_ty) {
|
||||
if bcx.ccx.shared().type_is_sized(tp_ty) {
|
||||
C_usize(ccx, ccx.align_of(tp_ty) as u64)
|
||||
} else if bcx.ccx.shared().type_has_metadata(tp_ty) {
|
||||
let (_, llalign) =
|
||||
glue::size_and_align_of_dst(bcx, tp_ty, llargs[1]);
|
||||
llalign
|
||||
} else {
|
||||
C_usize(ccx, ccx.align_of(tp_ty) as u64)
|
||||
C_usize(ccx, 1u64)
|
||||
}
|
||||
}
|
||||
"pref_align_of" => {
|
||||
|
@ -428,11 +428,11 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
.projection_ty(tcx, &projection.elem);
|
||||
let base = tr_base.to_const(span);
|
||||
let projected_ty = self.monomorphize(&projected_ty).to_ty(tcx);
|
||||
let is_sized = self.ccx.shared().type_is_sized(projected_ty);
|
||||
let has_metadata = self.ccx.shared().type_has_metadata(projected_ty);
|
||||
|
||||
let (projected, llextra) = match projection.elem {
|
||||
mir::ProjectionElem::Deref => {
|
||||
let (base, extra) = if is_sized {
|
||||
let (base, extra) = if !has_metadata {
|
||||
(base.llval, ptr::null_mut())
|
||||
} else {
|
||||
base.get_fat_ptr()
|
||||
@ -463,7 +463,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
mir::ProjectionElem::Field(ref field, _) => {
|
||||
let llprojected = adt::const_get_field(self.ccx, tr_base.ty, base.llval,
|
||||
field.index());
|
||||
let llextra = if is_sized {
|
||||
let llextra = if !has_metadata {
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
tr_base.llextra
|
||||
|
@ -147,15 +147,16 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
||||
// * Packed struct - There is no alignment padding
|
||||
// * Field is sized - pointer is properly aligned already
|
||||
if st.offsets[ix] == layout::Size::from_bytes(0) || st.packed ||
|
||||
bcx.ccx.shared().type_is_sized(fty) {
|
||||
return (bcx.struct_gep(
|
||||
ptr_val, adt::struct_llfields_index(st, ix)), alignment);
|
||||
}
|
||||
bcx.ccx.shared().type_is_sized(fty)
|
||||
{
|
||||
return (bcx.struct_gep(
|
||||
ptr_val, adt::struct_llfields_index(st, ix)), alignment);
|
||||
}
|
||||
|
||||
// If the type of the last field is [T] or str, then we don't need to do
|
||||
// If the type of the last field is [T], str or a foreign type, then we don't need to do
|
||||
// any adjusments
|
||||
match fty.sty {
|
||||
ty::TySlice(..) | ty::TyStr => {
|
||||
ty::TySlice(..) | ty::TyStr | ty::TyForeign(..) => {
|
||||
return (bcx.struct_gep(
|
||||
ptr_val, adt::struct_llfields_index(st, ix)), alignment);
|
||||
}
|
||||
@ -328,7 +329,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
let ((llprojected, align), llextra) = match projection.elem {
|
||||
mir::ProjectionElem::Deref => bug!(),
|
||||
mir::ProjectionElem::Field(ref field, _) => {
|
||||
let llextra = if self.ccx.shared().type_is_sized(projected_ty.to_ty(tcx)) {
|
||||
let has_metadata = self.ccx.shared()
|
||||
.type_has_metadata(projected_ty.to_ty(tcx));
|
||||
let llextra = if !has_metadata {
|
||||
ptr::null_mut()
|
||||
} else {
|
||||
tr_base.llextra
|
||||
@ -415,3 +418,4 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
self.monomorphize(&lvalue_ty.to_ty(tcx))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
|
||||
// Note: lvalues are indirect, so storing the `llval` into the
|
||||
// destination effectively creates a reference.
|
||||
let operand = if bcx.ccx.shared().type_is_sized(ty) {
|
||||
let operand = if !bcx.ccx.shared().type_has_metadata(ty) {
|
||||
OperandRef {
|
||||
val: OperandValue::Immediate(tr_lvalue.llval),
|
||||
ty: ref_ty,
|
||||
|
@ -230,4 +230,3 @@ fn predefine_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
||||
ccx.instances().borrow_mut().insert(instance, lldecl);
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ use syntax::ast;
|
||||
pub fn fat_ptr_base_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
|
||||
match ty.sty {
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: t, .. }) |
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) if !ccx.shared().type_is_sized(t) => {
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) if ccx.shared().type_has_metadata(t) => {
|
||||
in_memory_type_of(ccx, t).ptr_to()
|
||||
}
|
||||
ty::TyAdt(def, _) if def.is_box() => {
|
||||
@ -62,7 +62,7 @@ pub fn immediate_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||
/// is too large for it to be placed in SSA value (by our rules).
|
||||
/// For the raw type without far pointer indirection, see `in_memory_type_of`.
|
||||
pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
|
||||
let ty = if !cx.shared().type_is_sized(ty) {
|
||||
let ty = if cx.shared().type_has_metadata(ty) {
|
||||
cx.tcx().mk_imm_ptr(ty)
|
||||
} else {
|
||||
ty
|
||||
@ -106,7 +106,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||
}
|
||||
|
||||
let ptr_ty = |ty: Ty<'tcx>| {
|
||||
if !cx.shared().type_is_sized(ty) {
|
||||
if cx.shared().type_has_metadata(ty) {
|
||||
if let ty::TyStr = ty.sty {
|
||||
// This means we get a nicer name in the output (str is always
|
||||
// unsized).
|
||||
@ -158,7 +158,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||
// fat pointers is of the right type (e.g. for array accesses), even
|
||||
// when taking the address of an unsized field in a struct.
|
||||
ty::TySlice(ty) => in_memory_type_of(cx, ty),
|
||||
ty::TyStr | ty::TyDynamic(..) => Type::i8(cx),
|
||||
ty::TyStr | ty::TyDynamic(..) | ty::TyForeign(..) => Type::i8(cx),
|
||||
|
||||
ty::TyFnDef(..) => Type::nil(cx),
|
||||
ty::TyFnPtr(sig) => {
|
||||
|
@ -203,7 +203,7 @@ use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||
use rustc::mir::{self, Location};
|
||||
use rustc::mir::visit::Visitor as MirVisitor;
|
||||
|
||||
use common::{def_ty, instance_ty, type_is_sized};
|
||||
use common::{def_ty, instance_ty, type_has_metadata};
|
||||
use monomorphize::{self, Instance};
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
|
||||
|
||||
@ -782,7 +782,7 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
target_ty: Ty<'tcx>)
|
||||
-> (Ty<'tcx>, Ty<'tcx>) {
|
||||
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
|
||||
if !type_is_sized(tcx, inner_source) {
|
||||
if type_has_metadata(tcx, inner_source) {
|
||||
(inner_source, inner_target)
|
||||
} else {
|
||||
tcx.struct_lockstep_tails(inner_source, inner_target)
|
||||
|
@ -25,6 +25,19 @@ pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> boo
|
||||
ty.is_sized(tcx, ty::ParamEnv::empty(traits::Reveal::All), DUMMY_SP)
|
||||
}
|
||||
|
||||
pub fn type_has_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
if type_is_sized(tcx, ty) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let tail = tcx.struct_tail(ty);
|
||||
match tail.sty {
|
||||
ty::TyForeign(..) => false,
|
||||
ty::TyStr | ty::TySlice(..) | ty::TyDynamic(..) => true,
|
||||
_ => bug!("unexpected unsized tail: {:?}", tail.sty),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn requests_inline<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
instance: &ty::Instance<'tcx>
|
||||
|
@ -48,7 +48,7 @@ use rustc::util::nodemap::NodeSet;
|
||||
|
||||
use syntax::attr;
|
||||
|
||||
mod common;
|
||||
pub mod common;
|
||||
pub mod link;
|
||||
pub mod collector;
|
||||
pub mod trans_item;
|
||||
|
@ -335,6 +335,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
||||
output);
|
||||
}
|
||||
},
|
||||
ty::TyForeign(did) => self.push_def_path(did, output),
|
||||
ty::TyFnDef(..) |
|
||||
ty::TyFnPtr(_) => {
|
||||
let sig = t.fn_sig(self.tcx);
|
||||
|
@ -928,7 +928,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
let span = path.span;
|
||||
match path.def {
|
||||
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => {
|
||||
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) |
|
||||
Def::Union(did) | Def::TyForeign(did) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
self.prohibit_type_params(path.segments.split_last().unwrap().1);
|
||||
self.ast_path_to_ty(span, did, path.segments.last().unwrap())
|
||||
|
@ -13,7 +13,7 @@
|
||||
//! A cast `e as U` is valid if one of the following holds:
|
||||
//! * `e` has type `T` and `T` coerces to `U`; *coercion-cast*
|
||||
//! * `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or
|
||||
//! unsize_kind(`T`) = unsize_kind(`U_0`); *ptr-ptr-cast*
|
||||
//! pointer_kind(`T`) = pointer_kind(`U_0`); *ptr-ptr-cast*
|
||||
//! * `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
|
||||
//! * `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
|
||||
//! * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
|
||||
@ -26,7 +26,7 @@
|
||||
//! * `e` is a function pointer type and `U` is an integer; *fptr-addr-cast*
|
||||
//!
|
||||
//! where `&.T` and `*T` are references of either mutability,
|
||||
//! and where unsize_kind(`T`) is the kind of the unsize info
|
||||
//! and where pointer_kind(`T`) is the kind of the unsize info
|
||||
//! in `T` - the vtable for a trait definition (e.g. `fmt::Display` or
|
||||
//! `Iterator`, not `Iterator<Item=u8>`) or a length (or `()` if `T: Sized`).
|
||||
//!
|
||||
@ -64,11 +64,16 @@ pub struct CastCheck<'tcx> {
|
||||
span: Span,
|
||||
}
|
||||
|
||||
/// The kind of the unsize info (length or vtable) - we only allow casts between
|
||||
/// fat pointers if their unsize-infos have the same kind.
|
||||
/// The kind of pointer and associated metadata (thin, length or vtable) - we
|
||||
/// only allow casts between fat pointers if their metadata have the same
|
||||
/// kind.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
enum UnsizeKind<'tcx> {
|
||||
enum PointerKind<'tcx> {
|
||||
/// No metadata attached, ie pointer to sized type or foreign type
|
||||
Thin,
|
||||
/// A trait object
|
||||
Vtable(Option<DefId>),
|
||||
/// Slice
|
||||
Length,
|
||||
/// The unsize info of this projection
|
||||
OfProjection(&'tcx ty::ProjectionTy<'tcx>),
|
||||
@ -79,22 +84,28 @@ enum UnsizeKind<'tcx> {
|
||||
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
/// Returns the kind of unsize information of t, or None
|
||||
/// if t is sized or it is unknown.
|
||||
fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
|
||||
fn pointer_kind(&self, t: Ty<'tcx>, span: Span) -> PointerKind<'tcx> {
|
||||
if self.type_is_known_to_be_sized(t, span) {
|
||||
return PointerKind::Thin;
|
||||
}
|
||||
|
||||
match t.sty {
|
||||
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
|
||||
ty::TySlice(_) | ty::TyStr => PointerKind::Length,
|
||||
ty::TyDynamic(ref tty, ..) =>
|
||||
Some(UnsizeKind::Vtable(tty.principal().map(|p| p.def_id()))),
|
||||
PointerKind::Vtable(tty.principal().map(|p| p.def_id())),
|
||||
ty::TyAdt(def, substs) if def.is_struct() => {
|
||||
// FIXME(arielb1): do some kind of normalization
|
||||
match def.struct_variant().fields.last() {
|
||||
None => None,
|
||||
Some(f) => self.unsize_kind(f.ty(self.tcx, substs)),
|
||||
None => PointerKind::Thin,
|
||||
Some(f) => self.pointer_kind(f.ty(self.tcx, substs), span),
|
||||
}
|
||||
}
|
||||
// Pointers to foreign types are thin, despite being unsized
|
||||
ty::TyForeign(..) => PointerKind::Thin,
|
||||
// We should really try to normalize here.
|
||||
ty::TyProjection(ref pi) => Some(UnsizeKind::OfProjection(pi)),
|
||||
ty::TyParam(ref p) => Some(UnsizeKind::OfParam(p)),
|
||||
_ => None,
|
||||
ty::TyProjection(ref pi) => PointerKind::OfProjection(pi),
|
||||
ty::TyParam(ref p) => PointerKind::OfParam(p),
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -446,20 +457,23 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
||||
debug!("check_ptr_ptr_cast m_expr={:?} m_cast={:?}", m_expr, m_cast);
|
||||
// ptr-ptr cast. vtables must match.
|
||||
|
||||
// Cast to sized is OK
|
||||
if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
|
||||
// Cast to thin pointer is OK
|
||||
let cast_kind = fcx.pointer_kind(m_cast.ty, self.span);
|
||||
if cast_kind == PointerKind::Thin {
|
||||
return Ok(CastKind::PtrPtrCast);
|
||||
}
|
||||
|
||||
// sized -> unsized? report invalid cast (don't complain about vtable kinds)
|
||||
if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
|
||||
// thin -> fat? report invalid cast (don't complain about vtable kinds)
|
||||
let expr_kind = fcx.pointer_kind(m_expr.ty, self.span);
|
||||
if expr_kind == PointerKind::Thin {
|
||||
return Err(CastError::SizedUnsizedCast);
|
||||
}
|
||||
|
||||
// vtable kinds must match
|
||||
match (fcx.unsize_kind(m_cast.ty), fcx.unsize_kind(m_expr.ty)) {
|
||||
(Some(a), Some(b)) if a == b => Ok(CastKind::PtrPtrCast),
|
||||
_ => Err(CastError::DifferingKinds),
|
||||
if cast_kind == expr_kind {
|
||||
Ok(CastKind::PtrPtrCast)
|
||||
} else {
|
||||
Err(CastError::DifferingKinds)
|
||||
}
|
||||
}
|
||||
|
||||
@ -467,9 +481,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
||||
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
|
||||
m_cast: &'tcx ty::TypeAndMut<'tcx>)
|
||||
-> Result<CastKind, CastError> {
|
||||
// fptr-ptr cast. must be to sized ptr
|
||||
// fptr-ptr cast. must be to thin ptr
|
||||
|
||||
if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
|
||||
if fcx.pointer_kind(m_cast.ty, self.span) == PointerKind::Thin {
|
||||
Ok(CastKind::FnPtrPtrCast)
|
||||
} else {
|
||||
Err(CastError::IllegalCast)
|
||||
@ -480,9 +494,9 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
||||
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
|
||||
m_expr: &'tcx ty::TypeAndMut<'tcx>)
|
||||
-> Result<CastKind, CastError> {
|
||||
// ptr-addr cast. must be from sized ptr
|
||||
// ptr-addr cast. must be from thin ptr
|
||||
|
||||
if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
|
||||
if fcx.pointer_kind(m_expr.ty, self.span) == PointerKind::Thin {
|
||||
Ok(CastKind::PtrAddrCast)
|
||||
} else {
|
||||
Err(CastError::NeedViaThinPtr)
|
||||
@ -519,7 +533,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
|
||||
m_cast: &'tcx ty::TypeAndMut<'tcx>)
|
||||
-> Result<CastKind, CastError> {
|
||||
// ptr-addr cast. pointer must be thin.
|
||||
if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
|
||||
if fcx.pointer_kind(m_cast.ty, self.span) == PointerKind::Thin {
|
||||
Ok(CastKind::AddrPtrCast)
|
||||
} else {
|
||||
Err(CastError::IllegalCast)
|
||||
|
@ -414,6 +414,9 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
||||
ty::TyAdt(def, _) => {
|
||||
self.assemble_inherent_impl_candidates_for_type(def.did);
|
||||
}
|
||||
ty::TyForeign(did) => {
|
||||
self.assemble_inherent_impl_candidates_for_type(did);
|
||||
}
|
||||
ty::TyParam(p) => {
|
||||
self.assemble_inherent_candidates_from_param(self_ty, p);
|
||||
}
|
||||
|
@ -451,6 +451,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
fn is_local(ty: Ty) -> bool {
|
||||
match ty.sty {
|
||||
ty::TyAdt(def, _) => def.did.is_local(),
|
||||
ty::TyForeign(did) => did.is_local(),
|
||||
|
||||
ty::TyDynamic(ref tr, ..) => tr.principal()
|
||||
.map_or(false, |p| p.def_id().is_local()),
|
||||
|
@ -117,6 +117,9 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
|
||||
ty::TyAdt(def, _) => {
|
||||
self.check_def_id(item, def.did);
|
||||
}
|
||||
ty::TyForeign(did) => {
|
||||
self.check_def_id(item, did);
|
||||
}
|
||||
ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
|
||||
self.check_def_id(item, data.principal().unwrap().def_id());
|
||||
}
|
||||
|
@ -68,10 +68,10 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
// In addition to the above rules, we restrict impls of defaulted traits
|
||||
// so that they can only be implemented on structs/enums. To see why this
|
||||
// restriction exists, consider the following example (#22978). Imagine
|
||||
// that crate A defines a defaulted trait `Foo` and a fn that operates
|
||||
// on pairs of types:
|
||||
// so that they can only be implemented on nominal types, such as structs,
|
||||
// enums or foreign types. To see why this restriction exists, consider the
|
||||
// following example (#22978). Imagine that crate A defines a defaulted trait
|
||||
// `Foo` and a fn that operates on pairs of types:
|
||||
//
|
||||
// ```
|
||||
// // Crate A
|
||||
@ -109,11 +109,12 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let opt_self_def_id = match self_ty.sty {
|
||||
ty::TyAdt(self_def, _) => Some(self_def.did),
|
||||
ty::TyForeign(did) => Some(did),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let msg = match opt_self_def_id {
|
||||
// We only want to permit structs/enums, but not *all* structs/enums.
|
||||
// We only want to permit nominal types, but not *all* nominal types.
|
||||
// They must be local to the current crate, so that people
|
||||
// can't do `unsafe impl Send for Rc<SomethingLocal>` or
|
||||
// `impl !Send for Box<SomethingLocalAndSend>`.
|
||||
|
@ -916,7 +916,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
NodeForeignItem(item) => {
|
||||
match item.node {
|
||||
ForeignItemStatic(..) => &no_generics,
|
||||
ForeignItemFn(_, _, ref generics) => generics
|
||||
ForeignItemFn(_, _, ref generics) => generics,
|
||||
ForeignItemType => &no_generics,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1094,7 +1095,8 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let substs = Substs::identity_for_item(tcx, def_id);
|
||||
tcx.mk_fn_def(def_id, substs)
|
||||
}
|
||||
ForeignItemStatic(ref t, _) => icx.to_ty(t)
|
||||
ForeignItemStatic(ref t, _) => icx.to_ty(t),
|
||||
ForeignItemType => tcx.mk_foreign(def_id),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1363,7 +1365,8 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
NodeForeignItem(item) => {
|
||||
match item.node {
|
||||
ForeignItemStatic(..) => &no_generics,
|
||||
ForeignItemFn(_, _, ref generics) => generics
|
||||
ForeignItemFn(_, _, ref generics) => generics,
|
||||
ForeignItemType => &no_generics,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,7 +305,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
||||
|
||||
match ty.sty {
|
||||
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
|
||||
ty::TyStr | ty::TyNever => {
|
||||
ty::TyStr | ty::TyNever | ty::TyForeign(..) => {
|
||||
// leaf type -- noop
|
||||
}
|
||||
|
||||
|
@ -419,6 +419,8 @@ pub enum ItemEnum {
|
||||
ForeignFunctionItem(Function),
|
||||
/// `static`s from an extern block
|
||||
ForeignStaticItem(Static),
|
||||
/// `type`s from an extern block
|
||||
ForeignTypeItem,
|
||||
MacroItem(Macro),
|
||||
PrimitiveItem(PrimitiveType),
|
||||
AssociatedConstItem(Type, Option<String>),
|
||||
@ -1646,6 +1648,7 @@ pub enum TypeKind {
|
||||
Trait,
|
||||
Variant,
|
||||
Typedef,
|
||||
Foreign,
|
||||
}
|
||||
|
||||
pub trait GetDefId {
|
||||
@ -2027,6 +2030,17 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
|
||||
is_generic: false,
|
||||
}
|
||||
}
|
||||
ty::TyForeign(did) => {
|
||||
inline::record_extern_fqn(cx, did, TypeKind::Foreign);
|
||||
let path = external_path(cx, &cx.tcx.item_name(did),
|
||||
None, false, vec![], Substs::empty());
|
||||
ResolvedPath {
|
||||
path: path,
|
||||
typarams: None,
|
||||
did: did,
|
||||
is_generic: false,
|
||||
}
|
||||
}
|
||||
ty::TyDynamic(ref obj, ref reg) => {
|
||||
if let Some(principal) = obj.principal() {
|
||||
let did = principal.def_id();
|
||||
@ -2840,6 +2854,9 @@ impl Clean<Item> for hir::ForeignItem {
|
||||
expr: "".to_string(),
|
||||
})
|
||||
}
|
||||
hir::ForeignItemType => {
|
||||
ForeignTypeItem
|
||||
}
|
||||
};
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
|
@ -41,6 +41,7 @@ pub enum ItemType {
|
||||
Constant = 17,
|
||||
AssociatedConst = 18,
|
||||
Union = 19,
|
||||
ForeignType = 20,
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +83,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
|
||||
clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
|
||||
clean::AssociatedTypeItem(..) => ItemType::AssociatedType,
|
||||
clean::DefaultImplItem(..) => ItemType::Impl,
|
||||
clean::ForeignTypeItem => ItemType::ForeignType,
|
||||
clean::StrippedItem(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -100,6 +102,7 @@ impl From<clean::TypeKind> for ItemType {
|
||||
clean::TypeKind::Const => ItemType::Constant,
|
||||
clean::TypeKind::Variant => ItemType::Variant,
|
||||
clean::TypeKind::Typedef => ItemType::Typedef,
|
||||
clean::TypeKind::Foreign => ItemType::ForeignType,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,6 +130,7 @@ impl ItemType {
|
||||
ItemType::AssociatedType => "associatedtype",
|
||||
ItemType::Constant => "constant",
|
||||
ItemType::AssociatedConst => "associatedconstant",
|
||||
ItemType::ForeignType => "foreigntype",
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +143,8 @@ impl ItemType {
|
||||
ItemType::Typedef |
|
||||
ItemType::Trait |
|
||||
ItemType::Primitive |
|
||||
ItemType::AssociatedType => NameSpace::Type,
|
||||
ItemType::AssociatedType |
|
||||
ItemType::ForeignType => NameSpace::Type,
|
||||
|
||||
ItemType::ExternCrate |
|
||||
ItemType::Import |
|
||||
|
@ -2044,6 +2044,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
ItemType::Primitive => ("primitives", "Primitive Types"),
|
||||
ItemType::AssociatedType => ("associated-types", "Associated Types"),
|
||||
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
|
||||
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
|
||||
};
|
||||
write!(w, "<h2 id='{id}' class='section-header'>\
|
||||
<a href=\"#{id}\">{name}</a></h2>\n<table>",
|
||||
@ -3679,7 +3680,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
|
||||
ItemType::Enum, ItemType::Constant, ItemType::Static, ItemType::Trait,
|
||||
ItemType::Function, ItemType::Typedef, ItemType::Union, ItemType::Impl,
|
||||
ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
|
||||
ItemType::AssociatedType, ItemType::AssociatedConst] {
|
||||
ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
|
||||
if items.iter().any(|it| {
|
||||
if let clean::DefaultImplItem(..) = it.inner {
|
||||
false
|
||||
@ -3708,6 +3709,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
|
||||
ItemType::Primitive => ("primitives", "Primitive Types"),
|
||||
ItemType::AssociatedType => ("associated-types", "Associated Types"),
|
||||
ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
|
||||
ItemType::ForeignType => ("foreign-types", "Foreign Types"),
|
||||
};
|
||||
sidebar.push_str(&format!("<li><a href=\"#{id}\">{name}</a></li>",
|
||||
id = short,
|
||||
|
@ -90,7 +90,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
|
||||
clean::VariantItem(..) | clean::MethodItem(..) |
|
||||
clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) |
|
||||
clean::ConstantItem(..) | clean::UnionItem(..) |
|
||||
clean::AssociatedConstItem(..) => {
|
||||
clean::AssociatedConstItem(..) | clean::ForeignTypeItem => {
|
||||
if i.def_id.is_local() {
|
||||
if !self.access_levels.is_exported(i.def_id) {
|
||||
return None;
|
||||
|
@ -10,25 +10,66 @@
|
||||
|
||||
//! A module for working with processes.
|
||||
//!
|
||||
//! # Examples
|
||||
//! This module is mostly concerned with spawning and interacting with child
|
||||
//! processes, but it also provides [`abort`] and [`exit`] for terminating the
|
||||
//! current process.
|
||||
//!
|
||||
//! Basic usage where we try to execute the `cat` shell command:
|
||||
//! # Spawning a process
|
||||
//!
|
||||
//! ```should_panic
|
||||
//! The [`Command`] struct is used to configure and spawn processes:
|
||||
//!
|
||||
//! ```
|
||||
//! use std::process::Command;
|
||||
//!
|
||||
//! let mut child = Command::new("/bin/cat")
|
||||
//! .arg("file.txt")
|
||||
//! .spawn()
|
||||
//! .expect("failed to execute child");
|
||||
//! let output = Command::new("echo")
|
||||
//! .arg("Hello world")
|
||||
//! .output()
|
||||
//! .expect("Failed to execute command");
|
||||
//!
|
||||
//! let ecode = child.wait()
|
||||
//! .expect("failed to wait on child");
|
||||
//!
|
||||
//! assert!(ecode.success());
|
||||
//! assert_eq!(b"Hello world\n", output.stdout.as_slice());
|
||||
//! ```
|
||||
//!
|
||||
//! Calling a command with input and reading its output:
|
||||
//! Several methods on [`Command`], such as [`spawn`] or [`output`], can be used
|
||||
//! to spawn a process. In particular, [`output`] spawns the child process and
|
||||
//! waits until the process terminates, while [`spawn`] will return a [`Child`]
|
||||
//! that represents the spawned child process.
|
||||
//!
|
||||
//! # Handling I/O
|
||||
//!
|
||||
//! The [`stdout`], [`stdin`], and [`stderr`] of a child process can be
|
||||
//! configured by passing an [`Stdio`] to the corresponding method on
|
||||
//! [`Command`]. Once spawned, they can be accessed from the [`Child`]. For
|
||||
//! example, piping output from one command into another command can be done
|
||||
//! like so:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::process::{Command, Stdio};
|
||||
//!
|
||||
//! // stdout must be configured with `Stdio::piped` in order to use
|
||||
//! // `echo_child.stdout`
|
||||
//! let echo_child = Command::new("echo")
|
||||
//! .arg("Oh no, a tpyo!")
|
||||
//! .stdout(Stdio::piped())
|
||||
//! .spawn()
|
||||
//! .expect("Failed to start echo process");
|
||||
//!
|
||||
//! // Note that `echo_child` is moved here, but we won't be needing
|
||||
//! // `echo_child` anymore
|
||||
//! let echo_out = echo_child.stdout.expect("Failed to open echo stdout");
|
||||
//!
|
||||
//! let mut sed_child = Command::new("sed")
|
||||
//! .arg("s/tpyo/typo/")
|
||||
//! .stdin(Stdio::from(echo_out))
|
||||
//! .stdout(Stdio::piped())
|
||||
//! .spawn()
|
||||
//! .expect("Failed to start sed process");
|
||||
//!
|
||||
//! let output = sed_child.wait_with_output().expect("Failed to wait on sed");
|
||||
//! assert_eq!(b"Oh no, a typo!\n", output.stdout.as_slice());
|
||||
//! ```
|
||||
//!
|
||||
//! Note that [`ChildStderr`] and [`ChildStdout`] implement [`Write`] and
|
||||
//! [`ChildStdin`] implements [`Read`]:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::process::{Command, Stdio};
|
||||
@ -52,6 +93,26 @@
|
||||
//!
|
||||
//! assert_eq!(b"test", output.stdout.as_slice());
|
||||
//! ```
|
||||
//!
|
||||
//! [`abort`]: fn.abort.html
|
||||
//! [`exit`]: fn.exit.html
|
||||
//!
|
||||
//! [`Command`]: struct.Command.html
|
||||
//! [`spawn`]: struct.Command.html#method.spawn
|
||||
//! [`output`]: struct.Command.html#method.output
|
||||
//!
|
||||
//! [`Child`]: struct.Child.html
|
||||
//! [`ChildStdin`]: struct.ChildStdin.html
|
||||
//! [`ChildStdout`]: struct.ChildStdout.html
|
||||
//! [`ChildStderr`]: struct.ChildStderr.html
|
||||
//! [`Stdio`]: struct.Stdio.html
|
||||
//!
|
||||
//! [`stdout`]: struct.Command.html#method.stdout
|
||||
//! [`stdin`]: struct.Command.html#method.stdin
|
||||
//! [`stderr`]: struct.Command.html#method.stderr
|
||||
//!
|
||||
//! [`Write`]: ../io/trait.Write.html
|
||||
//! [`Read`]: ../io/trait.Read.html
|
||||
|
||||
#![stable(feature = "process", since = "1.0.0")]
|
||||
|
||||
|
@ -2007,13 +2007,16 @@ pub enum ForeignItemKind {
|
||||
/// A foreign static item (`static ext: u8`), with optional mutability
|
||||
/// (the boolean is true when mutable)
|
||||
Static(P<Ty>, bool),
|
||||
/// A foreign type
|
||||
Ty,
|
||||
}
|
||||
|
||||
impl ForeignItemKind {
|
||||
pub fn descriptive_variant(&self) -> &str {
|
||||
match *self {
|
||||
ForeignItemKind::Fn(..) => "foreign function",
|
||||
ForeignItemKind::Static(..) => "foreign static item"
|
||||
ForeignItemKind::Static(..) => "foreign static item",
|
||||
ForeignItemKind::Ty => "foreign type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -404,6 +404,9 @@ declare_features! (
|
||||
|
||||
// `crate` as visibility modifier, synonymous to `pub(crate)`
|
||||
(active, crate_visibility_modifier, "1.23.0", Some(45388)),
|
||||
|
||||
// extern types
|
||||
(active, extern_types, "1.23.0", Some(43467)),
|
||||
);
|
||||
|
||||
declare_features! (
|
||||
@ -1398,13 +1401,23 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
|
||||
let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
|
||||
Some(val) => val.as_str().starts_with("llvm."),
|
||||
_ => false
|
||||
};
|
||||
if links_to_llvm {
|
||||
gate_feature_post!(&self, link_llvm_intrinsics, i.span,
|
||||
"linking to LLVM intrinsics is experimental");
|
||||
match i.node {
|
||||
ast::ForeignItemKind::Fn(..) |
|
||||
ast::ForeignItemKind::Static(..) => {
|
||||
let link_name = attr::first_attr_value_str_by_name(&i.attrs, "link_name");
|
||||
let links_to_llvm = match link_name {
|
||||
Some(val) => val.as_str().starts_with("llvm."),
|
||||
_ => false
|
||||
};
|
||||
if links_to_llvm {
|
||||
gate_feature_post!(&self, link_llvm_intrinsics, i.span,
|
||||
"linking to LLVM intrinsics is experimental");
|
||||
}
|
||||
}
|
||||
ast::ForeignItemKind::Ty => {
|
||||
gate_feature_post!(&self, extern_types, i.span,
|
||||
"extern types are experimental");
|
||||
}
|
||||
}
|
||||
|
||||
visit::walk_foreign_item(self, i)
|
||||
|
@ -1069,6 +1069,7 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> For
|
||||
ForeignItemKind::Static(t, m) => {
|
||||
ForeignItemKind::Static(folder.fold_ty(t), m)
|
||||
}
|
||||
ForeignItemKind::Ty => ForeignItemKind::Ty,
|
||||
},
|
||||
span: folder.new_span(ni.span)
|
||||
}
|
||||
|
@ -153,17 +153,15 @@ impl Diagnostic {
|
||||
fn from_diagnostic_builder(db: &DiagnosticBuilder,
|
||||
je: &JsonEmitter)
|
||||
-> Diagnostic {
|
||||
let sugg = db.suggestions.iter().flat_map(|sugg| {
|
||||
je.render(sugg).into_iter().map(move |rendered| {
|
||||
Diagnostic {
|
||||
message: sugg.msg.clone(),
|
||||
code: None,
|
||||
level: "help",
|
||||
spans: DiagnosticSpan::from_suggestion(sugg, je),
|
||||
children: vec![],
|
||||
rendered: Some(rendered),
|
||||
}
|
||||
})
|
||||
let sugg = db.suggestions.iter().map(|sugg| {
|
||||
Diagnostic {
|
||||
message: sugg.msg.clone(),
|
||||
code: None,
|
||||
level: "help",
|
||||
spans: DiagnosticSpan::from_suggestion(sugg, je),
|
||||
children: vec![],
|
||||
rendered: None,
|
||||
}
|
||||
});
|
||||
Diagnostic {
|
||||
message: db.message(),
|
||||
@ -356,9 +354,3 @@ impl DiagnosticCode {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonEmitter {
|
||||
fn render(&self, suggestion: &CodeSuggestion) -> Vec<String> {
|
||||
suggestion.splice_lines(&*self.cm).iter().map(|line| line.0.to_owned()).collect()
|
||||
}
|
||||
}
|
||||
|
@ -5687,6 +5687,24 @@ impl<'a> Parser<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse a type from a foreign module
|
||||
fn parse_item_foreign_type(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>)
|
||||
-> PResult<'a, ForeignItem> {
|
||||
self.expect_keyword(keywords::Type)?;
|
||||
|
||||
let ident = self.parse_ident()?;
|
||||
let hi = self.span;
|
||||
self.expect(&token::Semi)?;
|
||||
Ok(ast::ForeignItem {
|
||||
ident: ident,
|
||||
attrs: attrs,
|
||||
node: ForeignItemKind::Ty,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: lo.to(hi),
|
||||
vis: vis
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse extern crate links
|
||||
///
|
||||
/// # Examples
|
||||
@ -6161,6 +6179,10 @@ impl<'a> Parser<'a> {
|
||||
if self.check_keyword(keywords::Fn) {
|
||||
return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?));
|
||||
}
|
||||
// FOREIGN TYPE ITEM
|
||||
if self.check_keyword(keywords::Type) {
|
||||
return Ok(Some(self.parse_item_foreign_type(visibility, lo, attrs)?));
|
||||
}
|
||||
|
||||
// FIXME #5668: this will occur for a macro invocation:
|
||||
match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? {
|
||||
|
@ -1112,6 +1112,13 @@ impl<'a> State<'a> {
|
||||
self.end()?; // end the head-ibox
|
||||
self.end() // end the outer cbox
|
||||
}
|
||||
ast::ForeignItemKind::Ty => {
|
||||
self.head(&visibility_qualified(&item.vis, "type"))?;
|
||||
self.print_ident(item.ident)?;
|
||||
self.s.word(";")?;
|
||||
self.end()?; // end the head-ibox
|
||||
self.end() // end the outer cbox
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,6 +477,7 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a
|
||||
visitor.visit_generics(generics)
|
||||
}
|
||||
ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
|
||||
ForeignItemKind::Ty => (),
|
||||
}
|
||||
|
||||
walk_list!(visitor, visit_attribute, &foreign_item.attrs);
|
||||
|
22
src/test/compile-fail/extern-types-distinct-types.rs
Normal file
22
src/test/compile-fail/extern-types-distinct-types.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
type A;
|
||||
type B;
|
||||
}
|
||||
|
||||
fn foo(r: &A) -> &B {
|
||||
r //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() { }
|
28
src/test/compile-fail/extern-types-not-sync-send.rs
Normal file
28
src/test/compile-fail/extern-types-not-sync-send.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// Make sure extern types are !Sync and !Send.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
fn assert_sync<T: ?Sized + Sync>() { }
|
||||
fn assert_send<T: ?Sized + Send>() { }
|
||||
|
||||
fn main() {
|
||||
assert_sync::<A>();
|
||||
//~^ ERROR the trait bound `A: std::marker::Sync` is not satisfied
|
||||
|
||||
assert_send::<A>();
|
||||
//~^ ERROR the trait bound `A: std::marker::Send` is not satisfied
|
||||
}
|
43
src/test/compile-fail/extern-types-unsized.rs
Normal file
43
src/test/compile-fail/extern-types-unsized.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
|
||||
// Make sure extern types are !Sized.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
x: u8,
|
||||
tail: A,
|
||||
}
|
||||
|
||||
struct Bar<T: ?Sized> {
|
||||
x: u8,
|
||||
tail: T,
|
||||
}
|
||||
|
||||
fn assert_sized<T>() { }
|
||||
|
||||
fn main() {
|
||||
assert_sized::<A>();
|
||||
//~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
|
||||
|
||||
assert_sized::<Foo>();
|
||||
//~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
|
||||
|
||||
assert_sized::<Bar<A>>();
|
||||
//~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
|
||||
|
||||
assert_sized::<Bar<Bar<A>>>();
|
||||
//~^ ERROR the trait bound `A: std::marker::Sized` is not satisfied
|
||||
}
|
15
src/test/compile-fail/feature-gate-extern_types.rs
Normal file
15
src/test/compile-fail/feature-gate-extern_types.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern {
|
||||
type T; //~ ERROR extern types are experimental
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -14,7 +14,7 @@ fn main() {
|
||||
let _ = tup[0];
|
||||
//~^ ERROR cannot index into a value of type
|
||||
//~| HELP to access tuple elements, use
|
||||
//~| SUGGESTION let _ = tup.0
|
||||
//~| SUGGESTION tup.0
|
||||
|
||||
// the case where we show just a general hint
|
||||
let i = 0_usize;
|
||||
|
5
src/test/run-make/extern-fn-with-extern-types/Makefile
Normal file
5
src/test/run-make/extern-fn-with-extern-types/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
-include ../tools.mk
|
||||
|
||||
all: $(call NATIVE_STATICLIB,ctest)
|
||||
$(RUSTC) test.rs
|
||||
$(call RUN,test) || exit 1
|
17
src/test/run-make/extern-fn-with-extern-types/ctest.c
Normal file
17
src/test/run-make/extern-fn-with-extern-types/ctest.c
Normal file
@ -0,0 +1,17 @@
|
||||
// ignore-license
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct data {
|
||||
uint32_t magic;
|
||||
} data;
|
||||
|
||||
data* data_create(uint32_t magic) {
|
||||
static data d;
|
||||
d.magic = magic;
|
||||
return &d;
|
||||
}
|
||||
|
||||
uint32_t data_get(data* p) {
|
||||
return p->magic;
|
||||
}
|
27
src/test/run-make/extern-fn-with-extern-types/test.rs
Normal file
27
src/test/run-make/extern-fn-with-extern-types/test.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
#[link(name = "ctest", kind = "static")]
|
||||
extern {
|
||||
type data;
|
||||
|
||||
fn data_create(magic: u32) -> *mut data;
|
||||
fn data_get(data: *mut data) -> u32;
|
||||
}
|
||||
|
||||
const MAGIC: u32 = 0xdeadbeef;
|
||||
fn main() {
|
||||
unsafe {
|
||||
let data = data_create(MAGIC);
|
||||
assert_eq!(data_get(data), MAGIC);
|
||||
}
|
||||
}
|
27
src/test/run-pass/extern-types-inherent-impl.rs
Normal file
27
src/test/run-pass/extern-types-inherent-impl.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
// Test that inherent impls can be defined for extern types.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
impl A {
|
||||
fn foo(&self) { }
|
||||
}
|
||||
|
||||
fn use_foo(x: &A) {
|
||||
x.foo();
|
||||
}
|
||||
|
||||
fn main() { }
|
28
src/test/run-pass/extern-types-manual-sync-send.rs
Normal file
28
src/test/run-pass/extern-types-manual-sync-send.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// Test that unsafe impl for Sync/Send can be provided for extern types.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
unsafe impl Sync for A { }
|
||||
unsafe impl Send for A { }
|
||||
|
||||
fn assert_sync<T: ?Sized + Sync>() { }
|
||||
fn assert_send<T: ?Sized + Send>() { }
|
||||
|
||||
fn main() {
|
||||
assert_sync::<A>();
|
||||
assert_send::<A>();
|
||||
}
|
40
src/test/run-pass/extern-types-pointer-cast.rs
Normal file
40
src/test/run-pass/extern-types-pointer-cast.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// 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.
|
||||
|
||||
// Test that pointers to extern types can be casted from/to usize,
|
||||
// despite being !Sized.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
x: u8,
|
||||
tail: A,
|
||||
}
|
||||
|
||||
struct Bar<T: ?Sized> {
|
||||
x: u8,
|
||||
tail: T,
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const MAGIC: usize = 0xdeadbeef;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const MAGIC: usize = 0x12345678deadbeef;
|
||||
|
||||
fn main() {
|
||||
assert_eq!((MAGIC as *const A) as usize, MAGIC);
|
||||
assert_eq!((MAGIC as *const Foo) as usize, MAGIC);
|
||||
assert_eq!((MAGIC as *const Bar<A>) as usize, MAGIC);
|
||||
assert_eq!((MAGIC as *const Bar<Bar<A>>) as usize, MAGIC);
|
||||
}
|
26
src/test/run-pass/extern-types-size_of_val.rs
Normal file
26
src/test/run-pass/extern-types-size_of_val.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
use std::mem::{size_of_val, align_of_val};
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: &A = unsafe {
|
||||
&*(1usize as *const A)
|
||||
};
|
||||
|
||||
assert_eq!(size_of_val(x), 0);
|
||||
assert_eq!(align_of_val(x), 1);
|
||||
}
|
51
src/test/run-pass/extern-types-thin-pointer.rs
Normal file
51
src/test/run-pass/extern-types-thin-pointer.rs
Normal file
@ -0,0 +1,51 @@
|
||||
// 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.
|
||||
|
||||
// Test that pointers and references to extern types are thin, ie they have the same size and
|
||||
// alignment as a pointer to ().
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
use std::mem::{align_of, size_of};
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
x: u8,
|
||||
tail: A,
|
||||
}
|
||||
|
||||
struct Bar<T: ?Sized> {
|
||||
x: u8,
|
||||
tail: T,
|
||||
}
|
||||
|
||||
fn assert_thin<T: ?Sized>() {
|
||||
assert_eq!(size_of::<*const T>(), size_of::<*const ()>());
|
||||
assert_eq!(align_of::<*const T>(), align_of::<*const ()>());
|
||||
|
||||
assert_eq!(size_of::<*mut T>(), size_of::<*mut ()>());
|
||||
assert_eq!(align_of::<*mut T>(), align_of::<*mut ()>());
|
||||
|
||||
assert_eq!(size_of::<&T>(), size_of::<&()>());
|
||||
assert_eq!(align_of::<&T>(), align_of::<&()>());
|
||||
|
||||
assert_eq!(size_of::<&mut T>(), size_of::<&mut ()>());
|
||||
assert_eq!(align_of::<&mut T>(), align_of::<&mut ()>());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_thin::<A>();
|
||||
assert_thin::<Foo>();
|
||||
assert_thin::<Bar<A>>();
|
||||
assert_thin::<Bar<Bar<A>>>();
|
||||
}
|
35
src/test/run-pass/extern-types-trait-impl.rs
Normal file
35
src/test/run-pass/extern-types-trait-impl.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// 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.
|
||||
|
||||
// Test that traits can be implemented for extern types.
|
||||
|
||||
#![feature(extern_types)]
|
||||
|
||||
extern {
|
||||
type A;
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
fn foo(&self) { }
|
||||
}
|
||||
|
||||
impl Foo for A {
|
||||
fn foo(&self) { }
|
||||
}
|
||||
|
||||
fn assert_foo<T: ?Sized + Foo>() { }
|
||||
|
||||
fn use_foo<T: ?Sized + Foo>(x: &Foo) {
|
||||
x.foo();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_foo::<A>();
|
||||
}
|
@ -1 +1 @@
|
||||
{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":" let _a = 1 / (2 + 3);"}],"rendered":null}
|
||||
{"message":"unnecessary parentheses around assigned value","code":null,"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"#[warn(unused_parens)] on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":976,"byte_end":989,"line_start":22,"line_end":22,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":null}],"rendered":null}
|
||||
|
21
src/test/ui/lint/use_suggestion_json.rs
Normal file
21
src/test/ui/lint/use_suggestion_json.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: --error-format json
|
||||
|
||||
// The output for humans should just highlight the whole span without showing
|
||||
// the suggested replacement, but we also want to test that suggested
|
||||
// replacement only removes one set of parentheses, rather than naïvely
|
||||
// stripping away any starting or ending parenthesis characters—hence this
|
||||
// test of the JSON error format.
|
||||
|
||||
fn main() {
|
||||
let x: Iter;
|
||||
}
|
2
src/test/ui/lint/use_suggestion_json.stderr
Normal file
2
src/test/ui/lint/use_suggestion_json.stderr
Normal file
File diff suppressed because one or more lines are too long
@ -36,6 +36,7 @@ struct DiagnosticSpan {
|
||||
column_end: usize,
|
||||
is_primary: bool,
|
||||
label: Option<String>,
|
||||
suggested_replacement: Option<String>,
|
||||
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
|
||||
}
|
||||
|
||||
@ -164,15 +165,15 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>,
|
||||
}
|
||||
|
||||
// If the message has a suggestion, register that.
|
||||
if let Some(ref rendered) = diagnostic.rendered {
|
||||
let start_line = primary_spans.iter().map(|s| s.line_start).min().expect("\
|
||||
every suggestion should have at least one span");
|
||||
for (index, line) in rendered.lines().enumerate() {
|
||||
expected_errors.push(Error {
|
||||
line_num: start_line + index,
|
||||
kind: Some(ErrorKind::Suggestion),
|
||||
msg: line.to_string(),
|
||||
});
|
||||
for span in primary_spans {
|
||||
if let Some(ref suggested_replacement) = span.suggested_replacement {
|
||||
for (index, line) in suggested_replacement.lines().enumerate() {
|
||||
expected_errors.push(Error {
|
||||
line_num: span.line_start + index,
|
||||
kind: Some(ErrorKind::Suggestion),
|
||||
msg: line.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user