Auto merge of #54168 - kennytm:rollup, r=kennytm

Rollup of 11 pull requests

Successful merges:

 - #53371 (Do not emit E0277 on incorrect tuple destructured binding)
 - #53829 (Add rustc SHA to released DWARF debuginfo)
 - #53950 (Allow for opting out of ThinLTO and clean up LTO related cli flag handling.)
 - #53976 (Replace unwrap calls in example by expect)
 - #54070 (Add Error::description soft-deprecation to RELEASES)
 - #54076 (miri loop detector hashing)
 - #54119 (Add some unit tests for find_best_match_for_name)
 - #54147 (Add a test that tries to modify static memory at compile-time)
 - #54150 (Updated 1.29 release notes with --document-private-items flag)
 - #54163 (Update stage 0 to latest beta)
 - #54170 (COMPILER_TESTS.md has been moved)
This commit is contained in:
bors
2018-09-13 22:40:35 +00:00
38 changed files with 398 additions and 113 deletions

View File

@@ -368,8 +368,7 @@ will run all the tests on every platform we support. If it all works out,
[merge-queue]: https://buildbot2.rust-lang.org/homu/queue/rust
Speaking of tests, Rust has a comprehensive test suite. More information about
it can be found
[here](https://github.com/rust-lang/rust/blob/master/src/test/COMPILER_TESTS.md).
it can be found [here][rctd].
### External Dependencies
[external-dependencies]: #external-dependencies
@@ -654,5 +653,5 @@ are:
[rustforge]: https://forge.rust-lang.org/
[tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
[ro]: http://www.rustaceans.org/
[rctd]: ./src/test/COMPILER_TESTS.md
[rctd]: https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html
[cheatsheet]: https://buildbot2.rust-lang.org/homu/

View File

@@ -31,6 +31,8 @@ Cargo
using `--target`][cargo/5614]
- [Added the `cargo-fix` subcommand to automatically move project code from
2015 edition to 2018.][cargo/5723]
- [`cargo doc` can now optionally document private types using the
`--document-private-items` flag.][cargo/5543]
Misc
----
@@ -68,6 +70,7 @@ Compatibility Notes
[51178]: https://github.com/rust-lang/rust/pull/51178/
[51122]: https://github.com/rust-lang/rust/pull/51122
[50494]: https://github.com/rust-lang/rust/pull/50494/
[cargo/5543]: https://github.com/rust-lang/cargo/pull/5543
[cargo/5614]: https://github.com/rust-lang/cargo/pull/5614/
[cargo/5723]: https://github.com/rust-lang/cargo/pull/5723/
[cargo/5831]: https://github.com/rust-lang/cargo/pull/5831/
@@ -370,6 +373,8 @@ Compatibility Notes
- [The maximum number for `repr(align(N))` is now 2²⁹.][50378] Previously you
could enter higher numbers but they were not supported by LLVM. Up to 512MB
alignment should cover all use cases.
- The `.description()` method on the `std::error::Error` trait
[has been soft-deprecated][50163]. It is no longer required to implement it.
[48553]: https://github.com/rust-lang/rust/pull/48553/
[48851]: https://github.com/rust-lang/rust/pull/48851/
@@ -383,6 +388,7 @@ Compatibility Notes
[49719]: https://github.com/rust-lang/rust/pull/49719/
[49896]: https://github.com/rust-lang/rust/pull/49896/
[49968]: https://github.com/rust-lang/rust/pull/49968/
[50163]: https://github.com/rust-lang/rust/pull/50163
[50177]: https://github.com/rust-lang/rust/pull/50177/
[50378]: https://github.com/rust-lang/rust/pull/50378/
[50398]: https://github.com/rust-lang/rust/pull/50398/

View File

@@ -377,6 +377,10 @@
# Whether to verify generated LLVM IR
#verify-llvm-ir = false
# Map all debuginfo paths for libstd and crates to `/rust/$sha/$crate/...`,
# generally only set for releases
#remap-debuginfo = false
# =============================================================================
# Options for specific targets
#

View File

@@ -263,6 +263,10 @@ fn main() {
if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
cmd.arg("-Z").arg("force-unstable-if-unmarked");
}
if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
cmd.arg("--remap-path-prefix").arg(&map);
}
} else {
// Override linker if necessary.
if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {

View File

@@ -32,7 +32,7 @@ use native;
use test;
use tool;
use util::{add_lib_path, exe, libdir};
use {Build, DocTests, Mode};
use {Build, DocTests, Mode, GitRepo};
pub use Compiler;
@@ -876,6 +876,10 @@ impl<'a> Builder<'a> {
cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string());
}
if let Some(map) = self.build.debuginfo_map(GitRepo::Rustc) {
cargo.env("RUSTC_DEBUGINFO_MAP", map);
}
// Enable usage of unstable features
cargo.env("RUSTC_BOOTSTRAP", "1");
self.add_rust_test_threads(&mut cargo);
@@ -964,7 +968,7 @@ impl<'a> Builder<'a> {
let cc = ccacheify(&self.cc(target));
cargo.env(format!("CC_{}", target), &cc).env("CC", &cc);
let cflags = self.cflags(target).join(" ");
let cflags = self.cflags(target, GitRepo::Rustc).join(" ");
cargo
.env(format!("CFLAGS_{}", target), cflags.clone())
.env("CFLAGS", cflags.clone());

View File

@@ -39,7 +39,7 @@ use std::process::Command;
use build_helper::output;
use cc;
use Build;
use {Build, GitRepo};
use config::Target;
use cache::Interned;
@@ -107,7 +107,7 @@ pub fn find(build: &mut Build) {
build.cc.insert(target, compiler);
build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target)));
build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target)));
build.verbose(&format!("CFLAGS_{} = {:?}", &target, build.cflags(target, GitRepo::Rustc)));
if let Some(ar) = ar {
build.verbose(&format!("AR_{} = {:?}", &target, ar));
build.ar.insert(target, ar);

View File

@@ -30,7 +30,7 @@ use filetime::FileTime;
use serde_json;
use util::{exe, libdir, is_dylib, CiEnv};
use {Compiler, Mode};
use {Compiler, Mode, GitRepo};
use native;
use tool;
@@ -895,7 +895,7 @@ pub fn compiler_file(builder: &Builder,
target: Interned<String>,
file: &str) -> PathBuf {
let mut cmd = Command::new(compiler);
cmd.args(builder.cflags(target));
cmd.args(builder.cflags(target, GitRepo::Rustc));
cmd.arg(format!("-print-file-name={}", file));
let out = output(&mut cmd);
PathBuf::from(out.trim())

View File

@@ -109,6 +109,7 @@ pub struct Config {
pub rust_codegen_backends: Vec<Interned<String>>,
pub rust_codegen_backends_dir: String,
pub rust_verify_llvm_ir: bool,
pub rust_remap_debuginfo: bool,
pub build: Interned<String>,
pub hosts: Vec<Interned<String>>,
@@ -321,6 +322,7 @@ struct Rust {
deny_warnings: Option<bool>,
backtrace_on_ice: Option<bool>,
verify_llvm_ir: Option<bool>,
remap_debuginfo: Option<bool>,
}
/// TOML representation of how each build target is configured.
@@ -557,6 +559,7 @@ impl Config {
set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings));
set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
if let Some(ref backends) = rust.codegen_backends {
config.rust_codegen_backends = backends.iter()

View File

@@ -237,6 +237,11 @@ pub enum DocTests {
Only,
}
pub enum GitRepo {
Rustc,
Llvm,
}
/// Global configuration for the build system.
///
/// This structure transitively contains all configuration for the build system.
@@ -738,6 +743,21 @@ impl Build {
self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32)
}
fn debuginfo_map(&self, which: GitRepo) -> Option<String> {
if !self.config.rust_remap_debuginfo {
return None
}
let path = match which {
GitRepo::Rustc => {
let sha = self.rust_info.sha().expect("failed to find sha");
format!("/rustc/{}", sha)
}
GitRepo::Llvm => format!("/rustc/llvm"),
};
Some(format!("{}={}", self.src.display(), path))
}
/// Returns the path to the C compiler for the target specified.
fn cc(&self, target: Interned<String>) -> &Path {
self.cc[&target].path()
@@ -745,7 +765,7 @@ impl Build {
/// Returns a list of flags to pass to the C compiler for the target
/// specified.
fn cflags(&self, target: Interned<String>) -> Vec<String> {
fn cflags(&self, target: Interned<String>, which: GitRepo) -> Vec<String> {
// Filter out -O and /O (the optimization flags) that we picked up from
// cc-rs because the build scripts will determine that for themselves.
let mut base = self.cc[&target].args().iter()
@@ -767,6 +787,16 @@ impl Build {
if &*target == "i686-pc-windows-gnu" {
base.push("-fno-omit-frame-pointer".into());
}
if let Some(map) = self.debuginfo_map(which) {
let cc = self.cc(target);
if cc.ends_with("clang") || cc.ends_with("gcc") {
base.push(format!("-fdebug-prefix-map={}", map).into());
} else if cc.ends_with("clang-cl.exe") {
base.push("-Xclang".into());
base.push(format!("-fdebug-prefix-map={}", map).into());
}
}
base
}

View File

@@ -33,6 +33,7 @@ use util::{self, exe};
use build_helper::up_to_date;
use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;
use GitRepo;
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Llvm {
@@ -373,8 +374,8 @@ fn configure_cmake(builder: &Builder,
}
cfg.build_arg("-j").build_arg(builder.jobs().to_string());
cfg.define("CMAKE_C_FLAGS", builder.cflags(target).join(" "));
let mut cxxflags = builder.cflags(target).join(" ");
cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" "));
let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" ");
if building_dist_binaries {
if builder.config.llvm_static_stdcpp && !target.contains("windows") {
cxxflags.push_str(" -static-libstdc++");
@@ -680,7 +681,7 @@ impl Step for Openssl {
};
configure.arg(os);
configure.env("CC", builder.cc(target));
for flag in builder.cflags(target) {
for flag in builder.cflags(target, GitRepo::Rustc) {
configure.arg(flag);
}
// There is no specific os target for android aarch64 or x86_64,

View File

@@ -34,7 +34,7 @@ use tool::{self, Tool, SourceType};
use toolstate::ToolState;
use util::{self, dylib_path, dylib_path_var};
use Crate as CargoCrate;
use {DocTests, Mode};
use {DocTests, Mode, GitRepo};
const ADB_TEST_DIR: &str = "/data/tmp/work";
@@ -1142,7 +1142,7 @@ impl Step for Compiletest {
.arg("--cxx")
.arg(builder.cxx(target).unwrap())
.arg("--cflags")
.arg(builder.cflags(target).join(" "))
.arg(builder.cflags(target, GitRepo::Rustc).join(" "))
.arg("--llvm-components")
.arg(llvm_components.trim())
.arg("--llvm-cxxflags")

View File

@@ -55,6 +55,7 @@ export RUST_RELEASE_CHANNEL=nightly
if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp"
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo"
if [ "$NO_LLVM_ASSERTIONS" = "1" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"

View File

@@ -68,15 +68,13 @@ pub enum OptLevel {
SizeMin, // -Oz
}
/// This is what the `LtoCli` values get mapped to after resolving defaults and
/// and taking other command line options into account.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum Lto {
/// Don't do any LTO whatsoever
No,
/// Do a full crate graph LTO. The flavor is determined by the compiler
/// (currently the default is "fat").
Yes,
/// Do a full crate graph LTO with ThinLTO
Thin,
@@ -88,6 +86,23 @@ pub enum Lto {
Fat,
}
/// The different settings that the `-C lto` flag can have.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum LtoCli {
/// `-C lto=no`
No,
/// `-C lto=yes`
Yes,
/// `-C lto`
NoParam,
/// `-C lto=thin`
Thin,
/// `-C lto=fat`
Fat,
/// No `-C lto` flag passed
Unspecified,
}
#[derive(Clone, PartialEq, Hash)]
pub enum CrossLangLto {
LinkerPlugin(PathBuf),
@@ -801,7 +816,8 @@ macro_rules! options {
pub const parse_unpretty: Option<&'static str> =
Some("`string` or `string=string`");
pub const parse_lto: Option<&'static str> =
Some("one of `thin`, `fat`, or omitted");
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, \
`fat`, or omitted");
pub const parse_cross_lang_lto: Option<&'static str> =
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
or the path to the linker plugin");
@@ -809,7 +825,7 @@ macro_rules! options {
#[allow(dead_code)]
mod $mod_set {
use super::{$struct_name, Passes, Sanitizer, Lto, CrossLangLto};
use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto};
use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
use std::path::PathBuf;
@@ -1002,11 +1018,23 @@ macro_rules! options {
}
}
fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool {
if v.is_some() {
let mut bool_arg = None;
if parse_opt_bool(&mut bool_arg, v) {
*slot = if bool_arg.unwrap() {
LtoCli::Yes
} else {
LtoCli::No
};
return true
}
}
*slot = match v {
None => Lto::Yes,
Some("thin") => Lto::Thin,
Some("fat") => Lto::Fat,
None => LtoCli::NoParam,
Some("thin") => LtoCli::Thin,
Some("fat") => LtoCli::Fat,
Some(_) => return false,
};
true
@@ -1047,7 +1075,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
"extra arguments to append to the linker invocation (space separated)"),
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
"don't let linker strip dead code (turning it on can be used for code coverage)"),
lto: Lto = (Lto::No, parse_lto, [TRACKED],
lto: LtoCli = (LtoCli::Unspecified, parse_lto, [TRACKED],
"perform LLVM link-time optimizations"),
target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
"select target processor (rustc --print target-cpus for details)"),
@@ -2384,8 +2412,8 @@ mod dep_tracking {
use std::hash::Hash;
use std::path::PathBuf;
use std::collections::hash_map::DefaultHasher;
use super::{CrateType, DebugInfo, ErrorOutputType, Lto, OptLevel, OutputTypes,
Passes, Sanitizer, CrossLangLto};
use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
Passes, Sanitizer, LtoCli, CrossLangLto};
use syntax::feature_gate::UnstableFeatures;
use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
use syntax::edition::Edition;
@@ -2440,7 +2468,7 @@ mod dep_tracking {
impl_dep_tracking_hash_via_hash!(RelroLevel);
impl_dep_tracking_hash_via_hash!(Passes);
impl_dep_tracking_hash_via_hash!(OptLevel);
impl_dep_tracking_hash_via_hash!(Lto);
impl_dep_tracking_hash_via_hash!(LtoCli);
impl_dep_tracking_hash_via_hash!(DebugInfo);
impl_dep_tracking_hash_via_hash!(UnstableFeatures);
impl_dep_tracking_hash_via_hash!(OutputTypes);
@@ -2514,7 +2542,7 @@ mod tests {
use lint;
use middle::cstore;
use session::config::{build_configuration, build_session_options_and_crate_config};
use session::config::{Lto, CrossLangLto};
use session::config::{LtoCli, CrossLangLto};
use session::build_session;
use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator;
@@ -2948,7 +2976,7 @@ mod tests {
// Make sure changing a [TRACKED] option changes the hash
opts = reference.clone();
opts.cg.lto = Lto::Fat;
opts.cg.lto = LtoCli::Fat;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();

View File

@@ -550,9 +550,27 @@ impl Session {
// lto` and we've for whatever reason forced off ThinLTO via the CLI,
// then ensure we can't use a ThinLTO.
match self.opts.cg.lto {
config::Lto::No => {}
config::Lto::Yes if self.opts.cli_forced_thinlto_off => return config::Lto::Fat,
other => return other,
config::LtoCli::Unspecified => {
// The compiler was invoked without the `-Clto` flag. Fall
// through to the default handling
}
config::LtoCli::No => {
// The user explicitly opted out of any kind of LTO
return config::Lto::No;
}
config::LtoCli::Yes |
config::LtoCli::Fat |
config::LtoCli::NoParam => {
// All of these mean fat LTO
return config::Lto::Fat;
}
config::LtoCli::Thin => {
return if self.opts.cli_forced_thinlto_off {
config::Lto::Fat
} else {
config::Lto::Thin
};
}
}
// Ok at this point the target doesn't require anything and the user
@@ -1178,7 +1196,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
if sess.opts.incremental.is_some() {
match sess.lto() {
Lto::Yes |
Lto::Thin |
Lto::Fat => {
sess.err("can't perform LTO when compiling incrementally");

View File

@@ -1666,7 +1666,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
match sess.lto() {
Lto::Yes |
Lto::Fat => true,
Lto::Thin => {
// If we defer LTO to the linker, we haven't run LTO ourselves, so

View File

@@ -205,13 +205,12 @@ impl<'a> GccLinker<'a> {
self.linker_arg(&format!("-plugin-opt={}", opt_level));
self.linker_arg(&format!("-plugin-opt=mcpu={}", llvm_util::target_cpu(self.sess)));
match self.sess.opts.cg.lto {
match self.sess.lto() {
config::Lto::Thin |
config::Lto::ThinLocal => {
self.linker_arg("-plugin-opt=thin");
}
config::Lto::Fat |
config::Lto::Yes |
config::Lto::No => {
// default to regular LTO
}

View File

@@ -118,7 +118,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
Lto::ThinLocal => SymbolExportLevel::Rust,
// We're doing LTO for the entire crate graph
Lto::Yes | Lto::Fat | Lto::Thin => {
Lto::Fat | Lto::Thin => {
symbol_export::crates_export_threshold(&cgcx.crate_types)
}
@@ -201,7 +201,6 @@ pub(crate) fn run(cgcx: &CodegenContext,
.map(|c| c.as_ptr())
.collect::<Vec<_>>();
match cgcx.lto {
Lto::Yes | // `-C lto` == fat LTO by default
Lto::Fat => {
assert!(cached_modules.is_empty());
let opt_jobs = fat_lto(cgcx,

View File

@@ -937,7 +937,6 @@ fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
}
match sess.lto() {
Lto::Yes |
Lto::Fat |
Lto::No => false,
Lto::Thin |
@@ -1372,7 +1371,7 @@ fn execute_optimize_work_item(cgcx: &CodegenContext,
// require LTO so the request for LTO is always unconditionally
// passed down to the backend, but we don't actually want to do
// anything about it yet until we've got a final product.
Lto::Yes | Lto::Fat | Lto::Thin => {
Lto::Fat | Lto::Thin => {
cgcx.crate_types.len() != 1 ||
cgcx.crate_types[0] != config::CrateType::Rlib
}
@@ -1552,7 +1551,7 @@ fn start_executing_work(tcx: TyCtxt,
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
Some(Arc::new(exported_symbols))
}
Lto::Yes | Lto::Fat | Lto::Thin => {
Lto::Fat | Lto::Thin => {
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
for &cnum in tcx.crates().iter() {
exported_symbols.insert(cnum, copy_symbols(cnum));

View File

@@ -239,6 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator {
type MemoryKinds = !;
const MUT_STATIC_KIND: Option<!> = None; // no mutating of statics allowed
const DETECT_LOOPS: bool = true;
fn find_fn<'a>(
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,

View File

@@ -65,6 +65,8 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
/// detector period.
pub(super) steps_since_detector_enabled: isize,
/// Extra state to detect loops.
/// FIXME: Move this to the CTFE machine's state, out of the general miri engine.
pub(super) loop_detector: InfiniteLoopDetector<'a, 'mir, 'tcx, M>,
}
@@ -110,6 +112,7 @@ pub struct Frame<'mir, 'tcx: 'mir> {
pub stmt: usize,
}
// Not using the macro because that does not support types depending on 'tcx
impl<'a, 'mir, 'tcx: 'mir> HashStable<StableHashingContext<'a>> for Frame<'mir, 'tcx> {
fn hash_stable<W: StableHasherResult>(
&self,
@@ -144,11 +147,14 @@ pub enum StackPopCleanup {
None { cleanup: bool },
}
// Can't use the macro here because that does not support named enum fields.
impl<'a> HashStable<StableHashingContext<'a>> for StackPopCleanup {
fn hash_stable<W: StableHasherResult>(
&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
hasher: &mut StableHasher<W>)
{
mem::discriminant(self).hash_stable(hcx, hasher);
match self {
StackPopCleanup::Goto(ref block) => block.hash_stable(hcx, hasher),
StackPopCleanup::None { cleanup } => cleanup.hash_stable(hcx, hasher),

View File

@@ -12,29 +12,29 @@
//! This separation exists to ensure that no fancy miri features like
//! interpreting common C functions leak into CTFE.
use std::hash::Hash;
use rustc::hir::def_id::DefId;
use rustc::ich::StableHashingContext;
use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
use rustc::mir;
use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
use rustc_data_structures::stable_hasher::HashStable;
use super::{EvalContext, PlaceTy, OpTy};
/// Methods of this trait signifies a point where CTFE evaluation would fail
/// and some use case dependent behaviour can instead be applied
pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>> {
pub trait Machine<'mir, 'tcx>: Clone + Eq {
/// Additional data that can be accessed via the Memory
type MemoryData: Clone + Eq + Hash + for<'a> HashStable<StableHashingContext<'a>>;
type MemoryData: Clone + Eq;
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash;
type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq;
/// The memory kind to use for mutated statics -- or None if those are not supported.
const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
/// Whether to attempt to detect infinite loops (any kind of infinite
/// execution, really).
const DETECT_LOOPS: bool;
/// Entry point to all function calls.
///
/// Returns either the mir to use for the call, or `None` if execution should

View File

@@ -13,6 +13,7 @@
//! All high-level functions to write to memory work on places as destinations.
use std::convert::TryFrom;
use std::mem;
use rustc::ich::StableHashingContext;
use rustc::mir;
@@ -57,11 +58,13 @@ pub enum Place<Id=AllocId> {
},
}
// Can't use the macro here because that does not support named enum fields.
impl<'a> HashStable<StableHashingContext<'a>> for Place {
fn hash_stable<W: StableHasherResult>(
&self, hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
hasher: &mut StableHasher<W>)
{
mem::discriminant(self).hash_stable(hcx, hasher);
match self {
Place::Ptr(mem_place) => mem_place.hash_stable(hcx, hasher),

View File

@@ -62,14 +62,13 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
pub fn observe_and_analyze(
&mut self,
tcx: &TyCtxt<'b, 'tcx, 'tcx>,
machine: &M,
memory: &Memory<'a, 'mir, 'tcx, M>,
stack: &[Frame<'mir, 'tcx>],
) -> EvalResult<'tcx, ()> {
let mut hcx = tcx.get_stable_hashing_context();
let mut hasher = StableHasher::<u64>::new();
(machine, stack).hash_stable(&mut hcx, &mut hasher);
stack.hash_stable(&mut hcx, &mut hasher);
let hash = hasher.finish();
if self.hashes.insert(hash) {
@@ -79,7 +78,7 @@ impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
info!("snapshotting the state of the interpreter");
if self.snapshots.insert(EvalSnapshot::new(machine, memory, stack)) {
if self.snapshots.insert(EvalSnapshot::new(memory, stack)) {
// Spurious collision or first cycle
return Ok(())
}
@@ -345,7 +344,6 @@ impl<'a, 'b, 'mir, 'tcx, M> SnapshotContext<'b> for Memory<'a, 'mir, 'tcx, M>
/// The virtual machine state during const-evaluation at a given point in time.
struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
machine: M,
memory: Memory<'a, 'mir, 'tcx, M>,
stack: Vec<Frame<'mir, 'tcx>>,
}
@@ -354,21 +352,20 @@ impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M>
where M: Machine<'mir, 'tcx>,
{
fn new(
machine: &M,
memory: &Memory<'a, 'mir, 'tcx, M>,
stack: &[Frame<'mir, 'tcx>]) -> Self {
stack: &[Frame<'mir, 'tcx>]
) -> Self {
EvalSnapshot {
machine: machine.clone(),
memory: memory.clone(),
stack: stack.into(),
}
}
fn snapshot<'b: 'a>(&'b self)
-> (&'b M, MemorySnapshot<'b, 'mir, 'tcx, M>, Vec<FrameSnapshot<'a, 'tcx>>) {
let EvalSnapshot{ machine, memory, stack } = self;
(&machine, memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect())
-> (MemorySnapshot<'b, 'mir, 'tcx, M>, Vec<FrameSnapshot<'a, 'tcx>>)
{
let EvalSnapshot{ memory, stack } = self;
(memory.snapshot(), stack.iter().map(|frame| frame.snapshot(memory)).collect())
}
}
@@ -384,6 +381,8 @@ impl<'a, 'mir, 'tcx, M> Hash for EvalSnapshot<'a, 'mir, 'tcx, M>
}
}
// Not using the macro because we need special handling for `memory`, which the macro
// does not support at the same time as the extra bounds on the type.
impl<'a, 'b, 'mir, 'tcx, M> HashStable<StableHashingContext<'b>>
for EvalSnapshot<'a, 'mir, 'tcx, M>
where M: Machine<'mir, 'tcx>,
@@ -391,10 +390,10 @@ impl<'a, 'b, 'mir, 'tcx, M> HashStable<StableHashingContext<'b>>
fn hash_stable<W: StableHasherResult>(
&self,
hcx: &mut StableHashingContext<'b>,
hasher: &mut StableHasher<W>) {
let EvalSnapshot{ machine, memory, stack } = self;
(machine, &memory.data, stack).hash_stable(hcx, hasher);
hasher: &mut StableHasher<W>)
{
let EvalSnapshot{ memory: _, stack } = self;
stack.hash_stable(hcx, hasher);
}
}

View File

@@ -65,6 +65,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
}
}
if !M::DETECT_LOOPS {
return Ok(());
}
if self.loop_detector.is_empty() {
// First run of the loop detector
@@ -75,7 +79,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
self.loop_detector.observe_and_analyze(
&self.tcx,
&self.machine,
&self.memory,
&self.stack[..],
)

View File

@@ -298,12 +298,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
TypeVariableOrigin::TypeInference(pat.span)));
let element_tys = tcx.mk_type_list(element_tys_iter);
let pat_ty = tcx.mk_ty(ty::Tuple(element_tys));
self.demand_eqtype(pat.span, expected, pat_ty);
if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) {
err.emit();
// Walk subpatterns with an expected type of `err` in this case to silence
// further errors being emitted when using the bindings. #50333
let element_tys_iter = (0..max_len).map(|_| tcx.types.err);
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat_walk(elem, &tcx.types.err, def_bm, true);
}
tcx.mk_tup(element_tys_iter)
} else {
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
self.check_pat_walk(elem, &element_tys[i], def_bm, true);
}
pat_ty
}
}
PatKind::Box(ref inner) => {
let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
let uniq_ty = tcx.mk_box(inner_ty);

View File

@@ -97,6 +97,10 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> {
.file("../libbacktrace/sort.c")
.file("../libbacktrace/state.c");
let any_debug = env::var("RUSTC_DEBUGINFO").unwrap_or(String::new()) == "true" ||
env::var("RUSTC_DEBUGINFO_LINES").unwrap_or(String::new()) == "true";
build.debug(any_debug);
if target.contains("darwin") {
build.file("../libbacktrace/macho.c");
} else if target.contains("windows") {

View File

@@ -102,8 +102,8 @@ use sys;
/// }
///
/// // We are certain that our string doesn't have 0 bytes in the middle,
/// // so we can .unwrap()
/// let c_to_print = CString::new("Hello, world!").unwrap();
/// // so we can .expect()
/// let c_to_print = CString::new("Hello, world!").expect("CString::new failed");
/// unsafe {
/// my_printer(c_to_print.as_ptr());
/// }
@@ -175,7 +175,7 @@ pub struct CString {
/// unsafe { work_with(data.as_ptr()) }
/// }
///
/// let s = CString::new("data data data data").unwrap();
/// let s = CString::new("data data data data").expect("CString::new failed");
/// work(&s);
/// ```
///
@@ -314,7 +314,7 @@ impl CString {
///
/// extern { fn puts(s: *const c_char); }
///
/// let to_print = CString::new("Hello!").unwrap();
/// let to_print = CString::new("Hello!").expect("CString::new failed");
/// unsafe {
/// puts(to_print.as_ptr());
/// }
@@ -398,7 +398,7 @@ impl CString {
/// fn some_extern_function(s: *mut c_char);
/// }
///
/// let c_string = CString::new("Hello!").unwrap();
/// let c_string = CString::new("Hello!").expect("CString::new failed");
/// let raw = c_string.into_raw();
/// unsafe {
/// some_extern_function(raw);
@@ -428,7 +428,7 @@ impl CString {
/// ```
/// use std::ffi::CString;
///
/// let c_string = CString::new("foo").unwrap();
/// let c_string = CString::new("foo").expect("CString::new failed");
///
/// let ptr = c_string.into_raw();
///
@@ -460,12 +460,12 @@ impl CString {
/// use std::ffi::CString;
///
/// let valid_utf8 = vec![b'f', b'o', b'o'];
/// let cstring = CString::new(valid_utf8).unwrap();
/// assert_eq!(cstring.into_string().unwrap(), "foo");
/// let cstring = CString::new(valid_utf8).expect("CString::new failed");
/// assert_eq!(cstring.into_string().expect("into_string() call failed"), "foo");
///
/// let invalid_utf8 = vec![b'f', 0xff, b'o', b'o'];
/// let cstring = CString::new(invalid_utf8).unwrap();
/// let err = cstring.into_string().err().unwrap();
/// let cstring = CString::new(invalid_utf8).expect("CString::new failed");
/// let err = cstring.into_string().err().expect("into_string().err() failed");
/// assert_eq!(err.utf8_error().valid_up_to(), 1);
/// ```
@@ -489,7 +489,7 @@ impl CString {
/// ```
/// use std::ffi::CString;
///
/// let c_string = CString::new("foo").unwrap();
/// let c_string = CString::new("foo").expect("CString::new failed");
/// let bytes = c_string.into_bytes();
/// assert_eq!(bytes, vec![b'f', b'o', b'o']);
/// ```
@@ -511,7 +511,7 @@ impl CString {
/// ```
/// use std::ffi::CString;
///
/// let c_string = CString::new("foo").unwrap();
/// let c_string = CString::new("foo").expect("CString::new failed");
/// let bytes = c_string.into_bytes_with_nul();
/// assert_eq!(bytes, vec![b'f', b'o', b'o', b'\0']);
/// ```
@@ -534,7 +534,7 @@ impl CString {
/// ```
/// use std::ffi::CString;
///
/// let c_string = CString::new("foo").unwrap();
/// let c_string = CString::new("foo").expect("CString::new failed");
/// let bytes = c_string.as_bytes();
/// assert_eq!(bytes, &[b'f', b'o', b'o']);
/// ```
@@ -554,7 +554,7 @@ impl CString {
/// ```
/// use std::ffi::CString;
///
/// let c_string = CString::new("foo").unwrap();
/// let c_string = CString::new("foo").expect("CString::new failed");
/// let bytes = c_string.as_bytes_with_nul();
/// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']);
/// ```
@@ -573,9 +573,10 @@ impl CString {
/// ```
/// use std::ffi::{CString, CStr};
///
/// let c_string = CString::new(b"foo".to_vec()).unwrap();
/// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
/// let c_str = c_string.as_c_str();
/// assert_eq!(c_str, CStr::from_bytes_with_nul(b"foo\0").unwrap());
/// assert_eq!(c_str,
/// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
/// ```
#[inline]
#[stable(feature = "as_c_str", since = "1.20.0")]
@@ -592,16 +593,17 @@ impl CString {
/// ```
/// use std::ffi::{CString, CStr};
///
/// let c_string = CString::new(b"foo".to_vec()).unwrap();
/// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
/// let boxed = c_string.into_boxed_c_str();
/// assert_eq!(&*boxed, CStr::from_bytes_with_nul(b"foo\0").unwrap());
/// assert_eq!(&*boxed,
/// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed"));
/// ```
#[stable(feature = "into_boxed_c_str", since = "1.20.0")]
pub fn into_boxed_c_str(self) -> Box<CStr> {
unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
}
// Bypass "move out of struct which implements [`Drop`] trait" restriction.
/// Bypass "move out of struct which implements [`Drop`] trait" restriction.
///
/// [`Drop`]: ../ops/trait.Drop.html
fn into_inner(self) -> Box<[u8]> {
@@ -1031,7 +1033,7 @@ impl CStr {
/// use std::ffi::{CStr, CString};
///
/// unsafe {
/// let cstring = CString::new("hello").unwrap();
/// let cstring = CString::new("hello").expect("CString::new failed");
/// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
/// assert_eq!(cstr, &*cstring);
/// }
@@ -1058,7 +1060,7 @@ impl CStr {
/// # #![allow(unused_must_use)]
/// use std::ffi::{CString};
///
/// let ptr = CString::new("Hello").unwrap().as_ptr();
/// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
/// unsafe {
/// // `ptr` is dangling
/// *ptr;
@@ -1067,14 +1069,14 @@ impl CStr {
///
/// This happens because the pointer returned by `as_ptr` does not carry any
/// lifetime information and the [`CString`] is deallocated immediately after
/// the `CString::new("Hello").unwrap().as_ptr()` expression is evaluated.
/// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated.
/// To fix the problem, bind the `CString` to a local variable:
///
/// ```no_run
/// # #![allow(unused_must_use)]
/// use std::ffi::{CString};
///
/// let hello = CString::new("Hello").unwrap();
/// let hello = CString::new("Hello").expect("CString::new failed");
/// let ptr = hello.as_ptr();
/// unsafe {
/// // `ptr` is valid because `hello` is in scope
@@ -1106,7 +1108,7 @@ impl CStr {
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(c_str.to_bytes(), b"foo");
/// ```
#[inline]
@@ -1132,7 +1134,7 @@ impl CStr {
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(c_str.to_bytes_with_nul(), b"foo\0");
/// ```
#[inline]
@@ -1159,7 +1161,7 @@ impl CStr {
/// ```
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").unwrap();
/// let c_str = CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(c_str.to_str(), Ok("foo"));
/// ```
#[stable(feature = "cstr_to_str", since = "1.4.0")]
@@ -1200,7 +1202,8 @@ impl CStr {
/// use std::borrow::Cow;
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"Hello World\0").unwrap();
/// let c_str = CStr::from_bytes_with_nul(b"Hello World\0")
/// .expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(c_str.to_string_lossy(), Cow::Borrowed("Hello World"));
/// ```
///
@@ -1210,7 +1213,8 @@ impl CStr {
/// use std::borrow::Cow;
/// use std::ffi::CStr;
///
/// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0").unwrap();
/// let c_str = CStr::from_bytes_with_nul(b"Hello \xF0\x90\x80World\0")
/// .expect("CStr::from_bytes_with_nul failed");
/// assert_eq!(
/// c_str.to_string_lossy(),
/// Cow::Owned(String::from("Hello <20>World")) as Cow<str>
@@ -1231,9 +1235,9 @@ impl CStr {
/// ```
/// use std::ffi::CString;
///
/// let c_string = CString::new(b"foo".to_vec()).unwrap();
/// let c_string = CString::new(b"foo".to_vec()).expect("CString::new failed");
/// let boxed = c_string.into_boxed_c_str();
/// assert_eq!(boxed.into_c_string(), CString::new("foo").unwrap());
/// assert_eq!(boxed.into_c_string(), CString::new("foo").expect("CString::new failed"));
/// ```
#[stable(feature = "into_boxed_c_str", since = "1.20.0")]
pub fn into_c_string(self: Box<CStr>) -> CString {

View File

@@ -11,7 +11,7 @@
use std::cmp;
use symbol::Symbol;
/// To find the Levenshtein distance between two strings
/// Find the Levenshtein distance between two strings
pub fn lev_distance(a: &str, b: &str) -> usize {
// cases which don't require further computation
if a.is_empty() {
@@ -41,10 +41,12 @@ pub fn lev_distance(a: &str, b: &str) -> usize {
} dcol[t_last + 1]
}
/// To find the best match for a given string from an iterator of names
/// Find the best match for a given word in the given iterator
///
/// As a loose rule to avoid the obviously incorrect suggestions, it takes
/// an optional limit for the maximum allowable edit distance, which defaults
/// to one-third of the given word.
///
/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
/// a lower(upper)case letters mismatch.
pub fn find_best_match_for_name<'a, T>(iter_names: T,
@@ -105,3 +107,39 @@ fn test_lev_distance() {
assert_eq!(lev_distance(b, c), 1);
assert_eq!(lev_distance(c, b), 1);
}
#[test]
fn test_find_best_match_for_name() {
use with_globals;
with_globals(|| {
let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")];
assert_eq!(
find_best_match_for_name(input.iter(), "aaaa", None),
Some(Symbol::intern("aaab"))
);
assert_eq!(
find_best_match_for_name(input.iter(), "1111111111", None),
None
);
let input = vec![Symbol::intern("aAAA")];
assert_eq!(
find_best_match_for_name(input.iter(), "AAAA", None),
Some(Symbol::intern("aAAA"))
);
let input = vec![Symbol::intern("AAAA")];
// Returns None because `lev_distance > max_dist / 3`
assert_eq!(
find_best_match_for_name(input.iter(), "aaaa", None),
None
);
let input = vec![Symbol::intern("AAAA")];
assert_eq!(
find_best_match_for_name(input.iter(), "aaaa", Some(4)),
Some(Symbol::intern("AAAA"))
);
})
}

View File

@@ -12,7 +12,7 @@
# source tarball for a stable release you'll likely see `1.x.0` for rustc and
# `0.x.0` for Cargo where they were released on `date`.
date: 2018-08-01
date: 2018-09-11
rustc: beta
cargo: beta

View File

@@ -16,11 +16,11 @@ all:
$(RUSTC) -C extra-filename=foo dummy.rs 2>&1
#Option taking no argument
$(RUSTC) -C lto= dummy.rs 2>&1 | \
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
$(RUSTC) -C lto=1 dummy.rs 2>&1 | \
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
$(RUSTC) -C lto=foo dummy.rs 2>&1 | \
$(CGREP) 'codegen option `lto` - one of `thin`, `fat`, or'
$(CGREP) 'codegen option `lto` - either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted'
$(RUSTC) -C lto dummy.rs
# Should not link dead code...

View File

@@ -1,6 +1,30 @@
-include ../tools.mk
all:
all: noparam bool_true bool_false thin fat
noparam:
$(RUSTC) lib.rs
$(RUSTC) main.rs -C lto
$(call RUN,main)
bool_true:
$(RUSTC) lib.rs
$(RUSTC) main.rs -C lto=yes
$(call RUN,main)
bool_false:
$(RUSTC) lib.rs
$(RUSTC) main.rs -C lto=off
$(call RUN,main)
thin:
$(RUSTC) lib.rs
$(RUSTC) main.rs -C lto=thin
$(call RUN,main)
fat:
$(RUSTC) lib.rs
$(RUSTC) main.rs -C lto=fat
$(call RUN,main)

View File

@@ -0,0 +1,37 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
// New test for #53818: modifying static memory at compile-time is not allowed.
// The test should never succeed.
#![feature(const_raw_ptr_deref)]
#![feature(const_let)]
use std::cell::UnsafeCell;
struct Foo(UnsafeCell<u32>);
unsafe impl Send for Foo {}
unsafe impl Sync for Foo {}
static FOO: Foo = Foo(UnsafeCell::new(42));
static BAR: () = unsafe {
*FOO.0.get() = 5;
//~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
// This error is caused by a separate bug that the feature gate error is reported
// even though the feature gate "const_let" is active.
//~| statements in statics are unstable (see issue #48821)
};
fn main() {
println!("{}", unsafe { *FOO.0.get() });
}

View File

@@ -0,0 +1,18 @@
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> $DIR/mod-static-with-const-fn.rs:27:6
|
LL | *FOO.0.get() = 5;
| ^^^^^^^^^^^
error[E0658]: statements in statics are unstable (see issue #48821)
--> $DIR/mod-static-with-const-fn.rs:27:5
|
LL | *FOO.0.get() = 5;
| ^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_let)] to the crate attributes to enable
error: aborting due to 2 previous errors
Some errors occurred: E0015, E0658.
For more information about an error, try `rustc --explain E0015`.

View File

@@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-musl
// ignore-x86
// error-pattern: cycle detected
struct Foo {

View File

@@ -0,0 +1,28 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <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.
// Hide irrelevant E0277 errors (#50333)
trait T {}
struct A;
impl T for A {}
impl A {
fn new() -> Self {
Self {}
}
}
fn main() {
let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
//~^ ERROR mismatched types
let ts: Vec<&T> = vec![&a, &b, &c];
// There is no E0277 error above, as `a`, `b` and `c` are `TyErr`
}

View File

@@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/elide-errors-on-mismatched-tuple.rs:24:9
|
LL | let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three
| ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
|
= note: expected type `(A, A)`
found type `(_, _, _)`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.

View File

@@ -8,6 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-musl
// ignore-x86
use std::fmt::Debug;
trait Foo {

View File

@@ -1,5 +1,5 @@
error[E0643]: method `foo` has incompatible signature for trait
--> $DIR/impl-generic-mismatch.rs:18:12
--> $DIR/impl-generic-mismatch.rs:21:12
|
LL | fn foo(&self, _: &impl Debug);
| ---------- declaration in trait here
@@ -12,7 +12,7 @@ LL | fn foo(&self, _: &impl Debug) { }
| -- ^^^^^^^^^^
error[E0643]: method `bar` has incompatible signature for trait
--> $DIR/impl-generic-mismatch.rs:27:23
--> $DIR/impl-generic-mismatch.rs:30:23
|
LL | fn bar<U: Debug>(&self, _: &U);
| - declaration in trait here
@@ -25,7 +25,7 @@ LL | fn bar<U: Debug>(&self, _: &U) { }
| ^^^^^^^^^^ ^
error[E0643]: method `hash` has incompatible signature for trait
--> $DIR/impl-generic-mismatch.rs:38:33
--> $DIR/impl-generic-mismatch.rs:41:33
|
LL | fn hash(&self, hasher: &mut impl Hasher) {}
| ^^^^^^^^^^^ expected generic parameter, found `impl Trait`