(And other kinds of items).
This brings trait/impl items in line with top-level items in this respect. It means we don't get the attributes when showing error messages for methods, etc. (a good thing, I think). Since attributes have spans it is still easy to create a span for the item + all attributes.
esac
}
+# Prints the absolute path of a directory to stdout
+abs_path() {
+ local _path="$1"
+ # Unset CDPATH because it causes havok: it makes the destination unpredictable
+ # and triggers 'cd' to print the path to stdout. Route `cd`'s output to /dev/null
+ # for good measure.
+ (unset CDPATH && cd "$_path" > /dev/null && pwd)
+}
+
msg "looking for configure programs"
need_cmd cmp
need_cmd mkdir
DEFAULT_BUILD="${CFG_CPUTYPE}-${CFG_OSTYPE}"
-CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
+CFG_SRC_DIR="$(abs_path $(dirname $0))/"
CFG_BUILD_DIR="$(pwd)/"
CFG_SELF="$0"
CFG_CONFIGURE_ARGS="$@"
CFG_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),beta)
-CFG_RELEASE=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
-CFG_PACKAGE_VERS=$(CFG_RELEASE_NUM)-beta$(CFG_PRERELEASE_VERSION)
+CFG_RELEASE=$(CFG_RELEASE_NUM)-beta
+# When building beta distributables just reuse the same "beta" name
+# so when we upload we'll always override the previous beta. This
+# doesn't actually impact the version reported by rustc - it's just
+# for file naming.
+CFG_PACKAGE_VERS=beta
CFG_DISABLE_UNSTABLE_FEATURES=1
endif
ifeq ($(CFG_RELEASE_CHANNEL),nightly)
PRETTY_DEPS_pretty-rfail = $(RFAIL_TESTS)
PRETTY_DEPS_pretty-bench = $(BENCH_TESTS)
PRETTY_DEPS_pretty-pretty = $(PRETTY_TESTS)
-# The stage- and host-specific dependencies are for e.g. macro_crate_test which pulls in
-# external crates.
-PRETTY_DEPS$(1)_H_$(3)_pretty-rpass =
-PRETTY_DEPS$(1)_H_$(3)_pretty-rpass-full = $$(HLIB$(1)_H_$(3))/stamp.syntax $$(HLIB$(1)_H_$(3))/stamp.rustc
-PRETTY_DEPS$(1)_H_$(3)_pretty-rfail =
-PRETTY_DEPS$(1)_H_$(3)_pretty-bench =
-PRETTY_DEPS$(1)_H_$(3)_pretty-pretty =
PRETTY_DIRNAME_pretty-rpass = run-pass
PRETTY_DIRNAME_pretty-rpass-valgrind = run-pass-valgrind
PRETTY_DIRNAME_pretty-rpass-full = run-pass-fulldeps
PRETTY_DIRNAME_pretty-bench = bench
PRETTY_DIRNAME_pretty-pretty = pretty
+define DEF_PRETTY_FULLDEPS
+PRETTY_DEPS$(1)_T_$(2)_H_$(3)_pretty-rpass-full = $$(CSREQ$(1)_T_$(3)_H_$(3))
+endef
+
+$(foreach host,$(CFG_HOST), \
+ $(foreach target,$(CFG_TARGET), \
+ $(foreach stage,$(STAGES), \
+ $(eval $(call DEF_PRETTY_FULLDEPS,$(stage),$(target),$(host))))))
+
define DEF_RUN_PRETTY_TEST
PRETTY_ARGS$(1)-T-$(2)-H-$(3)-$(4) := \
$$(call TEST_OK_FILE,$(1),$(2),$(3),$(4)): \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
$$(PRETTY_DEPS_$(4)) \
- $$(PRETTY_DEPS$(1)_H_$(3)_$(4))
+ $$(PRETTY_DEPS$(1)_T_$(2)_H_$(3)_$(4))
@$$(call E, run pretty-rpass [$(2)]: $$<)
$$(Q)touch $$@.start_time
$$(Q)$$(call CFG_RUN_CTEST_$(2),$(1),$$<,$(3)) \
fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf {
let f = output_base_name(config, testfile);
let mut fname = f.file_name().unwrap().to_os_string();
- fname.push("libaux");
+ fname.push(&format!(".{}.libaux", config.mode));
f.with_file_name(&fname)
}
}
```
-Traits also define an [object type](#object-types) with the same name as the
+Traits also define an [trait object](#trait-objects) with the same name as the
trait. Values of this type are created by [casting](#type-cast-expressions)
pointer values (pointing to a type for which an implementation of the given
trait is in scope) to pointers to the trait name, used as a type.
`"unix"` or `"windows"`. The value of this configuration option is defined
as a configuration itself, like `unix` or `windows`.
* `target_os = "..."`. Operating system of the target, examples include
- `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
+ `"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
`"bitrig"` or `"openbsd"`.
* `target_pointer_width = "..."`. Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
identifier, and a parenthesized expression-list. Method calls are resolved to
methods on specific traits, either statically dispatching to a method if the
exact `self`-type of the left-hand-side is known, or dynamically dispatching if
-the left-hand-side expression is an indirect [object type](#object-types).
+the left-hand-side expression is an indirect [trait object](#trait-objects).
### Field expressions
```
-### Object types
+### Trait objects
Every trait item (see [traits](#traits)) defines a type with the same name as
-the trait. This type is called the _object type_ of the trait. Object types
+the trait. This type is called the _trait object_ of the trait. Trait objects
permit "late binding" of methods, dispatched using _virtual method tables_
("vtables"). Whereas most calls to trait methods are "early bound" (statically
resolved) to specific implementations at compile time, a call to a method on an
-object type is only resolved to a vtable entry at compile time. The actual
+trait objects is only resolved to a vtable entry at compile time. The actual
implementation for each vtable entry can vary on an object-by-object basis.
Given a pointer-typed expression `E` of type `&T` or `Box<T>`, where `T`
implements trait `R`, casting `E` to the corresponding pointer type `&R` or
-`Box<R>` results in a value of the _object type_ `R`. This result is
+`Box<R>` results in a value of the _trait object_ `R`. This result is
represented as a pair of pointers: the vtable pointer for the `T`
implementation of `R`, and the pointer value of `E`.
-An example of an object type:
+An example of a trait object:
```
trait Printable {
}
```
-In this example, the trait `Printable` occurs as an object type in both the
+In this example, the trait `Printable` occurs as a trait object in both the
type signature of `print`, and the cast expression in `main`.
### Type parameters
% Universal Function Call Syntax
-Coming soon
+Sometimes, functions can have the same names. Consider this code:
+
+```rust
+trait Foo {
+ fn f(&self);
+}
+
+trait Bar {
+ fn f(&self);
+}
+
+struct Baz;
+
+impl Foo for Baz {
+ fn f(&self) { println!("Baz’s impl of Foo"); }
+}
+
+impl Bar for Baz {
+ fn f(&self) { println!("Baz’s impl of Bar"); }
+}
+
+let b = Baz;
+```
+
+If we were to try to call `b.f()`, we’d get an error:
+
+```text
+error: multiple applicable methods in scope [E0034]
+b.f();
+ ^~~
+note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
+`main::Baz`
+ fn f(&self) { println!("Baz’s impl of Foo"); }
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
+`main::Baz`
+ fn f(&self) { println!("Baz’s impl of Bar"); }
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+```
+
+We need a way to disambiguate which method we need. This feature is called
+‘universal function call syntax’, and it looks like this:
+
+```rust
+# trait Foo {
+# fn f(&self);
+# }
+# trait Bar {
+# fn f(&self);
+# }
+# struct Baz;
+# impl Foo for Baz {
+# fn f(&self) { println!("Baz’s impl of Foo"); }
+# }
+# impl Bar for Baz {
+# fn f(&self) { println!("Baz’s impl of Bar"); }
+# }
+# let b = Baz;
+Foo::f(&b);
+Bar::f(&b);
+```
+
+Let’s break it down.
+
+```rust,ignore
+Foo::
+Bar::
+```
+
+These halves of the invocation are the types of the two traits: `Foo` and
+`Bar`. This is what ends up actually doing the disambiguation between the two:
+Rust calls the one from the trait name you use.
+
+```rust,ignore
+f(&b)
+```
+
+When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
+will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
+not, and so we need to pass an explicit `&b`.
+
+[methodsyntax]: method-syntax.html
+
+# Angle-bracket Form
+
+The form of UFCS we just talked about:
+
+```rust,ignore
+Type::method(args);
+```
+
+Is a short-hand. There’s an expanded form of this that’s needed in some
+situations:
+
+```rust,ignore
+<Type as Trait>::method(args);
+```
+
+The `<>::` syntax is a means of providing a type hint. The type goes inside
+the `<>`s. In this case, the type is `Type as Trait`, indicating that we want
+`Trait`’s version of `method` to be called here. The `as Trait` part is
+optional if it’s not ambiguous. Same with the angle brackets, hence the
+shorter form.
+
+Here’s an example of using the longer form.
+
+```rust
+trait Foo {
+ fn clone(&self);
+}
+
+#[derive(Clone)]
+struct Bar;
+
+impl Foo for Bar {
+ fn clone(&self) {
+ println!("Making a clone of Bar");
+
+ <Bar as Clone>::clone(self);
+ }
+}
+```
+
+This will call the `Clone` trait’s `clone()` method, rather than `Foo`’s.
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Default + Sync + Send> Default for Arc<T> {
+impl<T: Default> Default for Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
fn default() -> Arc<T> { Arc::new(Default::default()) }
}
obligation.repr(self.tcx()));
self.infcx.probe(|snapshot| {
- let (skol_obligation_trait_ref, skol_map) =
- self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
- match self.match_impl(impl_def_id, obligation, snapshot,
- &skol_map, skol_obligation_trait_ref.trait_ref.clone()) {
- Ok(substs) => {
+ match self.match_impl(impl_def_id, obligation, snapshot) {
+ Ok((substs, skol_map)) => {
let vtable_impl = self.vtable_impl(impl_def_id,
substs,
obligation.cause.clone(),
let all_impls = self.all_impls(def_id);
for &impl_def_id in &all_impls {
self.infcx.probe(|snapshot| {
- let (skol_obligation_trait_pred, skol_map) =
- self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
- match self.match_impl(impl_def_id, obligation, snapshot,
- &skol_map, skol_obligation_trait_pred.trait_ref.clone()) {
+ match self.match_impl(impl_def_id, obligation, snapshot) {
Ok(_) => {
candidates.vec.push(ImplCandidate(impl_def_id));
}
// First, create the substitutions by matching the impl again,
// this time not in a probe.
self.infcx.commit_if_ok(|snapshot| {
- let (skol_obligation_trait_ref, skol_map) =
- self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
- let substs =
+ let (substs, skol_map) =
self.rematch_impl(impl_def_id, obligation,
- snapshot, &skol_map, skol_obligation_trait_ref.trait_ref);
+ snapshot);
debug!("confirm_impl_candidate substs={}", substs.repr(self.tcx()));
Ok(self.vtable_impl(impl_def_id, substs, obligation.cause.clone(),
obligation.recursion_depth + 1, skol_map, snapshot))
fn rematch_impl(&mut self,
impl_def_id: ast::DefId,
obligation: &TraitObligation<'tcx>,
- snapshot: &infer::CombinedSnapshot,
- skol_map: &infer::SkolemizationMap,
- skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
- -> Normalized<'tcx, Substs<'tcx>>
+ snapshot: &infer::CombinedSnapshot)
+ -> (Normalized<'tcx, Substs<'tcx>>, infer::SkolemizationMap)
{
- match self.match_impl(impl_def_id, obligation, snapshot,
- skol_map, skol_obligation_trait_ref) {
- Ok(substs) => substs,
+ match self.match_impl(impl_def_id, obligation, snapshot) {
+ Ok((substs, skol_map)) => (substs, skol_map),
Err(()) => {
self.tcx().sess.bug(
&format!("Impl {} was matchable against {} but now is not",
fn match_impl(&mut self,
impl_def_id: ast::DefId,
obligation: &TraitObligation<'tcx>,
- snapshot: &infer::CombinedSnapshot,
- skol_map: &infer::SkolemizationMap,
- skol_obligation_trait_ref: Rc<ty::TraitRef<'tcx>>)
- -> Result<Normalized<'tcx, Substs<'tcx>>, ()>
+ snapshot: &infer::CombinedSnapshot)
+ -> Result<(Normalized<'tcx, Substs<'tcx>>,
+ infer::SkolemizationMap), ()>
{
let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
return Err(());
}
+ let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions(
+ &obligation.predicate,
+ snapshot);
+ let skol_obligation_trait_ref = skol_obligation.trait_ref;
+
let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
obligation.cause.span,
impl_def_id);
return Err(());
}
- if let Err(e) = self.infcx.leak_check(skol_map, snapshot) {
+ if let Err(e) = self.infcx.leak_check(&skol_map, snapshot) {
debug!("match_impl: failed leak check due to `{}`",
ty::type_err_to_str(self.tcx(), &e));
return Err(());
}
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
- Ok(Normalized {
+ Ok((Normalized {
value: impl_substs,
obligations: impl_trait_ref.obligations
- })
+ }, skol_map))
}
fn fast_reject_trait_refs(&mut self,
try!(write!(fmt, "<span class='out-of-band'>"));
try!(write!(fmt,
r##"<span id='render-detail'>
- <a id="collapse-all" href="#">[-]</a> <a id="expand-all" href="#">[+]</a>
+ <a id="toggle-all-docs" href="#" title="collapse all docs">[-]</a>
</span>"##));
// Write `src` tag
match self.href(self.cx) {
Some(l) => {
try!(write!(fmt, "<a id='src-{}' class='srclink' \
- href='{}'>[src]</a>",
- self.item.def_id.node, l));
+ href='{}' title='{}'>[src]</a>",
+ self.item.def_id.node, l, "goto source code"));
}
None => {}
}
window.location = $('.srclink').attr('href');
}
- $("#expand-all").on("click", function() {
- $(".docblock").show();
- $(".toggle-label").hide();
- $(".toggle-wrapper").removeClass("collapsed");
- $(".collapse-toggle").children(".inner").html("-");
- });
-
- $("#collapse-all").on("click", function() {
- $(".docblock").hide();
- $(".toggle-label").show();
- $(".toggle-wrapper").addClass("collapsed");
- $(".collapse-toggle").children(".inner").html("+");
+ $("#toggle-all-docs").on("click", function() {
+ var toggle = $("#toggle-all-docs");
+ if (toggle.html() == "[-]") {
+ toggle.html("[+]");
+ toggle.attr("title", "expand all docs");
+ $(".docblock").hide();
+ $(".toggle-label").show();
+ $(".toggle-wrapper").addClass("collapsed");
+ $(".collapse-toggle").children(".inner").html("+");
+ } else {
+ toggle.html("[-]");
+ toggle.attr("title", "collapse all docs");
+ $(".docblock").show();
+ $(".toggle-label").hide();
+ $(".toggle-wrapper").removeClass("collapsed");
+ $(".collapse-toggle").children(".inner").html("-");
+ }
});
$(document).on("click", ".collapse-toggle", function() {
rx: &'a Receiver<T>
}
+/// An owning iterator over messages on a receiver, this iterator will block
+/// whenever `next` is called, waiting for a new message, and `None` will be
+/// returned when the corresponding channel has hung up.
+#[stable(feature = "receiver_into_iter", since = "1.1.0")]
+pub struct IntoIter<T> {
+ rx: Receiver<T>
+}
+
/// The sending-half of Rust's asynchronous channel type. This half can only be
/// owned by one task, but it can be cloned to send to other tasks.
#[stable(feature = "rust1", since = "1.0.0")]
fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
}
+#[stable(feature = "receiver_into_iter", since = "1.1.0")]
+impl<'a, T> IntoIterator for &'a Receiver<T> {
+ type Item = T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Iter<'a, T> { self.iter() }
+}
+
+impl<T> Iterator for IntoIter<T> {
+ type Item = T;
+ fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
+}
+
+#[stable(feature = "receiver_into_iter", since = "1.1.0")]
+impl <T> IntoIterator for Receiver<T> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ fn into_iter(self) -> IntoIter<T> {
+ IntoIter { rx: self }
+ }
+}
+
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Receiver<T> {
assert_eq!(count_rx.recv().unwrap(), 4);
}
+ #[test]
+ fn test_recv_into_iter_owned() {
+ let mut iter = {
+ let (tx, rx) = channel::<i32>();
+ tx.send(1).unwrap();
+ tx.send(2).unwrap();
+
+ rx.into_iter()
+ };
+ assert_eq!(iter.next().unwrap(), 1);
+ assert_eq!(iter.next().unwrap(), 2);
+ assert_eq!(iter.next().is_none(), true);
+ }
+
+ #[test]
+ fn test_recv_into_iter_borrowed() {
+ let (tx, rx) = channel::<i32>();
+ tx.send(1).unwrap();
+ tx.send(2).unwrap();
+ drop(tx);
+ let mut iter = (&rx).into_iter();
+ assert_eq!(iter.next().unwrap(), 1);
+ assert_eq!(iter.next().unwrap(), 2);
+ assert_eq!(iter.next().is_none(), true);
+ }
+
#[test]
fn try_recv_states() {
let (tx1, rx1) = channel::<i32>();
/// dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be access through this guard via its
-/// Deref and DerefMut implementations
+/// `Deref` and `DerefMut` implementations
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct MutexGuard<'a, T: 'a> {
-Subproject commit ebc6b04c29591108d3f28e724b4b9b74cd1232e6
+Subproject commit e54d4823d26cdb3f98e5a1b17e1c257cd329aa61
// aux-build:rlib_crate_test.rs
// ignore-stage1
// ignore-tidy-linelength
-// ignore-android
// ignore-cross-compile gives a different error message
#![feature(plugin)]
# on some platforms, but LLVM just prints a warning so that's fine for
# now.
$(1): simd.rs
- $$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs -C target-feature='+neon,+sse2'
+ $$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \
+ -C target-feature='+neon,+sse2' -C extra-filename=-$(1)
endef
$(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx))))
// Test that the CompilerCalls interface to the compiler works.
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private, path)]
#![feature(core)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private)]
// except according to those terms.
// no-prefer-dynamic
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private)]
// except according to those terms.
// ignore-pretty
-// ignore-android
+// ignore-cross-compile
#![feature(quote, rustc_private)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
// ignore-pretty: does not work well with `--test`
#![feature(quote, rustc_private)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-cross-compile
// ignore-pretty
// ignore-test
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
// ignore-pretty: does not work well with `--test`
#![feature(quote, rustc_private)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-android
+// ignore-cross-compile
// ignore-pretty: does not work well with `--test`
#![feature(quote, rustc_private)]
// This test can't be a unit test in std,
// because it needs TempDir, which is in extra
-// ignore-android
+// ignore-cross-compile
#![feature(rustc_private, path_ext)]
// except according to those terms.
// aux-build:rustdoc-default-impl.rs
-// ignore-android
+// ignore-cross-compile
extern crate rustdoc_default_impl as foo;
// except according to those terms.
// aux-build:rustdoc-extern-default-method.rs
-// ignore-android
+// ignore-cross-compile
extern crate rustdoc_extern_default_method as ext;
// except according to those terms.
// aux-build:rustdoc-extern-method.rs
-// ignore-android
+// ignore-cross-compile
#![feature(unboxed_closures)]
// except according to those terms.
// aux-build:rustdoc-ffi.rs
-// ignore-android
+// ignore-cross-compile
extern crate rustdoc_ffi as lib;
// except according to those terms.
// aux-build:inline-default-methods.rs
-// ignore-android
+// ignore-cross-compile
extern crate inline_default_methods;
// except according to those terms.
// aux-build:issue-13698.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_13698;
// except according to those terms.
// aux-build:issue-15318.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_15318;
// except according to those terms.
// aux-build:issue-15318.rs
-// ignore-android
+// ignore-cross-compile
#![feature(no_std)]
#![no_std]
// except according to those terms.
// aux-build:issue-17476.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_17476;
// except according to those terms.
// aux-build:issue-19190-3.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_19190_3;
// except according to those terms.
// aux-build:issue-20646.rs
-// ignore-android
+// ignore-cross-compile
#![feature(associated_types)]
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-20727.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_20727;
// except according to those terms.
// aux-build:issue-21092.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_21092;
// except according to those terms.
// aux-build:issue-21801.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_21801;
// except according to those terms.
// aux-build:issue-22025.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_22025;
// aux-build:issue-23207-1.rs
// aux-build:issue-23207-2.rs
-// ignore-android
+// ignore-cross-compile
extern crate issue_23207_2;