From f89ba5da4a7f9a6446b91cb621ed000d28529d82 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 18 Oct 2016 10:56:12 -0700 Subject: [PATCH 01/41] Fix some mistakes in HRTB docs The example code for higher-ranked trait bounds on closures had an unnecessary `mut` which was confusing, and the text referred to an mutable reference which does not exist in the code (and isn't needed). Removed the `mut`s and fixed the text to better describe the actual error for the failing example. --- src/doc/book/closures.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index 3ed85c1a90b69..60b99c08825ee 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -327,7 +327,7 @@ that takes a reference like so: fn call_with_ref(some_closure:F) -> i32 where F: Fn(&i32) -> i32 { - let mut value = 0; + let value = 0; some_closure(&value) } ``` @@ -340,14 +340,15 @@ fn call_with_ref<'a, F>(some_closure:F) -> i32 where F: Fn(&'a i32) -> i32 { ``` -However this presents a problem in our case. When you specify the explicit -lifetime on a function it binds that lifetime to the *entire* scope of the function -instead of just the invocation scope of our closure. This means that the borrow checker -will see a mutable reference in the same lifetime as our immutable reference and fail -to compile. +However, this presents a problem in our case. When a function has an explicit +lifetime parameter, that lifetime must be at least as long as the *entire* +call to that function. The borrow checker will complain that `value` doesn't +live long enough, because it is only in scope after its declaration inside the +function body. -In order to say that we only need the lifetime to be valid for the invocation scope -of the closure we can use Higher-Ranked Trait Bounds with the `for<...>` syntax: +What we need is a closure that can borrow its argument only for its own +invocation scope, not for the outer function's scope. In order to say that, +we can use Higher-Ranked Trait Bounds with the `for<...>` syntax: ```ignore fn call_with_ref(some_closure:F) -> i32 @@ -362,7 +363,7 @@ expect. fn call_with_ref(some_closure:F) -> i32 where F: for<'a> Fn(&'a i32) -> i32 { - let mut value = 0; + let value = 0; some_closure(&value) } ``` From e47da0c23c91feea24e5b961a662754d689bb082 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 20 Oct 2016 17:59:41 -0700 Subject: [PATCH 02/41] Add release notes for 1.12.1 --- RELEASES.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index e6f18f9f7ba55..222ad3aa112af 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,30 @@ +Version 1.12.1 (2016-10-20) +=========================== + +Regression Fixes +---------------- + +* [ICE: 'rustc' panicked at 'assertion failed: concrete_substs.is_normalized_for_trans()' #36381][36381] +* [Confusion with double negation and booleans][36856] +* [rustc 1.12.0 fails with SIGSEGV in release mode (syn crate 0.8.0)][36875] +* [Rustc 1.12.0 Windows build of `ethcore` crate fails with LLVM error][36924] +* [1.12.0: High memory usage when linking in release mode with debug info][36926] +* [Corrupted memory after updated to 1.12][36936] +* ["Let NullaryConstructor = something;" causes internal compiler error: "tried to overwrite interned AdtDef"][37026] +* [Fix ICE: inject bitcast if types mismatch for invokes/calls/stores][37112] +* [debuginfo: Handle spread_arg case in MIR-trans in a more stable way.][37153] + +[36381]: https://github.com/rust-lang/rust/issues/36381 +[36856]: https://github.com/rust-lang/rust/issues/36856 +[36875]: https://github.com/rust-lang/rust/issues/36875 +[36924]: https://github.com/rust-lang/rust/issues/36924 +[36926]: https://github.com/rust-lang/rust/issues/36926 +[36936]: https://github.com/rust-lang/rust/issues/36936 +[37026]: https://github.com/rust-lang/rust/issues/37026 +[37112]: https://github.com/rust-lang/rust/issues/37112 +[37153]: https://github.com/rust-lang/rust/issues/37153 + + Version 1.12.0 (2016-09-29) =========================== From 20c301330cf17dd98c58aaff602586b99f7676fc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 31 Oct 2016 09:36:30 -0700 Subject: [PATCH 03/41] rustc: Add knowledge of Windows subsystems. This commit is an implementation of [RFC 1665] which adds support for the `#![windows_subsystem]` attribute. This attribute allows specifying either the "windows" or "console" subsystems on Windows to the linker. [RFC 1665]: https://github.com/rust-lang/rfcs/blob/master/text/1665-windows-subsystem.md Previously all Rust executables were compiled as the "console" subsystem which meant that if you wanted a graphical application it would erroneously pop up a console whenever opened. When compiling an application, however, this is undesired behavior and the "windows" subsystem is used instead to have control over user interactions. This attribute is validated, but ignored on all non-Windows platforms. cc #37499 --- src/librustc_trans/back/link.rs | 12 ++++++-- src/librustc_trans/back/linker.rs | 29 +++++++++++++++++++ src/librustc_trans/base.rs | 17 +++++++++-- src/librustc_trans/lib.rs | 1 + src/libsyntax/feature_gate.rs | 9 ++++++ .../compile-fail/windows-subsystem-gated.rs | 14 +++++++++ .../compile-fail/windows-subsystem-invalid.rs | 15 ++++++++++ src/test/run-make/windows-subsystem/Makefile | 5 ++++ .../run-make/windows-subsystem/console.rs | 15 ++++++++++ .../run-make/windows-subsystem/windows.rs | 14 +++++++++ 10 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 src/test/compile-fail/windows-subsystem-gated.rs create mode 100644 src/test/compile-fail/windows-subsystem-invalid.rs create mode 100644 src/test/run-make/windows-subsystem/Makefile create mode 100644 src/test/run-make/windows-subsystem/console.rs create mode 100644 src/test/run-make/windows-subsystem/windows.rs diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e46bdbb5ccf4a..ad8e0c1ee59f6 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -636,7 +636,7 @@ fn link_natively(sess: &Session, { let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, - objects, out_filename, outputs); + objects, out_filename, outputs, trans); } cmd.args(&sess.target.target.options.late_link_args); for obj in &sess.target.target.options.post_link_objects { @@ -711,7 +711,8 @@ fn link_args(cmd: &mut Linker, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, - outputs: &OutputFilenames) { + outputs: &OutputFilenames, + trans: &CrateTranslation) { // The default library location, we need this to find the runtime. // The location of crates will be determined as needed. @@ -726,6 +727,13 @@ fn link_args(cmd: &mut Linker, } cmd.output_filename(out_filename); + if crate_type == config::CrateTypeExecutable && + sess.target.target.options.is_like_windows { + if let Some(ref s) = trans.windows_subsystem { + cmd.subsystem(s); + } + } + // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. if crate_type != config::CrateTypeExecutable { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 3222571a76e17..860903d259fe5 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -92,6 +92,7 @@ pub trait Linker { fn whole_archives(&mut self); fn no_whole_archives(&mut self); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); + fn subsystem(&mut self, subsystem: &str); } pub struct GnuLinker<'a> { @@ -294,6 +295,10 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg(arg); } + + fn subsystem(&mut self, subsystem: &str) { + self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem)); + } } pub struct MsvcLinker<'a> { @@ -441,6 +446,30 @@ impl<'a> Linker for MsvcLinker<'a> { arg.push(path); self.cmd.arg(&arg); } + + fn subsystem(&mut self, subsystem: &str) { + // Note that previous passes of the compiler validated this subsystem, + // so we just blindly pass it to the linker. + self.cmd.arg(&format!("/SUBSYSTEM:{}", subsystem)); + + // Windows has two subsystems we're interested in right now, the console + // and windows subsystems. These both implicitly have different entry + // points (starting symbols). The console entry point starts with + // `mainCRTStartup` and the windows entry point starts with + // `WinMainCRTStartup`. These entry points, defined in system libraries, + // will then later probe for either `main` or `WinMain`, respectively to + // start the application. + // + // In Rust we just always generate a `main` function so we want control + // to always start there, so we force the entry point on the windows + // subsystem to be `mainCRTStartup` to get everything booted up + // correctly. + // + // For more information see RFC #1665 + if subsystem == "windows" { + self.cmd.arg("/ENTRY:mainCRTStartup"); + } + } } fn exported_symbols(scx: &SharedCrateContext, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 977ababbf5688..d30183a13f1f8 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1611,7 +1611,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: vec![], no_builtins: no_builtins, - linker_info: linker_info + linker_info: linker_info, + windows_subsystem: None, }; } @@ -1747,6 +1748,17 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); + let subsystem = attr::first_attr_value_str_by_name(&krate.attrs, + "windows_subsystem"); + let windows_subsystem = subsystem.map(|subsystem| { + if subsystem != "windows" && subsystem != "console" { + tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \ + `windows` and `console` are allowed", + subsystem)); + } + subsystem.to_string() + }); + CrateTranslation { modules: modules, metadata_module: metadata_module, @@ -1754,7 +1766,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: reachable_symbols, no_builtins: no_builtins, - linker_info: linker_info + linker_info: linker_info, + windows_subsystem: windows_subsystem, } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 07acc54962b87..37304f28e03f6 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -169,6 +169,7 @@ pub struct CrateTranslation { pub metadata: Vec, pub reachable: Vec, pub no_builtins: bool, + pub windows_subsystem: Option, pub linker_info: back::linker::LinkerInfo } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 129e4a8233803..bf6482e5b99d5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -309,6 +309,9 @@ declare_features! ( // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (active, field_init_shorthand, "1.14.0", Some(37340)), + + // The #![windows_subsystem] attribute + (active, windows_subsystem, "1.14.0", Some(37499)), ); declare_features! ( @@ -713,6 +716,12 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat "defining reflective traits is still evolving", cfg_fn!(reflect))), + ("windows_subsystem", Whitelisted, Gated(Stability::Unstable, + "windows_subsystem", + "the windows subsystem attribute \ + id currently unstable", + cfg_fn!(windows_subsystem))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), diff --git a/src/test/compile-fail/windows-subsystem-gated.rs b/src/test/compile-fail/windows-subsystem-gated.rs new file mode 100644 index 0000000000000..4b563e78e55c8 --- /dev/null +++ b/src/test/compile-fail/windows-subsystem-gated.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![windows_subsystem = "console"] +//~^ ERROR: the windows subsystem attribute is currently unstable + +fn main() {} diff --git a/src/test/compile-fail/windows-subsystem-invalid.rs b/src/test/compile-fail/windows-subsystem-invalid.rs new file mode 100644 index 0000000000000..28c3950e76f20 --- /dev/null +++ b/src/test/compile-fail/windows-subsystem-invalid.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "wrong"] +//~^ ERROR: invalid subsystem `wrong`, only `windows` and `console` are allowed + +fn main() {} diff --git a/src/test/run-make/windows-subsystem/Makefile b/src/test/run-make/windows-subsystem/Makefile new file mode 100644 index 0000000000000..34fb5db32f95a --- /dev/null +++ b/src/test/run-make/windows-subsystem/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) windows.rs + $(RUSTC) console.rs diff --git a/src/test/run-make/windows-subsystem/console.rs b/src/test/run-make/windows-subsystem/console.rs new file mode 100644 index 0000000000000..3aedb0ecab722 --- /dev/null +++ b/src/test/run-make/windows-subsystem/console.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "console"] + +fn main() {} + diff --git a/src/test/run-make/windows-subsystem/windows.rs b/src/test/run-make/windows-subsystem/windows.rs new file mode 100644 index 0000000000000..5d875a5a1bf1f --- /dev/null +++ b/src/test/run-make/windows-subsystem/windows.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "windows"] + +fn main() {} From 9253e1206e91f5bd7fafd18f8488a937b0046959 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Tue, 25 Oct 2016 23:32:04 +0200 Subject: [PATCH 04/41] adapt debuginfo tests for gdb with native rust support --- src/test/debuginfo/associated-types.rs | 6 +- .../debuginfo/basic-types-globals-metadata.rs | 42 ++++-- src/test/debuginfo/basic-types-globals.rs | 45 ++++-- src/test/debuginfo/basic-types-metadata.rs | 31 ++-- src/test/debuginfo/basic-types-mut-globals.rs | 90 ++++++++---- src/test/debuginfo/basic-types.rs | 3 +- src/test/debuginfo/borrowed-basic.rs | 9 +- src/test/debuginfo/borrowed-c-style-enum.rs | 9 +- src/test/debuginfo/borrowed-enum.rs | 9 +- src/test/debuginfo/borrowed-struct.rs | 9 +- src/test/debuginfo/borrowed-tuple.rs | 9 +- src/test/debuginfo/borrowed-unique-basic.rs | 3 +- src/test/debuginfo/box.rs | 3 +- src/test/debuginfo/boxed-struct.rs | 6 +- .../by-value-non-immediate-argument.rs | 15 +- .../by-value-self-argument-in-trait-impl.rs | 6 +- .../debuginfo/c-style-enum-in-composite.rs | 22 ++- src/test/debuginfo/c-style-enum.rs | 74 ++++++---- src/test/debuginfo/cross-crate-spans.rs | 6 +- .../debuginfo/destructured-fn-argument.rs | 24 ++- .../destructured-for-loop-variable.rs | 6 +- src/test/debuginfo/destructured-local.rs | 24 ++- src/test/debuginfo/evec-in-struct.rs | 15 +- src/test/debuginfo/extern-c-fn.rs | 3 +- .../debuginfo/function-arg-initialization.rs | 8 +- ...gdb-pretty-struct-and-enums-pre-gdb-7-7.rs | 9 +- .../generic-enum-with-different-disr-sizes.rs | 31 +++- src/test/debuginfo/generic-function.rs | 14 +- .../generic-method-on-generic-struct.rs | 15 +- .../debuginfo/generic-struct-style-enum.rs | 12 +- src/test/debuginfo/generic-struct.rs | 12 +- .../debuginfo/generic-tuple-style-enum.rs | 12 +- .../lexical-scopes-in-block-expression.rs | 27 ++-- src/test/debuginfo/method-on-enum.rs | 15 +- .../debuginfo/method-on-generic-struct.rs | 15 +- src/test/debuginfo/method-on-struct.rs | 15 +- src/test/debuginfo/method-on-trait.rs | 15 +- src/test/debuginfo/method-on-tuple-struct.rs | 15 +- src/test/debuginfo/nil-enum.rs | 9 +- src/test/debuginfo/option-like-enum.rs | 24 ++- .../packed-struct-with-destructor.rs | 24 ++- src/test/debuginfo/packed-struct.rs | 12 +- src/test/debuginfo/pretty-std.rs | 3 +- src/test/debuginfo/recursive-struct.rs | 43 ++++-- src/test/debuginfo/self-in-default-method.rs | 15 +- .../self-in-generic-default-method.rs | 15 +- src/test/debuginfo/simd.rs | 56 ++++--- src/test/debuginfo/simple-struct.rs | 115 +++++++++------ src/test/debuginfo/simple-tuple.rs | 121 +++++++++------ src/test/debuginfo/struct-in-enum.rs | 9 +- src/test/debuginfo/struct-in-struct.rs | 9 +- src/test/debuginfo/struct-style-enum.rs | 12 +- src/test/debuginfo/struct-with-destructor.rs | 14 +- src/test/debuginfo/tuple-in-struct.rs | 30 ++-- src/test/debuginfo/tuple-in-tuple.rs | 21 ++- src/test/debuginfo/tuple-struct.rs | 18 ++- src/test/debuginfo/tuple-style-enum.rs | 12 +- src/test/debuginfo/type-names.rs | 138 ++++++++++++------ src/test/debuginfo/union-smoke.rs | 6 +- src/test/debuginfo/unique-enum.rs | 9 +- .../var-captured-in-nested-closure.rs | 12 +- .../var-captured-in-sendable-closure.rs | 3 +- .../var-captured-in-stack-closure.rs | 12 +- src/test/debuginfo/vec-slices.rs | 45 ++++-- src/test/debuginfo/vec.rs | 6 +- 65 files changed, 983 insertions(+), 494 deletions(-) diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs index ebaad663bb4e7..ccd94022711cd 100644 --- a/src/test/debuginfo/associated-types.rs +++ b/src/test/debuginfo/associated-types.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print arg -// gdb-check:$1 = {b = -1, b1 = 0} +// gdbg-check:$1 = {b = -1, b1 = 0} +// gdbr-check:$1 = associated_types::Struct {b: -1, b1: 0} // gdb-command:continue // gdb-command:print inferred @@ -30,7 +31,8 @@ // gdb-command:continue // gdb-command:print arg -// gdb-check:$5 = {__0 = 4, __1 = 5} +// gdbg-check:$5 = {__0 = 4, __1 = 5} +// gdbr-check:$5 = (4, 5) // gdb-command:continue // gdb-command:print a diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs index 8818063ddf4ba..fe687dabe9acb 100644 --- a/src/test/debuginfo/basic-types-globals-metadata.rs +++ b/src/test/debuginfo/basic-types-globals-metadata.rs @@ -12,33 +12,47 @@ // compile-flags:-g // gdb-command:run -// gdb-command:whatis 'basic_types_globals_metadata::B' +// gdbg-command:whatis 'basic_types_globals_metadata::B' +// gdbr-command:whatis basic_types_globals_metadata::B // gdb-check:type = bool -// gdb-command:whatis 'basic_types_globals_metadata::I' +// gdbg-command:whatis 'basic_types_globals_metadata::I' +// gdbr-command:whatis basic_types_globals_metadata::I // gdb-check:type = isize -// gdb-command:whatis 'basic_types_globals_metadata::C' +// gdbg-command:whatis 'basic_types_globals_metadata::C' +// gdbr-command:whatis basic_types_globals_metadata::C // gdb-check:type = char -// gdb-command:whatis 'basic_types_globals_metadata::I8' +// gdbg-command:whatis 'basic_types_globals_metadata::I8' +// gdbr-command:whatis basic_types_globals_metadata::I8 // gdb-check:type = i8 -// gdb-command:whatis 'basic_types_globals_metadata::I16' +// gdbg-command:whatis 'basic_types_globals_metadata::I16' +// gdbr-command:whatis basic_types_globals_metadata::I16 // gdb-check:type = i16 -// gdb-command:whatis 'basic_types_globals_metadata::I32' +// gdbg-command:whatis 'basic_types_globals_metadata::I32' +// gdbr-command:whatis basic_types_globals_metadata::I32 // gdb-check:type = i32 -// gdb-command:whatis 'basic_types_globals_metadata::I64' +// gdbg-command:whatis 'basic_types_globals_metadata::I64' +// gdbr-command:whatis basic_types_globals_metadata::I64 // gdb-check:type = i64 -// gdb-command:whatis 'basic_types_globals_metadata::U' +// gdbg-command:whatis 'basic_types_globals_metadata::U' +// gdbr-command:whatis basic_types_globals_metadata::U // gdb-check:type = usize -// gdb-command:whatis 'basic_types_globals_metadata::U8' +// gdbg-command:whatis 'basic_types_globals_metadata::U8' +// gdbr-command:whatis basic_types_globals_metadata::U8 // gdb-check:type = u8 -// gdb-command:whatis 'basic_types_globals_metadata::U16' +// gdbg-command:whatis 'basic_types_globals_metadata::U16' +// gdbr-command:whatis basic_types_globals_metadata::U16 // gdb-check:type = u16 -// gdb-command:whatis 'basic_types_globals_metadata::U32' +// gdbg-command:whatis 'basic_types_globals_metadata::U32' +// gdbr-command:whatis basic_types_globals_metadata::U32 // gdb-check:type = u32 -// gdb-command:whatis 'basic_types_globals_metadata::U64' +// gdbg-command:whatis 'basic_types_globals_metadata::U64' +// gdbr-command:whatis basic_types_globals_metadata::U64 // gdb-check:type = u64 -// gdb-command:whatis 'basic_types_globals_metadata::F32' +// gdbg-command:whatis 'basic_types_globals_metadata::F32' +// gdbr-command:whatis basic_types_globals_metadata::F32 // gdb-check:type = f32 -// gdb-command:whatis 'basic_types_globals_metadata::F64' +// gdbg-command:whatis 'basic_types_globals_metadata::F64' +// gdbr-command:whatis basic_types_globals_metadata::F64 // gdb-check:type = f64 // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs index ccf9508a3856c..20bc403fbbcdc 100644 --- a/src/test/debuginfo/basic-types-globals.rs +++ b/src/test/debuginfo/basic-types-globals.rs @@ -18,33 +18,48 @@ // compile-flags:-g // gdb-command:run -// gdb-command:print 'basic_types_globals::B' +// gdbg-command:print 'basic_types_globals::B' +// gdbr-command:print B // gdb-check:$1 = false -// gdb-command:print 'basic_types_globals::I' +// gdbg-command:print 'basic_types_globals::I' +// gdbr-command:print I // gdb-check:$2 = -1 -// gdb-command:print 'basic_types_globals::C' -// gdb-check:$3 = 97 -// gdb-command:print/d 'basic_types_globals::I8' +// gdbg-command:print 'basic_types_globals::C' +// gdbr-command:print C +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' +// gdbg-command:print/d 'basic_types_globals::I8' +// gdbr-command:print I8 // gdb-check:$4 = 68 -// gdb-command:print 'basic_types_globals::I16' +// gdbg-command:print 'basic_types_globals::I16' +// gdbr-command:print I16 // gdb-check:$5 = -16 -// gdb-command:print 'basic_types_globals::I32' +// gdbg-command:print 'basic_types_globals::I32' +// gdbr-command:print I32 // gdb-check:$6 = -32 -// gdb-command:print 'basic_types_globals::I64' +// gdbg-command:print 'basic_types_globals::I64' +// gdbr-command:print I64 // gdb-check:$7 = -64 -// gdb-command:print 'basic_types_globals::U' +// gdbg-command:print 'basic_types_globals::U' +// gdbr-command:print U // gdb-check:$8 = 1 -// gdb-command:print/d 'basic_types_globals::U8' +// gdbg-command:print/d 'basic_types_globals::U8' +// gdbr-command:print U8 // gdb-check:$9 = 100 -// gdb-command:print 'basic_types_globals::U16' +// gdbg-command:print 'basic_types_globals::U16' +// gdbr-command:print U16 // gdb-check:$10 = 16 -// gdb-command:print 'basic_types_globals::U32' +// gdbg-command:print 'basic_types_globals::U32' +// gdbr-command:print U32 // gdb-check:$11 = 32 -// gdb-command:print 'basic_types_globals::U64' +// gdbg-command:print 'basic_types_globals::U64' +// gdbr-command:print U64 // gdb-check:$12 = 64 -// gdb-command:print 'basic_types_globals::F32' +// gdbg-command:print 'basic_types_globals::F32' +// gdbr-command:print F32 // gdb-check:$13 = 2.5 -// gdb-command:print 'basic_types_globals::F64' +// gdbg-command:print 'basic_types_globals::F64' +// gdbr-command:print F64 // gdb-check:$14 = 3.5 // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-metadata.rs b/src/test/debuginfo/basic-types-metadata.rs index 1a6b605d9d06a..8aec1a059bdc6 100644 --- a/src/test/debuginfo/basic-types-metadata.rs +++ b/src/test/debuginfo/basic-types-metadata.rs @@ -45,20 +45,29 @@ // gdb-command:whatis fnptr // gdb-check:type = [...] (*)([...]) // gdb-command:info functions _yyy -// gdb-check:[...]![...]_yyy([...]); +// gdbg-check:[...]![...]_yyy([...]); +// gdbr-check:static fn basic_types_metadata::_yyy() -> !; // gdb-command:ptype closure_0 -// gdb-check: type = struct closure { -// gdb-check: -// gdb-check: } +// gdbr-check: type = struct closure +// gdbg-check: type = struct closure { +// gdbg-check: +// gdbg-check: } // gdb-command:ptype closure_1 -// gdb-check: type = struct closure { -// gdb-check: bool *__0; -// gdb-check: } +// gdbg-check: type = struct closure { +// gdbg-check: bool *__0; +// gdbg-check: } +// gdbr-check: type = struct closure ( +// gdbr-check: bool *, +// gdbr-check: ) // gdb-command:ptype closure_2 -// gdb-check: type = struct closure { -// gdb-check: bool *__0; -// gdb-check: isize *__1; -// gdb-check: } +// gdbg-check: type = struct closure { +// gdbg-check: bool *__0; +// gdbg-check: isize *__1; +// gdbg-check: } +// gdbr-check: type = struct closure ( +// gdbr-check: bool *, +// gdbr-check: isize *, +// gdbr-check: ) // // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-mut-globals.rs b/src/test/debuginfo/basic-types-mut-globals.rs index 4ebd0c9577029..62325aa53ab9f 100644 --- a/src/test/debuginfo/basic-types-mut-globals.rs +++ b/src/test/debuginfo/basic-types-mut-globals.rs @@ -21,64 +21,94 @@ // gdb-command:run // Check initializers -// gdb-command:print 'basic_types_mut_globals::B' +// gdbg-command:print 'basic_types_mut_globals::B' +// gdbr-command:print B // gdb-check:$1 = false -// gdb-command:print 'basic_types_mut_globals::I' +// gdbg-command:print 'basic_types_mut_globals::I' +// gdbr-command:print I // gdb-check:$2 = -1 -// gdb-command:print 'basic_types_mut_globals::C' -// gdb-check:$3 = 97 -// gdb-command:print/d 'basic_types_mut_globals::I8' +// gdbg-command:print/d 'basic_types_mut_globals::C' +// gdbr-command:print C +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' +// gdbg-command:print/d 'basic_types_mut_globals::I8' +// gdbr-command:print I8 // gdb-check:$4 = 68 -// gdb-command:print 'basic_types_mut_globals::I16' +// gdbg-command:print 'basic_types_mut_globals::I16' +// gdbr-command:print I16 // gdb-check:$5 = -16 -// gdb-command:print 'basic_types_mut_globals::I32' +// gdbg-command:print 'basic_types_mut_globals::I32' +// gdbr-command:print I32 // gdb-check:$6 = -32 -// gdb-command:print 'basic_types_mut_globals::I64' +// gdbg-command:print 'basic_types_mut_globals::I64' +// gdbr-command:print I64 // gdb-check:$7 = -64 -// gdb-command:print 'basic_types_mut_globals::U' +// gdbg-command:print 'basic_types_mut_globals::U' +// gdbr-command:print U // gdb-check:$8 = 1 -// gdb-command:print/d 'basic_types_mut_globals::U8' +// gdbg-command:print/d 'basic_types_mut_globals::U8' +// gdbr-command:print U8 // gdb-check:$9 = 100 -// gdb-command:print 'basic_types_mut_globals::U16' +// gdbg-command:print 'basic_types_mut_globals::U16' +// gdbr-command:print U16 // gdb-check:$10 = 16 -// gdb-command:print 'basic_types_mut_globals::U32' +// gdbg-command:print 'basic_types_mut_globals::U32' +// gdbr-command:print U32 // gdb-check:$11 = 32 -// gdb-command:print 'basic_types_mut_globals::U64' +// gdbg-command:print 'basic_types_mut_globals::U64' +// gdbr-command:print U64 // gdb-check:$12 = 64 -// gdb-command:print 'basic_types_mut_globals::F32' +// gdbg-command:print 'basic_types_mut_globals::F32' +// gdbr-command:print F32 // gdb-check:$13 = 2.5 -// gdb-command:print 'basic_types_mut_globals::F64' +// gdbg-command:print 'basic_types_mut_globals::F64' +// gdbr-command:print F64 // gdb-check:$14 = 3.5 // gdb-command:continue // Check new values -// gdb-command:print 'basic_types_mut_globals'::B +// gdbg-command:print 'basic_types_mut_globals'::B +// gdbr-command:print B // gdb-check:$15 = true -// gdb-command:print 'basic_types_mut_globals'::I +// gdbg-command:print 'basic_types_mut_globals'::I +// gdbr-command:print I // gdb-check:$16 = 2 -// gdb-command:print 'basic_types_mut_globals'::C -// gdb-check:$17 = 102 -// gdb-command:print/d 'basic_types_mut_globals'::I8 +// gdbg-command:print/d 'basic_types_mut_globals'::C +// gdbr-command:print C +// gdbg-check:$17 = 102 +// gdbr-check:$17 = 102 'f' +// gdbg-command:print/d 'basic_types_mut_globals'::I8 +// gdbr-command:print/d I8 // gdb-check:$18 = 78 -// gdb-command:print 'basic_types_mut_globals'::I16 +// gdbg-command:print 'basic_types_mut_globals'::I16 +// gdbr-command:print I16 // gdb-check:$19 = -26 -// gdb-command:print 'basic_types_mut_globals'::I32 +// gdbg-command:print 'basic_types_mut_globals'::I32 +// gdbr-command:print I32 // gdb-check:$20 = -12 -// gdb-command:print 'basic_types_mut_globals'::I64 +// gdbg-command:print 'basic_types_mut_globals'::I64 +// gdbr-command:print I64 // gdb-check:$21 = -54 -// gdb-command:print 'basic_types_mut_globals'::U +// gdbg-command:print 'basic_types_mut_globals'::U +// gdbr-command:print U // gdb-check:$22 = 5 -// gdb-command:print/d 'basic_types_mut_globals'::U8 +// gdbg-command:print/d 'basic_types_mut_globals'::U8 +// gdbr-command:print/d U8 // gdb-check:$23 = 20 -// gdb-command:print 'basic_types_mut_globals'::U16 +// gdbg-command:print 'basic_types_mut_globals'::U16 +// gdbr-command:print U16 // gdb-check:$24 = 32 -// gdb-command:print 'basic_types_mut_globals'::U32 +// gdbg-command:print 'basic_types_mut_globals'::U32 +// gdbr-command:print U32 // gdb-check:$25 = 16 -// gdb-command:print 'basic_types_mut_globals'::U64 +// gdbg-command:print 'basic_types_mut_globals'::U64 +// gdbr-command:print U64 // gdb-check:$26 = 128 -// gdb-command:print 'basic_types_mut_globals'::F32 +// gdbg-command:print 'basic_types_mut_globals'::F32 +// gdbr-command:print F32 // gdb-check:$27 = 5.75 -// gdb-command:print 'basic_types_mut_globals'::F64 +// gdbg-command:print 'basic_types_mut_globals'::F64 +// gdbr-command:print F64 // gdb-check:$28 = 9.25 #![allow(unused_variables)] diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 998010832881b..01ce5bd31626e 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -26,7 +26,8 @@ // gdb-command:print i // gdb-check:$2 = -1 // gdb-command:print c -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print/d i8 // gdb-check:$4 = 68 // gdb-command:print i16 diff --git a/src/test/debuginfo/borrowed-basic.rs b/src/test/debuginfo/borrowed-basic.rs index bada77b66293c..f6c0ff09efe93 100644 --- a/src/test/debuginfo/borrowed-basic.rs +++ b/src/test/debuginfo/borrowed-basic.rs @@ -25,10 +25,12 @@ // gdb-check:$2 = -1 // gdb-command:print *char_ref -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print *i8_ref -// gdb-check:$4 = 68 'D' +// gdbg-check:$4 = 68 'D' +// gdbr-check:$4 = 68 // gdb-command:print *i16_ref // gdb-check:$5 = -16 @@ -43,7 +45,8 @@ // gdb-check:$8 = 1 // gdb-command:print *u8_ref -// gdb-check:$9 = 100 'd' +// gdbg-check:$9 = 100 'd' +// gdbr-check:$9 = 100 // gdb-command:print *u16_ref // gdb-check:$10 = 16 diff --git a/src/test/debuginfo/borrowed-c-style-enum.rs b/src/test/debuginfo/borrowed-c-style-enum.rs index c80783ef31068..d6f379634be5b 100644 --- a/src/test/debuginfo/borrowed-c-style-enum.rs +++ b/src/test/debuginfo/borrowed-c-style-enum.rs @@ -17,13 +17,16 @@ // gdb-command:run // gdb-command:print *the_a_ref -// gdb-check:$1 = TheA +// gdbg-check:$1 = TheA +// gdbr-check:$1 = borrowed_c_style_enum::ABC::TheA // gdb-command:print *the_b_ref -// gdb-check:$2 = TheB +// gdbg-check:$2 = TheB +// gdbr-check:$2 = borrowed_c_style_enum::ABC::TheB // gdb-command:print *the_c_ref -// gdb-check:$3 = TheC +// gdbg-check:$3 = TheC +// gdbr-check:$3 = borrowed_c_style_enum::ABC::TheC // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index b21574e32866b..ddc29c6430270 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print *the_a_ref -// gdb-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$1 = borrowed_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b_ref -// gdb-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbr-check:$2 = borrowed_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant_ref -// gdb-check:$3 = {{__0 = 4820353753753434}} +// gdbg-check:$3 = {{__0 = 4820353753753434}} +// gdbr-check:$3 = borrowed_enum::Univariant::TheOnlyCase(4820353753753434) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs index ab41185cb7391..01428e515e27f 100644 --- a/src/test/debuginfo/borrowed-struct.rs +++ b/src/test/debuginfo/borrowed-struct.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print *stack_val_ref -// gdb-check:$1 = {x = 10, y = 23.5} +// gdbg-check:$1 = {x = 10, y = 23.5} +// gdbr-check:$1 = borrowed_struct::SomeStruct {x: 10, y: 23.5} // gdb-command:print *stack_val_interior_ref_1 // gdb-check:$2 = 10 @@ -25,10 +26,12 @@ // gdb-check:$3 = 23.5 // gdb-command:print *ref_to_unnamed -// gdb-check:$4 = {x = 11, y = 24.5} +// gdbg-check:$4 = {x = 11, y = 24.5} +// gdbr-check:$4 = borrowed_struct::SomeStruct {x: 11, y: 24.5} // gdb-command:print *unique_val_ref -// gdb-check:$5 = {x = 13, y = 26.5} +// gdbg-check:$5 = {x = 13, y = 26.5} +// gdbr-check:$5 = borrowed_struct::SomeStruct {x: 13, y: 26.5} // gdb-command:print *unique_val_interior_ref_1 // gdb-check:$6 = 13 diff --git a/src/test/debuginfo/borrowed-tuple.rs b/src/test/debuginfo/borrowed-tuple.rs index e3da3934f6d69..17db88ee37f53 100644 --- a/src/test/debuginfo/borrowed-tuple.rs +++ b/src/test/debuginfo/borrowed-tuple.rs @@ -17,13 +17,16 @@ // gdb-command:run // gdb-command:print *stack_val_ref -// gdb-check:$1 = {__0 = -14, __1 = -19} +// gdbg-check:$1 = {__0 = -14, __1 = -19} +// gdbr-check:$1 = (-14, -19) // gdb-command:print *ref_to_unnamed -// gdb-check:$2 = {__0 = -15, __1 = -20} +// gdbg-check:$2 = {__0 = -15, __1 = -20} +// gdbr-check:$2 = (-15, -20) // gdb-command:print *unique_val_ref -// gdb-check:$3 = {__0 = -17, __1 = -22} +// gdbg-check:$3 = {__0 = -17, __1 = -22} +// gdbr-check:$3 = (-17, -22) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-unique-basic.rs b/src/test/debuginfo/borrowed-unique-basic.rs index 88af94c53628c..9e95498b0c30e 100644 --- a/src/test/debuginfo/borrowed-unique-basic.rs +++ b/src/test/debuginfo/borrowed-unique-basic.rs @@ -26,7 +26,8 @@ // gdb-check:$2 = -1 // gdb-command:print *char_ref -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print/d *i8_ref // gdb-check:$4 = 68 diff --git a/src/test/debuginfo/box.rs b/src/test/debuginfo/box.rs index 106d0b243eb26..98c09fe09de8f 100644 --- a/src/test/debuginfo/box.rs +++ b/src/test/debuginfo/box.rs @@ -19,7 +19,8 @@ // gdb-command:print *a // gdb-check:$1 = 1 // gdb-command:print *b -// gdb-check:$2 = {__0 = 2, __1 = 3.5} +// gdbg-check:$2 = {__0 = 2, __1 = 3.5} +// gdbr-check:$2 = (2, 3.5) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index dd543405e4c27..ac091b4a533db 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -17,10 +17,12 @@ // gdb-command:run // gdb-command:print *unique -// gdb-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} +// gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} +// gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999} // gdb-command:print *unique_dtor -// gdb-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} +// gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} +// gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs index a329ef6d0e090..6d821dbc155d0 100644 --- a/src/test/debuginfo/by-value-non-immediate-argument.rs +++ b/src/test/debuginfo/by-value-non-immediate-argument.rs @@ -18,11 +18,13 @@ // gdb-command:run // gdb-command:print s -// gdb-check:$1 = {a = 1, b = 2.5} +// gdbg-check:$1 = {a = 1, b = 2.5} +// gdbr-check:$1 = by_value_non_immediate_argument::Struct {a: 1, b: 2.5} // gdb-command:continue // gdb-command:print x -// gdb-check:$2 = {a = 3, b = 4.5} +// gdbg-check:$2 = {a = 3, b = 4.5} +// gdbr-check:$2 = by_value_non_immediate_argument::Struct {a: 3, b: 4.5} // gdb-command:print y // gdb-check:$3 = 5 // gdb-command:print z @@ -30,15 +32,18 @@ // gdb-command:continue // gdb-command:print a -// gdb-check:$5 = {__0 = 7, __1 = 8, __2 = 9.5, __3 = 10.5} +// gdbg-check:$5 = {__0 = 7, __1 = 8, __2 = 9.5, __3 = 10.5} +// gdbr-check:$5 = (7, 8, 9.5, 10.5) // gdb-command:continue // gdb-command:print a -// gdb-check:$6 = {__0 = 11.5, __1 = 12.5, __2 = 13, __3 = 14} +// gdbg-check:$6 = {__0 = 11.5, __1 = 12.5, __2 = 13, __3 = 14} +// gdbr-check:$6 = by_value_non_immediate_argument::Newtype (11.5, 12.5, 13, 14) // gdb-command:continue // gdb-command:print x -// gdb-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$7 = by_value_non_immediate_argument::Enum::Case1{x: 0, y: 8970181431921507452} // gdb-command:continue diff --git a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs index a768bfdd16764..c14f8c7b354fc 100644 --- a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs +++ b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs @@ -21,11 +21,13 @@ // gdb-command:continue // gdb-command:print self -// gdb-check:$2 = {x = 2222, y = 3333} +// gdbg-check:$2 = {x = 2222, y = 3333} +// gdbr-check:$2 = by_value_self_argument_in_trait_impl::Struct {x: 2222, y: 3333} // gdb-command:continue // gdb-command:print self -// gdb-check:$3 = {__0 = 4444.5, __1 = 5555, __2 = 6666, __3 = 7777.5} +// gdbg-check:$3 = {__0 = 4444.5, __1 = 5555, __2 = 6666, __3 = 7777.5} +// gdbr-check:$3 = (4444.5, 5555, 6666, 7777.5) // gdb-command:continue diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs index 83a22edc96fe1..004e15d1cc6c1 100644 --- a/src/test/debuginfo/c-style-enum-in-composite.rs +++ b/src/test/debuginfo/c-style-enum-in-composite.rs @@ -18,26 +18,32 @@ // gdb-command:run // gdb-command:print tuple_interior_padding -// gdb-check:$1 = {__0 = 0, __1 = OneHundred} +// gdbg-check:$1 = {__0 = 0, __1 = OneHundred} +// gdbr-check:$1 = (0, c_style_enum_in_composite::AnEnum::OneHundred) // gdb-command:print tuple_padding_at_end -// gdb-check:$2 = {__0 = {__0 = 1, __1 = OneThousand}, __1 = 2} +// gdbg-check:$2 = {__0 = {__0 = 1, __1 = OneThousand}, __1 = 2} +// gdbr-check:$2 = ((1, c_style_enum_in_composite::AnEnum::OneThousand), 2) // gdb-command:print tuple_different_enums -// gdb-check:$3 = {__0 = OneThousand, __1 = MountainView, __2 = OneMillion, __3 = Vienna} +// gdbg-check:$3 = {__0 = OneThousand, __1 = MountainView, __2 = OneMillion, __3 = Vienna} +// gdbr-check:$3 = (c_style_enum_in_composite::AnEnum::OneThousand, c_style_enum_in_composite::AnotherEnum::MountainView, c_style_enum_in_composite::AnEnum::OneMillion, c_style_enum_in_composite::AnotherEnum::Vienna) // gdb-command:print padded_struct -// gdb-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} +// gdbg-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} +// gdbr-check:$4 = c_style_enum_in_composite::PaddedStruct {a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5} // gdb-command:print packed_struct -// gdb-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} +// gdbg-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} +// gdbr-check:$5 = c_style_enum_in_composite::PackedStruct {a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8} // gdb-command:print non_padded_struct -// gdb-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} +// gdbg-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} +// gdbr-check:$6 = c_style_enum_in_composite::NonPaddedStruct {a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto} // gdb-command:print struct_with_drop -// gdb-check:$7 = {__0 = {a = OneHundred, b = Vienna}, __1 = 9} - +// gdbg-check:$7 = {__0 = {a = OneHundred, b = Vienna}, __1 = 9} +// gdbr-check:$7 = (c_style_enum_in_composite::StructWithDrop {a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna}, 9) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index dbd336d2dc688..2452c18f54347 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -16,60 +16,82 @@ // === GDB TESTS =================================================================================== // gdb-command:print 'c_style_enum::SINGLE_VARIANT' -// gdb-check:$1 = TheOnlyVariant +// gdbg-check:$1 = TheOnlyVariant +// gdbr-check:$1 = c_style_enum::SingleVariant::TheOnlyVariant // gdb-command:print 'c_style_enum::AUTO_ONE' -// gdb-check:$2 = One +// gdbg-check:$2 = One +// gdbr-check:$2 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::AUTO_TWO' -// gdb-check:$3 = One +// gdbg-check:$3 = One +// gdbr-check:$3 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::AUTO_THREE' -// gdb-check:$4 = One +// gdbg-check:$4 = One +// gdbr-check:$4 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::MANUAL_ONE' -// gdb-check:$5 = OneHundred +// gdbg-check:$5 = OneHundred +// gdbr-check:$5 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print 'c_style_enum::MANUAL_TWO' -// gdb-check:$6 = OneHundred +// gdbg-check:$6 = OneHundred +// gdbr-check:$6 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print 'c_style_enum::MANUAL_THREE' -// gdb-check:$7 = OneHundred +// gdbg-check:$7 = OneHundred +// gdbr-check:$7 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:run // gdb-command:print auto_one -// gdb-check:$8 = One +// gdbg-check:$8 = One +// gdbr-check:$8 = c_style_enum::AutoDiscriminant::One // gdb-command:print auto_two -// gdb-check:$9 = Two +// gdbg-check:$9 = Two +// gdbr-check:$9 = c_style_enum::AutoDiscriminant::Two // gdb-command:print auto_three -// gdb-check:$10 = Three +// gdbg-check:$10 = Three +// gdbr-check:$10 = c_style_enum::AutoDiscriminant::Three // gdb-command:print manual_one_hundred -// gdb-check:$11 = OneHundred +// gdbg-check:$11 = OneHundred +// gdbr-check:$11 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print manual_one_thousand -// gdb-check:$12 = OneThousand +// gdbg-check:$12 = OneThousand +// gdbr-check:$12 = c_style_enum::ManualDiscriminant::OneThousand // gdb-command:print manual_one_million -// gdb-check:$13 = OneMillion +// gdbg-check:$13 = OneMillion +// gdbr-check:$13 = c_style_enum::ManualDiscriminant::OneMillion // gdb-command:print single_variant -// gdb-check:$14 = TheOnlyVariant - -// gdb-command:print 'c_style_enum::AUTO_TWO' -// gdb-check:$15 = Two - -// gdb-command:print 'c_style_enum::AUTO_THREE' -// gdb-check:$16 = Three - -// gdb-command:print 'c_style_enum::MANUAL_TWO' -// gdb-check:$17 = OneThousand - -// gdb-command:print 'c_style_enum::MANUAL_THREE' -// gdb-check:$18 = OneMillion +// gdbg-check:$14 = TheOnlyVariant +// gdbr-check:$14 = c_style_enum::SingleVariant::TheOnlyVariant + +// gdbg-command:print 'c_style_enum::AUTO_TWO' +// gdbr-command:print AUTO_TWO +// gdbg-check:$15 = Two +// gdbr-check:$15 = c_style_enum::AutoDiscriminant::Two + +// gdbg-command:print 'c_style_enum::AUTO_THREE' +// gdbr-command:print AUTO_THREE +// gdbg-check:$16 = Three +// gdbr-check:$16 = c_style_enum::AutoDiscriminant::Three + +// gdbg-command:print 'c_style_enum::MANUAL_TWO' +// gdbr-command:print MANUAL_TWO +// gdbg-check:$17 = OneThousand +// gdbr-check:$17 = c_style_enum::ManualDiscriminant::OneThousand + +// gdbg-command:print 'c_style_enum::MANUAL_THREE' +// gdbr-command:print MANUAL_THREE +// gdbg-check:$18 = OneMillion +// gdbr-check:$18 = c_style_enum::ManualDiscriminant::OneMillion // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/cross-crate-spans.rs b/src/test/debuginfo/cross-crate-spans.rs index 544fe2c66d5e8..28728df928051 100644 --- a/src/test/debuginfo/cross-crate-spans.rs +++ b/src/test/debuginfo/cross-crate-spans.rs @@ -25,7 +25,8 @@ extern crate cross_crate_spans; // gdb-command:run // gdb-command:print result -// gdb-check:$1 = {__0 = 17, __1 = 17} +// gdbg-check:$1 = {__0 = 17, __1 = 17} +// gdbr-check:$1 = (17, 17) // gdb-command:print a_variable // gdb-check:$2 = 123456789 // gdb-command:print another_variable @@ -33,7 +34,8 @@ extern crate cross_crate_spans; // gdb-command:continue // gdb-command:print result -// gdb-check:$4 = {__0 = 1212, __1 = 1212} +// gdbg-check:$4 = {__0 = 1212, __1 = 1212} +// gdbr-check:$4 = (1212, 1212) // gdb-command:print a_variable // gdb-check:$5 = 123456789 // gdb-command:print another_variable diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs index 954a7abe6323c..efa9ee59b22b2 100644 --- a/src/test/debuginfo/destructured-fn-argument.rs +++ b/src/test/debuginfo/destructured-fn-argument.rs @@ -33,13 +33,15 @@ // gdb-command:print a // gdb-check:$6 = 5 // gdb-command:print b -// gdb-check:$7 = {__0 = 6, __1 = 7} +// gdbg-check:$7 = {__0 = 6, __1 = 7} +// gdbr-check:$7 = (6, 7) // gdb-command:continue // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdb-check:$9 = {a = 9, b = 10} +// gdbg-check:$9 = {a = 9, b = 10} +// gdbr-check:$9 = destructured_fn_argument::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 // gdb-command:continue @@ -65,7 +67,8 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdb-check:$18 = {a = 21, b = 22} +// gdbg-check:$18 = {a = 21, b = 22} +// gdbr-check:$18 = destructured_fn_argument::Struct {a: 21, b: 22} // gdb-command:continue // gdb-command:print s @@ -95,11 +98,13 @@ // gdb-command:continue // gdb-command:print aa -// gdb-check:$30 = {__0 = 34, __1 = 35} +// gdbg-check:$30 = {__0 = 34, __1 = 35} +// gdbr-check:$30 = (34, 35) // gdb-command:continue // gdb-command:print bb -// gdb-check:$31 = {__0 = 36, __1 = 37} +// gdbg-check:$31 = {__0 = 36, __1 = 37} +// gdbr-check:$31 = (36, 37) // gdb-command:continue // gdb-command:print cc @@ -107,17 +112,20 @@ // gdb-command:continue // gdb-command:print dd -// gdb-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbr-check:$33 = (40, 41, 42) // gdb-command:continue // gdb-command:print *ee -// gdb-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbr-check:$34 = (43, 44, 45) // gdb-command:continue // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdb-check:$36 = {__0 = 47, __1 = 48} +// gdbg-check:$36 = {__0 = 47, __1 = 48} +// gdbr-check:$36 = (47, 48) // gdb-command:continue // gdb-command:print *hh diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs index a34d5d6adbfcb..e973c22fd4a85 100644 --- a/src/test/debuginfo/destructured-for-loop-variable.rs +++ b/src/test/debuginfo/destructured-for-loop-variable.rs @@ -73,11 +73,13 @@ // gdb-command:continue // gdb-command:print simple_struct_ident -// gdb-check:$23 = {x = 3537, y = 35437.5, z = true} +// gdbg-check:$23 = {x = 3537, y = 35437.5, z = true} +// gdbr-check:$23 = destructured_for_loop_variable::Struct {x: 3537, y: 35437.5, z: true} // gdb-command:continue // gdb-command:print simple_tuple_ident -// gdb-check:$24 = {__0 = 34903493, __1 = 232323} +// gdbg-check:$24 = {__0 = 34903493, __1 = 232323} +// gdbr-check:$24 = (34903493, 232323) // gdb-command:continue // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs index a43e4546d4f8f..1f18b77ab8f6f 100644 --- a/src/test/debuginfo/destructured-local.rs +++ b/src/test/debuginfo/destructured-local.rs @@ -31,12 +31,14 @@ // gdb-command:print f // gdb-check:$6 = 5 // gdb-command:print g -// gdb-check:$7 = {__0 = 6, __1 = 7} +// gdbg-check:$7 = {__0 = 6, __1 = 7} +// gdbr-check:$7 = (6, 7) // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdb-check:$9 = {a = 9, b = 10} +// gdbg-check:$9 = {a = 9, b = 10} +// gdbr-check:$9 = destructured_local::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 @@ -58,7 +60,8 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdb-check:$18 = {a = 21, b = 22} +// gdbg-check:$18 = {a = 21, b = 22} +// gdbr-check:$18 = destructured_local::Struct {a: 21, b: 22} // gdb-command:print s // gdb-check:$19 = 24 @@ -85,25 +88,30 @@ // gdb-check:$29 = 33 // gdb-command:print aa -// gdb-check:$30 = {__0 = 34, __1 = 35} +// gdbg-check:$30 = {__0 = 34, __1 = 35} +// gdbr-check:$30 = (34, 35) // gdb-command:print bb -// gdb-check:$31 = {__0 = 36, __1 = 37} +// gdbg-check:$31 = {__0 = 36, __1 = 37} +// gdbr-check:$31 = (36, 37) // gdb-command:print cc // gdb-check:$32 = 38 // gdb-command:print dd -// gdb-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbr-check:$33 = (40, 41, 42) // gdb-command:print *ee -// gdb-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbr-check:$34 = (43, 44, 45) // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdb-check:$36 = {__0 = 47, __1 = 48} +// gdbg-check:$36 = {__0 = 47, __1 = 48} +// gdbr-check:$36 = (47, 48) // gdb-command:print *hh // gdb-check:$37 = 50 diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs index 8624a0cba0256..2e151577590b3 100644 --- a/src/test/debuginfo/evec-in-struct.rs +++ b/src/test/debuginfo/evec-in-struct.rs @@ -17,18 +17,23 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} +// gdbg-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} +// gdbr-check:$1 = evec_in_struct::NoPadding1 {x: [0, 1, 2], y: -3, z: [4.5, 5.5]} // gdb-command:print no_padding2 -// gdb-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} +// gdbg-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} +// gdbr-check:$2 = evec_in_struct::NoPadding2 {x: [6, 7, 8], y: [[9, 10], [11, 12]]} // gdb-command:print struct_internal_padding -// gdb-check:$3 = {x = {13, 14}, y = {15, 16}} +// gdbg-check:$3 = {x = {13, 14}, y = {15, 16}} +// gdbr-check:$3 = evec_in_struct::StructInternalPadding {x: [13, 14], y: [15, 16]} // gdb-command:print single_vec -// gdb-check:$4 = {x = {17, 18, 19, 20, 21}} +// gdbg-check:$4 = {x = {17, 18, 19, 20, 21}} +// gdbr-check:$4 = evec_in_struct::SingleVec {x: [17, 18, 19, 20, 21]} // gdb-command:print struct_padded_at_end -// gdb-check:$5 = {x = {22, 23}, y = {24, 25}} +// gdbg-check:$5 = {x = {22, 23}, y = {24, 25}} +// gdbr-check:$5 = evec_in_struct::StructPaddedAtEnd {x: [22, 23], y: [24, 25]} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/extern-c-fn.rs b/src/test/debuginfo/extern-c-fn.rs index c93db41dc55bf..01901b2c42b8e 100644 --- a/src/test/debuginfo/extern-c-fn.rs +++ b/src/test/debuginfo/extern-c-fn.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print s -// gdb-check:$1 = [...]"abcd" +// gdbg-check:$1 = [...]"abcd" +// gdbr-check:$1 = [...]"abcd\000" // gdb-command:print len // gdb-check:$2 = 20 // gdb-command:print local0 diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index 57654acaf73d8..21fdc4e5e88a6 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // This test case checks if function arguments already have the correct value @@ -34,9 +36,11 @@ // NON IMMEDIATE ARGS // gdb-command:print a -// gdb-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10} +// gdbg-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10} +// gdbt-check:$4 = function_arg_initialization::BigStruct {a: 3, b: 4, c: 5, d: 6, e: 7, f: 8, g: 9, h: 10} // gdb-command:print b -// gdb-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18} +// gdbg-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18} +// gdbt-check:$5 = function_arg_initialization::BigStruct {a: 11, b: 12, c: 13, d: 14, e: 15, f: 16, g: 17, h: 18} // gdb-command:continue // BINDING diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs index 81743a367e40f..158a1f17fc03d 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs @@ -26,13 +26,16 @@ // gdb-check:$2 = EmptyStruct // gdb-command: print c_style_enum1 -// gdb-check:$3 = CStyleEnumVar1 +// gdbg-check:$3 = CStyleEnumVar1 +// gdbr-check:$3 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar1 // gdb-command: print c_style_enum2 -// gdb-check:$4 = CStyleEnumVar2 +// gdbg-check:$4 = CStyleEnumVar2 +// gdbr-check:$4 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar2 // gdb-command: print c_style_enum3 -// gdb-check:$5 = CStyleEnumVar3 +// gdbg-check:$5 = CStyleEnumVar3 +// gdbr-check:$5 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar3 #![allow(dead_code, unused_variables)] diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs index 3115b3f7e761c..1fc05b3752f04 100644 --- a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs +++ b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs @@ -18,22 +18,37 @@ // gdb-command:run // gdb-command:print eight_bytes1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}} +// gdbr-check:$1 = generic_enum_with_different_disr_sizes::Enum::Variant1(100) + // gdb-command:print four_bytes1 -// gdb-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}} +// gdbr-check:$2 = generic_enum_with_different_disr_sizes::Enum::Variant1(101) + // gdb-command:print two_bytes1 -// gdb-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}} +// gdbr-check:$3 = generic_enum_with_different_disr_sizes::Enum::Variant1(102) + // gdb-command:print one_byte1 -// gdb-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}} +// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}} +// gdbr-check:$4 = generic_enum_with_different_disr_sizes::Enum::Variant1(65) + // gdb-command:print eight_bytes2 -// gdb-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}} +// gdbg-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}} +// gdbr-check:$5 = generic_enum_with_different_disr_sizes::Enum::Variant2(100) + // gdb-command:print four_bytes2 -// gdb-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}} +// gdbg-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}} +// gdbr-check:$6 = generic_enum_with_different_disr_sizes::Enum::Variant2(101) + // gdb-command:print two_bytes2 -// gdb-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}} +// gdbr-check:$7 = generic_enum_with_different_disr_sizes::Enum::Variant2(102) + // gdb-command:print one_byte2 -// gdb-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}} +// gdbg-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}} +// gdbr-check:$8 = generic_enum_with_different_disr_sizes::Enum::Variant2(65) // gdb-command:continue diff --git a/src/test/debuginfo/generic-function.rs b/src/test/debuginfo/generic-function.rs index 415dd36212a44..f1bfc08915edd 100644 --- a/src/test/debuginfo/generic-function.rs +++ b/src/test/debuginfo/generic-function.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // compile-flags:-g @@ -21,7 +23,8 @@ // gdb-command:print *t1 // gdb-check:$2 = 2.5 // gdb-command:print ret -// gdb-check:$3 = {__0 = {__0 = 1, __1 = 2.5}, __1 = {__0 = 2.5, __1 = 1}} +// gdbg-check:$3 = {__0 = {__0 = 1, __1 = 2.5}, __1 = {__0 = 2.5, __1 = 1}} +// gdbr-check:$3 = ((1, 2.5), (2.5, 1)) // gdb-command:continue // gdb-command:print *t0 @@ -29,15 +32,18 @@ // gdb-command:print *t1 // gdb-check:$5 = 4 // gdb-command:print ret -// gdb-check:$6 = {__0 = {__0 = 3.5, __1 = 4}, __1 = {__0 = 4, __1 = 3.5}} +// gdbg-check:$6 = {__0 = {__0 = 3.5, __1 = 4}, __1 = {__0 = 4, __1 = 3.5}} +// gdbr-check:$6 = ((3.5, 4), (4, 3.5)) // gdb-command:continue // gdb-command:print *t0 // gdb-check:$7 = 5 // gdb-command:print *t1 -// gdb-check:$8 = {a = 6, b = 7.5} +// gdbg-check:$8 = {a = 6, b = 7.5} +// gdbr-check:$8 = generic_function::Struct {a: 6, b: 7.5} // gdb-command:print ret -// gdb-check:$9 = {__0 = {__0 = 5, __1 = {a = 6, b = 7.5}}, __1 = {__0 = {a = 6, b = 7.5}, __1 = 5}} +// gdbg-check:$9 = {__0 = {__0 = 5, __1 = {a = 6, b = 7.5}}, __1 = {__0 = {a = 6, b = 7.5}, __1 = 5}} +// gdbr-check:$9 = ((5, generic_function::Struct {a: 6, b: 7.5}), (generic_function::Struct {a: 6, b: 7.5}, 5)) // gdb-command:continue diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 968cb2e159716..4f3f6dfc821ee 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$1 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$4 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 1234.5} +// gdbg-check:$7 = {x = 1234.5} +// gdbr-check:$7 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 1234.5} +// gdbg-check:$10 = {x = 1234.5} +// gdbr-check:$10 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 1234.5} +// gdbg-check:$13 = {x = 1234.5} +// gdbr-check:$13 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 991404f56eff9..dba9422721a96 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -17,16 +17,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbr-check:$1 = generic_struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbr-check:$2 = generic_struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbr-check:$3 = generic_struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdb-check:$4 = {{a = -1}} +// gdbg-check:$4 = {{a = -1}} +// gdbr-check:$4 = generic_struct_style_enum::Univariant::TheOnlyCase{a: -1} #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 92a67a2344d1c..35f00ce78717b 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -18,13 +18,17 @@ // gdb-command:run // gdb-command:print int_int -// gdb-check:$1 = {key = 0, value = 1} +// gdbg-check:$1 = {key = 0, value = 1} +// gdbr-check:$1 = generic_struct::AGenericStruct {key: 0, value: 1} // gdb-command:print int_float -// gdb-check:$2 = {key = 2, value = 3.5} +// gdbg-check:$2 = {key = 2, value = 3.5} +// gdbr-check:$2 = generic_struct::AGenericStruct {key: 2, value: 3.5} // gdb-command:print float_int -// gdb-check:$3 = {key = 4.5, value = 5} +// gdbg-check:$3 = {key = 4.5, value = 5} +// gdbr-check:$3 = generic_struct::AGenericStruct {key: 4.5, value: 5} // gdb-command:print float_int_float -// gdb-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}} +// gdbg-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}} +// gdbr-check:$4 = generic_struct::AGenericStruct> {key: 6.5, value: generic_struct::AGenericStruct {key: 7, value: 8.5}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index e2727fbe7df4a..01d2ff4e33439 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbr-check:$1 = generic_tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbr-check:$2 = generic_tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbr-check:$3 = generic_tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdb-check:$4 = {{__0 = -1}} +// gdbg-check:$4 = {{__0 = -1}} +// gdbr-check:$4 = generic_tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs index 841786f930daf..8e8a194e37841 100644 --- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs +++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs @@ -16,7 +16,8 @@ // gdb-command:run -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$1 = 0 // STRUCT EXPRESSION @@ -28,7 +29,8 @@ // gdb-command:print val // gdb-check:$4 = 11 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$5 = 1 // gdb-command:print ten // gdb-check:$6 = 10 @@ -49,7 +51,8 @@ // gdb-command:print val // gdb-check:$11 = 12 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$12 = 2 // gdb-command:print ten // gdb-check:$13 = 10 @@ -70,7 +73,8 @@ // gdb-command:print val // gdb-check:$18 = 13 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$19 = 3 // gdb-command:print ten // gdb-check:$20 = 10 @@ -91,7 +95,8 @@ // gdb-command:print val // gdb-check:$25 = 14 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$26 = 4 // gdb-command:print ten // gdb-check:$27 = 10 @@ -112,7 +117,8 @@ // gdb-command:print val // gdb-check:$32 = 15 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$33 = 5 // gdb-command:print ten // gdb-check:$34 = 10 @@ -133,7 +139,8 @@ // gdb-command:print val // gdb-check:$39 = 16 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$40 = 6 // gdb-command:print ten // gdb-check:$41 = 10 @@ -155,7 +162,8 @@ // gdb-command:print val // gdb-check:$46 = 17 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$47 = 7 // gdb-command:print ten // gdb-check:$48 = 10 @@ -176,7 +184,8 @@ // gdb-command:print val // gdb-check:$53 = 18 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$54 = 8 // gdb-command:print ten // gdb-check:$55 = 10 diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index 6437b3bb900f8..7dbc0d3c5130d 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -19,7 +19,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbr-check:$1 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -28,7 +29,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbr-check:$4 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -37,7 +39,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$7 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -46,7 +49,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$10 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$10 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -55,7 +59,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$13 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$13 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 5b697f859d4ed..20d419b4ac088 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$1 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$4 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 1234.5} +// gdbg-check:$7 = {x = 1234.5} +// gdbr-check:$7 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 1234.5} +// gdbg-check:$10 = {x = 1234.5} +// gdbr-check:$10 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 1234.5} +// gdbg-check:$13 = {x = 1234.5} +// gdbr-check:$13 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index 3bf2e775e7791..c7546fe2221ff 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index 5ce4a7905a1d0..1dc37bb06ac40 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index d8644a3934f10..dac762ae0c35b 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {__0 = 100, __1 = -100.5} +// gdbg-check:$1 = {__0 = 100, __1 = -100.5} +// gdbr-check:$1 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {__0 = 100, __1 = -100.5} +// gdbg-check:$4 = {__0 = 100, __1 = -100.5} +// gdbr-check:$4 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {__0 = 200, __1 = -200.5} +// gdbg-check:$7 = {__0 = 200, __1 = -200.5} +// gdbr-check:$7 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {__0 = 200, __1 = -200.5} +// gdbg-check:$10 = {__0 = 200, __1 = -200.5} +// gdbr-check:$10 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {__0 = 200, __1 = -200.5} +// gdbg-check:$13 = {__0 = 200, __1 = -200.5} +// gdbr-check:$13 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/nil-enum.rs b/src/test/debuginfo/nil-enum.rs index 81399ec590b14..94377421c0b0c 100644 --- a/src/test/debuginfo/nil-enum.rs +++ b/src/test/debuginfo/nil-enum.rs @@ -16,10 +16,12 @@ // gdb-command:run // gdb-command:print first -// gdb-check:$1 = {} +// gdbg-check:$1 = {} +// gdbr-check:$1 = // gdb-command:print second -// gdb-check:$2 = {} +// gdbg-check:$2 = {} +// gdbr-check:$2 = #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] @@ -28,8 +30,9 @@ enum ANilEnum {} enum AnotherNilEnum {} -// This test relies on gdb printing the string "{}" for empty +// This test relies on gdbg printing the string "{}" for empty // structs (which may change some time) +// The error from gdbr is expected since nil enums are not supposed to exist. fn main() { unsafe { let first: ANilEnum = ::std::mem::zeroed(); diff --git a/src/test/debuginfo/option-like-enum.rs b/src/test/debuginfo/option-like-enum.rs index f103294a94a07..39e6a4e4facf9 100644 --- a/src/test/debuginfo/option-like-enum.rs +++ b/src/test/debuginfo/option-like-enum.rs @@ -18,28 +18,36 @@ // gdb-command:run // gdb-command:print some -// gdb-check:$1 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x12345678}} +// gdbg-check:$1 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x12345678}} +// gdbr-check:$1 = core::option::Option<&u32>::Some(0x12345678) // gdb-command:print none -// gdb-check:$2 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x0}} +// gdbg-check:$2 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x0}} +// gdbr-check:$2 = core::option::Option<&u32>::None // gdb-command:print full -// gdb-check:$3 = {RUST$ENCODED$ENUM$1$Empty = {__0 = 454545, __1 = 0x87654321, __2 = 9988}} +// gdbg-check:$3 = {RUST$ENCODED$ENUM$1$Empty = {__0 = 454545, __1 = 0x87654321, __2 = 9988}} +// gdbr-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988) -// gdb-command:print empty_gdb->discr +// gdbg-command:print empty_gdb->discr +// gdbr-command:print empty_gdb.discr // gdb-check:$4 = (isize *) 0x0 // gdb-command:print droid -// gdb-check:$5 = {RUST$ENCODED$ENUM$2$Void = {id = 675675, range = 10000001, internals = 0x43218765}} +// gdbg-check:$5 = {RUST$ENCODED$ENUM$2$Void = {id = 675675, range = 10000001, internals = 0x43218765}} +// gdbr-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765} -// gdb-command:print void_droid_gdb->internals +// gdbg-command:print void_droid_gdb->internals +// gdbr-command:print void_droid_gdb.internals // gdb-check:$6 = (isize *) 0x0 // gdb-command:print nested_non_zero_yep -// gdb-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = 10.5, __1 = {a = 10, b = 20, c = [...]}}} +// gdbg-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = 10.5, __1 = {a = 10, b = 20, c = [...]}}} +// gdbr-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...] "x[...]"}) // gdb-command:print nested_non_zero_nope -// gdb-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = [...], __1 = {a = [...], b = [...], c = 0x0}}} +// gdbg-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = [...], __1 = {a = [...], b = [...], c = 0x0}}} +// gdbr-check:$8 = option_like_enum::NestedNonZero::Nope // gdb-command:continue diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs index 9d37cb3012b7d..50bd857d46076 100644 --- a/src/test/debuginfo/packed-struct-with-destructor.rs +++ b/src/test/debuginfo/packed-struct-with-destructor.rs @@ -18,29 +18,37 @@ // gdb-command:run // gdb-command:print packed -// gdb-check:$1 = {x = 123, y = 234, z = 345} +// gdbg-check:$1 = {x = 123, y = 234, z = 345} +// gdbr-check:$1 = packed_struct_with_destructor::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbr-check:$2 = packed_struct_with_destructor::PackedInPacked {a: 1111, b: packed_struct_with_destructor::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct_with_destructor::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbr-check:$3 = packed_struct_with_destructor::PackedInUnpacked {a: -1111, b: packed_struct_with_destructor::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct_with_destructor::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} +// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} +// gdbr-check:$4 = packed_struct_with_destructor::UnpackedInPacked {a: 987, b: packed_struct_with_destructor::Unpacked {x: 876, y: 765, z: 654}, c: packed_struct_with_destructor::Unpacked {x: 543, y: 432, z: 321}, d: 210} // gdb-command:print packedInPackedWithDrop -// gdb-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} +// gdbg-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} +// gdbr-check:$5 = packed_struct_with_destructor::PackedInPackedWithDrop {a: 11, b: packed_struct_with_destructor::Packed {x: 22, y: 33, z: 44}, c: 55, d: packed_struct_with_destructor::Packed {x: 66, y: 77, z: 88}} // gdb-command:print packedInUnpackedWithDrop -// gdb-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} +// gdbg-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} +// gdbr-check:$6 = packed_struct_with_destructor::PackedInUnpackedWithDrop {a: -11, b: packed_struct_with_destructor::Packed {x: -22, y: -33, z: -44}, c: -55, d: packed_struct_with_destructor::Packed {x: -66, y: -77, z: -88}} // gdb-command:print unpackedInPackedWithDrop -// gdb-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} +// gdbg-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} +// gdbr-check:$7 = packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 98, b: packed_struct_with_destructor::Unpacked {x: 87, y: 76, z: 65}, c: packed_struct_with_destructor::Unpacked {x: 54, y: 43, z: 32}, d: 21} // gdb-command:print deeplyNested -// gdb-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} +// gdbg-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} +// gdbr-check:$8 = packed_struct_with_destructor::DeeplyNested {a: packed_struct_with_destructor::PackedInPacked {a: 1, b: packed_struct_with_destructor::Packed {x: 2, y: 3, z: 4}, c: 5, d: packed_struct_with_destructor::Packed {x: 6, y: 7, z: 8}}, b: packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 9, b: packed_struct_with_destructor::Unpacked {x: 10, y: 11, z: 12}, c: packed_struct_with_destructor::Unpacked {x: 13, y: 14, z: 15}, d: 16}, c: packed_struct_with_destructor::PackedInUnpacked {a: 17, b: packed_struct_with_destructor::Packed {x: 18, y: 19, z: 20}, c: 21, d: packed_struct_with_destructor::Packed {x: 22, y: 23, z: 24}}, d: packed_struct_with_destructor::PackedInUnpackedWithDrop {a: 25, b: packed_struct_with_destructor::Packed {x: 26, y: 27, z: 28}, c: 29, d: packed_struct_with_destructor::Packed {x: 30, y: 31, z: 32}}, e: packed_struct_with_destructor::UnpackedInPacked {a: 33, b: packed_struct_with_destructor::Unpacked {x: 34, y: 35, z: 36}, c: packed_struct_with_destructor::Unpacked {x: 37, y: 38, z: 39}, d: 40}, f: packed_struct_with_destructor::PackedInPackedWithDrop {a: 41, b: packed_struct_with_destructor::Packed {x: 42, y: 43, z: 44}, c: 45, d: packed_struct_with_destructor::Packed {x: 46, y: 47, z: 48}}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs index e86e963f38cdd..b84161c36a557 100644 --- a/src/test/debuginfo/packed-struct.rs +++ b/src/test/debuginfo/packed-struct.rs @@ -18,16 +18,20 @@ // gdb-command:run // gdb-command:print packed -// gdb-check:$1 = {x = 123, y = 234, z = 345} +// gdbg-check:$1 = {x = 123, y = 234, z = 345} +// gdbr-check:$1 = packed_struct::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbr-check:$2 = packed_struct::PackedInPacked {a: 1111, b: packed_struct::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbr-check:$3 = packed_struct::PackedInUnpacked {a: -1111, b: packed_struct::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} +// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} +// gdbr-check:$4 = packed_struct::UnpackedInPacked {a: 987, b: packed_struct::Unpacked {x: 876, y: 765, z: 654, w: 543}, c: packed_struct::Unpacked {x: 432, y: 321, z: 210, w: 109}, d: -98} // gdb-command:print sizeof(packed) // gdb-check:$5 = 14 diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 576621737e6b6..153f0c8271fc4 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -35,7 +35,8 @@ // gdb-check:$5 = Some = {8} // gdb-command: print none -// gdb-check:$6 = None +// gdbg-check:$6 = None +// gdbr-check:$6 = core::option::Option::None // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index ea067d5bffbec..80147b14174da 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -12,57 +12,72 @@ // ignore-lldb // compile-flags:-g + // gdb-command:run // gdb-command:print stack_unique.value // gdb-check:$1 = 0 -// gdb-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print stack_unique.next.val.value // gdb-check:$2 = 1 -// gdb-command:print unique_unique->value +// gdbg-command:print unique_unique->value +// gdbr-command:print unique_unique.value // gdb-check:$3 = 2 -// gdb-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print unique_unique.next.val.value // gdb-check:$4 = 3 // gdb-command:print vec_unique[0].value // gdb-check:$5 = 6.5 -// gdb-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print vec_unique[0].next.val.value // gdb-check:$6 = 7.5 -// gdb-command:print borrowed_unique->value +// gdbg-command:print borrowed_unique->value +// gdbr-command:print borrowed_unique.value // gdb-check:$7 = 8.5 -// gdb-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print borrowed_unique.next.val.value // gdb-check:$8 = 9.5 // LONG CYCLE // gdb-command:print long_cycle1.value // gdb-check:$9 = 20 -// gdb-command:print long_cycle1.next->value +// gdbg-command:print long_cycle1.next->value +// gdbr-command:print long_cycle1.next.value // gdb-check:$10 = 21 -// gdb-command:print long_cycle1.next->next->value +// gdbg-command:print long_cycle1.next->next->value +// gdbr-command:print long_cycle1.next.next.value // gdb-check:$11 = 22 -// gdb-command:print long_cycle1.next->next->next->value +// gdbg-command:print long_cycle1.next->next->next->value +// gdbr-command:print long_cycle1.next.next.next.value // gdb-check:$12 = 23 // gdb-command:print long_cycle2.value // gdb-check:$13 = 24 -// gdb-command:print long_cycle2.next->value +// gdbg-command:print long_cycle2.next->value +// gdbr-command:print long_cycle2.next.value // gdb-check:$14 = 25 -// gdb-command:print long_cycle2.next->next->value +// gdbg-command:print long_cycle2.next->next->value +// gdbr-command:print long_cycle2.next.next.value // gdb-check:$15 = 26 // gdb-command:print long_cycle3.value // gdb-check:$16 = 27 -// gdb-command:print long_cycle3.next->value +// gdbg-command:print long_cycle3.next->value +// gdbr-command:print long_cycle3.next.value // gdb-check:$17 = 28 // gdb-command:print long_cycle4.value // gdb-check:$18 = 29.5 -// gdb-command:print (*****long_cycle_w_anonymous_types).value +// gdbg-command:print (*****long_cycle_w_anonymous_types).value +// gdbr-command:print long_cycle_w_anonymous_types.value // gdb-check:$19 = 30 -// gdb-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value +// gdbg-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value +// gdbr-command:print long_cycle_w_anonymous_types.next.val.value // gdb-check:$20 = 31 // gdb-command:continue diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index 6d3f93c5d5014..796d122cd66ba 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index aea3bae4bfc1b..b07d7ca5fb7b7 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 987} +// gdbg-check:$1 = {x = 987} +// gdbr-check:$1 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 987} +// gdbg-check:$4 = {x = 987} +// gdbr-check:$4 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 879} +// gdbg-check:$7 = {x = 879} +// gdbr-check:$7 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 879} +// gdbg-check:$10 = {x = 879} +// gdbr-check:$10 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 879} +// gdbg-check:$13 = {x = 879} +// gdbr-check:$13 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs index 80ac901b60fd3..75e68f7efedef 100644 --- a/src/test/debuginfo/simd.rs +++ b/src/test/debuginfo/simd.rs @@ -20,28 +20,46 @@ // compile-flags:-g // gdb-command:run -// gdb-command:print/d vi8x16 -// gdb-check:$1 = {__0 = 0, __1 = 1, __2 = 2, __3 = 3, __4 = 4, __5 = 5, __6 = 6, __7 = 7, __8 = 8, __9 = 9, __10 = 10, __11 = 11, __12 = 12, __13 = 13, __14 = 14, __15 = 15} -// gdb-command:print/d vi16x8 -// gdb-check:$2 = {__0 = 16, __1 = 17, __2 = 18, __3 = 19, __4 = 20, __5 = 21, __6 = 22, __7 = 23} -// gdb-command:print/d vi32x4 -// gdb-check:$3 = {__0 = 24, __1 = 25, __2 = 26, __3 = 27} -// gdb-command:print/d vi64x2 -// gdb-check:$4 = {__0 = 28, __1 = 29} - -// gdb-command:print/d vu8x16 -// gdb-check:$5 = {__0 = 30, __1 = 31, __2 = 32, __3 = 33, __4 = 34, __5 = 35, __6 = 36, __7 = 37, __8 = 38, __9 = 39, __10 = 40, __11 = 41, __12 = 42, __13 = 43, __14 = 44, __15 = 45} -// gdb-command:print/d vu16x8 -// gdb-check:$6 = {__0 = 46, __1 = 47, __2 = 48, __3 = 49, __4 = 50, __5 = 51, __6 = 52, __7 = 53} -// gdb-command:print/d vu32x4 -// gdb-check:$7 = {__0 = 54, __1 = 55, __2 = 56, __3 = 57} -// gdb-command:print/d vu64x2 -// gdb-check:$8 = {__0 = 58, __1 = 59} +// gdbg-command:print/d vi8x16 +// gdbr-command:print vi8x16 +// gdbg-check:$1 = {__0 = 0, __1 = 1, __2 = 2, __3 = 3, __4 = 4, __5 = 5, __6 = 6, __7 = 7, __8 = 8, __9 = 9, __10 = 10, __11 = 11, __12 = 12, __13 = 13, __14 = 14, __15 = 15} +// gdbr-check:$1 = simd::i8x16 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) +// gdbg-command:print/d vi16x8 +// gdbr-command:print vi16x8 +// gdbg-check:$2 = {__0 = 16, __1 = 17, __2 = 18, __3 = 19, __4 = 20, __5 = 21, __6 = 22, __7 = 23} +// gdbr-check:$2 = simd::i16x8 (16, 17, 18, 19, 20, 21, 22, 23) +// gdbg-command:print/d vi32x4 +// gdbr-command:print vi32x4 +// gdbg-check:$3 = {__0 = 24, __1 = 25, __2 = 26, __3 = 27} +// gdbr-check:$3 = simd::i32x4 (24, 25, 26, 27) +// gdbg-command:print/d vi64x2 +// gdbr-command:print vi64x2 +// gdbg-check:$4 = {__0 = 28, __1 = 29} +// gdbr-check:$4 = simd::i64x2 (28, 29) + +// gdbg-command:print/d vu8x16 +// gdbr-command:print vu8x16 +// gdbg-check:$5 = {__0 = 30, __1 = 31, __2 = 32, __3 = 33, __4 = 34, __5 = 35, __6 = 36, __7 = 37, __8 = 38, __9 = 39, __10 = 40, __11 = 41, __12 = 42, __13 = 43, __14 = 44, __15 = 45} +// gdbr-check:$5 = simd::u8x16 (30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45) +// gdbg-command:print/d vu16x8 +// gdbr-command:print vu16x8 +// gdbg-check:$6 = {__0 = 46, __1 = 47, __2 = 48, __3 = 49, __4 = 50, __5 = 51, __6 = 52, __7 = 53} +// gdbr-check:$6 = simd::u16x8 (46, 47, 48, 49, 50, 51, 52, 53) +// gdbg-command:print/d vu32x4 +// gdbr-command:print vu32x4 +// gdbg-check:$7 = {__0 = 54, __1 = 55, __2 = 56, __3 = 57} +// gdbr-check:$7 = simd::u32x4 (54, 55, 56, 57) +// gdbg-command:print/d vu64x2 +// gdbr-command:print vu64x2 +// gdbg-check:$8 = {__0 = 58, __1 = 59} +// gdbr-check:$8 = simd::u64x2 (58, 59) // gdb-command:print vf32x4 -// gdb-check:$9 = {__0 = 60.5, __1 = 61.5, __2 = 62.5, __3 = 63.5} +// gdbg-check:$9 = {__0 = 60.5, __1 = 61.5, __2 = 62.5, __3 = 63.5} +// gdbr-check:$9 = simd::f32x4 (60.5, 61.5, 62.5, 63.5) // gdb-command:print vf64x2 -// gdb-check:$10 = {__0 = 64.5, __1 = 65.5} +// gdbg-check:$10 = {__0 = 64.5, __1 = 65.5} +// gdbr-check:$10 = simd::f64x2 (64.5, 65.5) // gdb-command:continue diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs index d25cd4d7c047f..4956313ad2214 100644 --- a/src/test/debuginfo/simple-struct.rs +++ b/src/test/debuginfo/simple-struct.rs @@ -14,61 +14,94 @@ // === GDB TESTS =================================================================================== -// gdb-command:print 'simple_struct::NO_PADDING_16' -// gdb-check:$1 = {x = 1000, y = -1001} - -// gdb-command:print 'simple_struct::NO_PADDING_32' -// gdb-check:$2 = {x = 1, y = 2, z = 3} - -// gdb-command:print 'simple_struct::NO_PADDING_64' -// gdb-check:$3 = {x = 4, y = 5, z = 6} - -// gdb-command:print 'simple_struct::NO_PADDING_163264' -// gdb-check:$4 = {a = 7, b = 8, c = 9, d = 10} - -// gdb-command:print 'simple_struct::INTERNAL_PADDING' -// gdb-check:$5 = {x = 11, y = 12} - -// gdb-command:print 'simple_struct::PADDING_AT_END' -// gdb-check:$6 = {x = 13, y = 14} +// there's no frame yet for gdb to reliably detect the language, set it explicitly +// gdbr-command:set language rust + +// gdbg-command:print 'simple_struct::NO_PADDING_16' +// gdbr-command:print simple_struct::NO_PADDING_16 +// gdbg-check:$1 = {x = 1000, y = -1001} +// gdbr-check:$1 = simple_struct::NoPadding16 {x: 1000, y: -1001} + +// gdbg-command:print 'simple_struct::NO_PADDING_32' +// gdbr-command:print simple_struct::NO_PADDING_32 +// gdbg-check:$2 = {x = 1, y = 2, z = 3} +// gdbr-check:$2 = simple_struct::NoPadding32 {x: 1, y: 2, z: 3} + +// gdbg-command:print 'simple_struct::NO_PADDING_64' +// gdbr-command:print simple_struct::NO_PADDING_64 +// gdbg-check:$3 = {x = 4, y = 5, z = 6} +// gdbr-check:$3 = simple_struct::NoPadding64 {x: 4, y: 5, z: 6} + +// gdbg-command:print 'simple_struct::NO_PADDING_163264' +// gdbr-command:print simple_struct::NO_PADDING_163264 +// gdbg-check:$4 = {a = 7, b = 8, c = 9, d = 10} +// gdbr-check:$4 = simple_struct::NoPadding163264 {a: 7, b: 8, c: 9, d: 10} + +// gdbg-command:print 'simple_struct::INTERNAL_PADDING' +// gdbr-command:print simple_struct::INTERNAL_PADDING +// gdbg-check:$5 = {x = 11, y = 12} +// gdbr-check:$5 = simple_struct::InternalPadding {x: 11, y: 12} + +// gdbg-command:print 'simple_struct::PADDING_AT_END' +// gdbr-command:print simple_struct::PADDING_AT_END +// gdbg-check:$6 = {x = 13, y = 14} +// gdbr-check:$6 = simple_struct::PaddingAtEnd {x: 13, y: 14} // gdb-command:run // gdb-command:print no_padding16 -// gdb-check:$7 = {x = 10000, y = -10001} +// gdbg-check:$7 = {x = 10000, y = -10001} +// gdbr-check:$7 = simple_struct::NoPadding16 {x: 10000, y: -10001} // gdb-command:print no_padding32 -// gdb-check:$8 = {x = -10002, y = -10003.5, z = 10004} +// gdbg-check:$8 = {x = -10002, y = -10003.5, z = 10004} +// gdbr-check:$8 = simple_struct::NoPadding32 {x: -10002, y: -10003.5, z: 10004} // gdb-command:print no_padding64 -// gdb-check:$9 = {x = -10005.5, y = 10006, z = 10007} +// gdbg-check:$9 = {x = -10005.5, y = 10006, z = 10007} +// gdbr-check:$9 = simple_struct::NoPadding64 {x: -10005.5, y: 10006, z: 10007} // gdb-command:print no_padding163264 -// gdb-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011} +// gdbg-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011} +// gdbr-check:$10 = simple_struct::NoPadding163264 {a: -10008, b: 10009, c: 10010, d: 10011} // gdb-command:print internal_padding -// gdb-check:$11 = {x = 10012, y = -10013} +// gdbg-check:$11 = {x = 10012, y = -10013} +// gdbr-check:$11 = simple_struct::InternalPadding {x: 10012, y: -10013} // gdb-command:print padding_at_end -// gdb-check:$12 = {x = -10014, y = 10015} - -// gdb-command:print 'simple_struct::NO_PADDING_16' -// gdb-check:$13 = {x = 100, y = -101} - -// gdb-command:print 'simple_struct::NO_PADDING_32' -// gdb-check:$14 = {x = -15, y = -16, z = 17} - -// gdb-command:print 'simple_struct::NO_PADDING_64' -// gdb-check:$15 = {x = -18, y = 19, z = 20} - -// gdb-command:print 'simple_struct::NO_PADDING_163264' -// gdb-check:$16 = {a = -21, b = 22, c = 23, d = 24} - -// gdb-command:print 'simple_struct::INTERNAL_PADDING' -// gdb-check:$17 = {x = 25, y = -26} - -// gdb-command:print 'simple_struct::PADDING_AT_END' -// gdb-check:$18 = {x = -27, y = 28} +// gdbg-check:$12 = {x = -10014, y = 10015} +// gdbr-check:$12 = simple_struct::PaddingAtEnd {x: -10014, y: 10015} + +// gdbg-command:print 'simple_struct::NO_PADDING_16' +// gdbr-command:print simple_struct::NO_PADDING_16 +// gdbg-check:$13 = {x = 100, y = -101} +// gdbr-check:$13 = simple_struct::NoPadding16 {x: 100, y: -101} + +// gdbg-command:print 'simple_struct::NO_PADDING_32' +// gdbr-command:print simple_struct::NO_PADDING_32 +// gdbg-check:$14 = {x = -15, y = -16, z = 17} +// gdbr-check:$14 = simple_struct::NoPadding32 {x: -15, y: -16, z: 17} + +// gdbg-command:print 'simple_struct::NO_PADDING_64' +// gdbr-command:print simple_struct::NO_PADDING_64 +// gdbg-check:$15 = {x = -18, y = 19, z = 20} +// gdbr-check:$15 = simple_struct::NoPadding64 {x: -18, y: 19, z: 20} + +// gdbg-command:print 'simple_struct::NO_PADDING_163264' +// gdbr-command:print simple_struct::NO_PADDING_163264 +// gdbg-check:$16 = {a = -21, b = 22, c = 23, d = 24} +// gdbr-check:$16 = simple_struct::NoPadding163264 {a: -21, b: 22, c: 23, d: 24} + +// gdbg-command:print 'simple_struct::INTERNAL_PADDING' +// gdbr-command:print simple_struct::INTERNAL_PADDING +// gdbg-check:$17 = {x = 25, y = -26} +// gdbr-check:$17 = simple_struct::InternalPadding {x: 25, y: -26} + +// gdbg-command:print 'simple_struct::PADDING_AT_END' +// gdbr-command:print simple_struct::PADDING_AT_END +// gdbg-check:$18 = {x = -27, y = 28} +// gdbr-check:$18 = simple_struct::PaddingAtEnd {x: -27, y: 28} // gdb-command:continue diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index 1b85ecc537a34..354a2c26cb36d 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -14,58 +14,97 @@ // === GDB TESTS =================================================================================== -// gdb-command:print/d 'simple_tuple::NO_PADDING_8' -// gdb-check:$1 = {__0 = -50, __1 = 50} -// gdb-command:print 'simple_tuple::NO_PADDING_16' -// gdb-check:$2 = {__0 = -1, __1 = 2, __2 = 3} -// gdb-command:print 'simple_tuple::NO_PADDING_32' -// gdb-check:$3 = {__0 = 4, __1 = 5, __2 = 6} -// gdb-command:print 'simple_tuple::NO_PADDING_64' -// gdb-check:$4 = {__0 = 7, __1 = 8, __2 = 9} - -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdb-check:$5 = {__0 = 10, __1 = 11} -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdb-check:$6 = {__0 = 12, __1 = 13, __2 = 14, __3 = 15} - -// gdb-command:print 'simple_tuple::PADDING_AT_END' -// gdb-check:$7 = {__0 = 16, __1 = 17} +// there's no frame yet for gdb to reliably detect the language, set it explicitly +// gdbr-command:set language rust + +// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' +// gdbr-command:print simple_tuple::NO_PADDING_8 +// gdbg-check:$1 = {__0 = -50, __1 = 50} +// gdbr-check:$1 = (-50, 50) +// gdbg-command:print 'simple_tuple::NO_PADDING_16' +// gdbr-command:print simple_tuple::NO_PADDING_16 +// gdbg-check:$2 = {__0 = -1, __1 = 2, __2 = 3} +// gdbr-check:$2 = (-1, 2, 3) +// gdbg-command:print 'simple_tuple::NO_PADDING_32' +// gdbr-command:print simple_tuple::NO_PADDING_32 +// gdbg-check:$3 = {__0 = 4, __1 = 5, __2 = 6} +// gdbr-check:$3 = (4, 5, 6) +// gdbg-command:print 'simple_tuple::NO_PADDING_64' +// gdbr-command:print simple_tuple::NO_PADDING_64 +// gdbg-check:$4 = {__0 = 7, __1 = 8, __2 = 9} +// gdbr-check:$4 = (7, 8, 9) + +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 +// gdbg-check:$5 = {__0 = 10, __1 = 11} +// gdbr-check:$5 = (10, 11) +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 +// gdbg-check:$6 = {__0 = 12, __1 = 13, __2 = 14, __3 = 15} +// gdbr-check:$6 = (12, 13, 14, 15) + +// gdbg-command:print 'simple_tuple::PADDING_AT_END' +// gdbr-command:print simple_tuple::PADDING_AT_END +// gdbg-check:$7 = {__0 = 16, __1 = 17} +// gdbr-check:$7 = (16, 17) // gdb-command:run -// gdb-command:print/d noPadding8 -// gdb-check:$8 = {__0 = -100, __1 = 100} +// gdbg-command:print/d noPadding8 +// gdbr-command:print noPadding8 +// gdbg-check:$8 = {__0 = -100, __1 = 100} +// gdbr-check:$8 = (-100, 100) // gdb-command:print noPadding16 -// gdb-check:$9 = {__0 = 0, __1 = 1, __2 = 2} +// gdbg-check:$9 = {__0 = 0, __1 = 1, __2 = 2} +// gdbr-check:$9 = (0, 1, 2) // gdb-command:print noPadding32 -// gdb-check:$10 = {__0 = 3, __1 = 4.5, __2 = 5} +// gdbg-check:$10 = {__0 = 3, __1 = 4.5, __2 = 5} +// gdbr-check:$10 = (3, 4.5, 5) // gdb-command:print noPadding64 -// gdb-check:$11 = {__0 = 6, __1 = 7.5, __2 = 8} +// gdbg-check:$11 = {__0 = 6, __1 = 7.5, __2 = 8} +// gdbr-check:$11 = (6, 7.5, 8) // gdb-command:print internalPadding1 -// gdb-check:$12 = {__0 = 9, __1 = 10} +// gdbg-check:$12 = {__0 = 9, __1 = 10} +// gdbr-check:$12 = (9, 10) // gdb-command:print internalPadding2 -// gdb-check:$13 = {__0 = 11, __1 = 12, __2 = 13, __3 = 14} +// gdbg-check:$13 = {__0 = 11, __1 = 12, __2 = 13, __3 = 14} +// gdbr-check:$13 = (11, 12, 13, 14) // gdb-command:print paddingAtEnd -// gdb-check:$14 = {__0 = 15, __1 = 16} - -// gdb-command:print/d 'simple_tuple::NO_PADDING_8' -// gdb-check:$15 = {__0 = -127, __1 = 127} -// gdb-command:print 'simple_tuple::NO_PADDING_16' -// gdb-check:$16 = {__0 = -10, __1 = 10, __2 = 9} -// gdb-command:print 'simple_tuple::NO_PADDING_32' -// gdb-check:$17 = {__0 = 14, __1 = 15, __2 = 16} -// gdb-command:print 'simple_tuple::NO_PADDING_64' -// gdb-check:$18 = {__0 = 17, __1 = 18, __2 = 19} - -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdb-check:$19 = {__0 = 110, __1 = 111} -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdb-check:$20 = {__0 = 112, __1 = 113, __2 = 114, __3 = 115} - -// gdb-command:print 'simple_tuple::PADDING_AT_END' -// gdb-check:$21 = {__0 = 116, __1 = 117} +// gdbg-check:$14 = {__0 = 15, __1 = 16} +// gdbr-check:$14 = (15, 16) + +// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' +// gdbr-command:print simple_tuple::NO_PADDING_8 +// gdbg-check:$15 = {__0 = -127, __1 = 127} +// gdbr-check:$15 = (-127, 127) +// gdbg-command:print 'simple_tuple::NO_PADDING_16' +// gdbr-command:print simple_tuple::NO_PADDING_16 +// gdbg-check:$16 = {__0 = -10, __1 = 10, __2 = 9} +// gdbr-check:$16 = (-10, 10, 9) +// gdbg-command:print 'simple_tuple::NO_PADDING_32' +// gdbr-command:print simple_tuple::NO_PADDING_32 +// gdbg-check:$17 = {__0 = 14, __1 = 15, __2 = 16} +// gdbr-check:$17 = (14, 15, 16) +// gdbg-command:print 'simple_tuple::NO_PADDING_64' +// gdbr-command:print simple_tuple::NO_PADDING_64 +// gdbg-check:$18 = {__0 = 17, __1 = 18, __2 = 19} +// gdbr-check:$18 = (17, 18, 19) + +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 +// gdbg-check:$19 = {__0 = 110, __1 = 111} +// gdbr-check:$19 = (110, 111) +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 +// gdbg-check:$20 = {__0 = 112, __1 = 113, __2 = 114, __3 = 115} +// gdbr-check:$20 = (112, 113, 114, 115) + +// gdbg-command:print 'simple_tuple::PADDING_AT_END' +// gdbr-command:print simple_tuple::PADDING_AT_END +// gdbg-check:$21 = {__0 = 116, __1 = 117} +// gdbr-check:$21 = (116, 117) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index 98b90de600516..d0aceaa4f3f9c 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -19,13 +19,16 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452, __2 = 31868}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452, __2 = 31868}} +// gdbr-check:$1 = struct_in_enum::Regular::Case1(0, struct_in_enum::Struct {x: 2088533116, y: 2088533116, z: 31868}) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = {x = 286331153, y = 286331153, z = 4369}}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = {x = 286331153, y = 286331153, z = 4369}}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} +// gdbr-check:$2 = struct_in_enum::Regular::Case2(0, 1229782938247303441, 4369) // gdb-command:print univariant -// gdb-check:$3 = {{__0 = {x = 123, y = 456, z = 789}}} +// gdbg-check:$3 = {{__0 = {x = 123, y = 456, z = 789}}} +// gdbr-check:$3 = struct_in_enum::Univariant::TheOnlyCase(struct_in_enum::Struct {x: 123, y: 456, z: 789}) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-in-struct.rs b/src/test/debuginfo/struct-in-struct.rs index 76a1613c23146..46524cf1d029a 100644 --- a/src/test/debuginfo/struct-in-struct.rs +++ b/src/test/debuginfo/struct-in-struct.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print three_simple_structs -// gdb-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}} +// gdbg-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}} +// gdbr-check:$1 = struct_in_struct::ThreeSimpleStructs {x: struct_in_struct::Simple {x: 1}, y: struct_in_struct::Simple {x: 2}, z: struct_in_struct::Simple {x: 3}} // gdb-command:print internal_padding_parent -// gdb-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}} +// gdbg-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}} +// gdbr-check:$2 = struct_in_struct::InternalPaddingParent {x: struct_in_struct::InternalPadding {x: 4, y: 5}, y: struct_in_struct::InternalPadding {x: 6, y: 7}, z: struct_in_struct::InternalPadding {x: 8, y: 9}} // gdb-command:print padding_at_end_parent -// gdb-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}} +// gdbg-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}} +// gdbr-check:$3 = struct_in_struct::PaddingAtEndParent {x: struct_in_struct::PaddingAtEnd {x: 10, y: 11}, y: struct_in_struct::PaddingAtEnd {x: 12, y: 13}, z: struct_in_struct::PaddingAtEnd {x: 14, y: 15}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 3376fc9bbd450..8abc139eb1172 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbr-check:$1 = struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbr-check:$2 = struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbr-check:$3 = struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdb-check:$4 = {{a = -1}} +// gdbg-check:$4 = {{a = -1}} +// gdbr-check:$4 = struct_style_enum::Univariant::TheOnlyCase{a: -1} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-with-destructor.rs b/src/test/debuginfo/struct-with-destructor.rs index ad8731997abd7..af70b4a63fd27 100644 --- a/src/test/debuginfo/struct-with-destructor.rs +++ b/src/test/debuginfo/struct-with-destructor.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // compile-flags:-g @@ -16,16 +18,20 @@ // gdb-command:run // gdb-command:print simple -// gdb-check:$1 = {x = 10, y = 20} +// gdbg-check:$1 = {x = 10, y = 20} +// gdbr-check:$1 = struct_with_destructor::WithDestructor {x: 10, y: 20} // gdb-command:print noDestructor -// gdb-check:$2 = {a = {x = 10, y = 20}, guard = -1} +// gdbg-check:$2 = {a = {x = 10, y = 20}, guard = -1} +// gdbr-check:$2 = struct_with_destructor::NoDestructorGuarded {a: struct_with_destructor::NoDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print withDestructor -// gdb-check:$3 = {a = {x = 10, y = 20}, guard = -1} +// gdbg-check:$3 = {a = {x = 10, y = 20}, guard = -1} +// gdbr-check:$3 = struct_with_destructor::WithDestructorGuarded {a: struct_with_destructor::WithDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print nested -// gdb-check:$4 = {a = {a = {x = 7890, y = 9870}}} +// gdbg-check:$4 = {a = {a = {x = 7890, y = 9870}}} +// gdbr-check:$4 = struct_with_destructor::NestedOuter {a: struct_with_destructor::NestedInner {a: struct_with_destructor::WithDestructor {x: 7890, y: 9870}}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-in-struct.rs b/src/test/debuginfo/tuple-in-struct.rs index 1a7fde766f0d8..dae1f5da542f5 100644 --- a/src/test/debuginfo/tuple-in-struct.rs +++ b/src/test/debuginfo/tuple-in-struct.rs @@ -17,29 +17,39 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {x = {__0 = 0, __1 = 1}, y = 2, z = {__0 = 3, __1 = 4, __2 = 5}} +// gdbg-check:$1 = {x = {__0 = 0, __1 = 1}, y = 2, z = {__0 = 3, __1 = 4, __2 = 5}} +// gdbr-check:$1 = tuple_in_struct::NoPadding1 {x: (0, 1), y: 2, z: (3, 4, 5)} // gdb-command:print no_padding2 -// gdb-check:$2 = {x = {__0 = 6, __1 = 7}, y = {__0 = {__0 = 8, __1 = 9}, __1 = 10}} +// gdbg-check:$2 = {x = {__0 = 6, __1 = 7}, y = {__0 = {__0 = 8, __1 = 9}, __1 = 10}} +// gdbr-check:$2 = tuple_in_struct::NoPadding2 {x: (6, 7), y: ((8, 9), 10)} // gdb-command:print tuple_internal_padding -// gdb-check:$3 = {x = {__0 = 11, __1 = 12}, y = {__0 = 13, __1 = 14}} +// gdbg-check:$3 = {x = {__0 = 11, __1 = 12}, y = {__0 = 13, __1 = 14}} +// gdbr-check:$3 = tuple_in_struct::TupleInternalPadding {x: (11, 12), y: (13, 14)} // gdb-command:print struct_internal_padding -// gdb-check:$4 = {x = {__0 = 15, __1 = 16}, y = {__0 = 17, __1 = 18}} +// gdbg-check:$4 = {x = {__0 = 15, __1 = 16}, y = {__0 = 17, __1 = 18}} +// gdbr-check:$4 = tuple_in_struct::StructInternalPadding {x: (15, 16), y: (17, 18)} // gdb-command:print both_internally_padded -// gdb-check:$5 = {x = {__0 = 19, __1 = 20, __2 = 21}, y = {__0 = 22, __1 = 23}} +// gdbg-check:$5 = {x = {__0 = 19, __1 = 20, __2 = 21}, y = {__0 = 22, __1 = 23}} +// gdbr-check:$5 = tuple_in_struct::BothInternallyPadded {x: (19, 20, 21), y: (22, 23)} // gdb-command:print single_tuple -// gdb-check:$6 = {x = {__0 = 24, __1 = 25, __2 = 26}} +// gdbg-check:$6 = {x = {__0 = 24, __1 = 25, __2 = 26}} +// gdbr-check:$6 = tuple_in_struct::SingleTuple {x: (24, 25, 26)} // gdb-command:print tuple_padded_at_end -// gdb-check:$7 = {x = {__0 = 27, __1 = 28}, y = {__0 = 29, __1 = 30}} +// gdbg-check:$7 = {x = {__0 = 27, __1 = 28}, y = {__0 = 29, __1 = 30}} +// gdbr-check:$7 = tuple_in_struct::TuplePaddedAtEnd {x: (27, 28), y: (29, 30)} // gdb-command:print struct_padded_at_end -// gdb-check:$8 = {x = {__0 = 31, __1 = 32}, y = {__0 = 33, __1 = 34}} +// gdbg-check:$8 = {x = {__0 = 31, __1 = 32}, y = {__0 = 33, __1 = 34}} +// gdbr-check:$8 = tuple_in_struct::StructPaddedAtEnd {x: (31, 32), y: (33, 34)} // gdb-command:print both_padded_at_end -// gdb-check:$9 = {x = {__0 = 35, __1 = 36, __2 = 37}, y = {__0 = 38, __1 = 39}} +// gdbg-check:$9 = {x = {__0 = 35, __1 = 36, __2 = 37}, y = {__0 = 38, __1 = 39}} +// gdbr-check:$9 = tuple_in_struct::BothPaddedAtEnd {x: (35, 36, 37), y: (38, 39)} // gdb-command:print mixed_padding -// gdb-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}} +// gdbg-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}} +// gdbr-check:$10 = tuple_in_struct::MixedPadding {x: ((40, 41, 42), (43, 44)), y: (45, 46, 47, 48)} #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index a514b69a2d31d..4ebc740b9c0f7 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -17,21 +17,28 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {__0 = {__0 = 0, __1 = 1}, __1 = 2, __2 = 3} +// gdbg-check:$1 = {__0 = {__0 = 0, __1 = 1}, __1 = 2, __2 = 3} +// gdbr-check:$1 = ((0, 1), 2, 3) // gdb-command:print no_padding2 -// gdb-check:$2 = {__0 = 4, __1 = {__0 = 5, __1 = 6}, __2 = 7} +// gdbg-check:$2 = {__0 = 4, __1 = {__0 = 5, __1 = 6}, __2 = 7} +// gdbr-check:$2 = (4, (5, 6), 7) // gdb-command:print no_padding3 -// gdb-check:$3 = {__0 = 8, __1 = 9, __2 = {__0 = 10, __1 = 11}} +// gdbg-check:$3 = {__0 = 8, __1 = 9, __2 = {__0 = 10, __1 = 11}} +// gdbr-check:$3 = (8, 9, (10, 11)) // gdb-command:print internal_padding1 -// gdb-check:$4 = {__0 = 12, __1 = {__0 = 13, __1 = 14}} +// gdbg-check:$4 = {__0 = 12, __1 = {__0 = 13, __1 = 14}} +// gdbr-check:$4 = (12, (13, 14)) // gdb-command:print internal_padding2 -// gdb-check:$5 = {__0 = 15, __1 = {__0 = 16, __1 = 17}} +// gdbg-check:$5 = {__0 = 15, __1 = {__0 = 16, __1 = 17}} +// gdbr-check:$5 = (15, (16, 17)) // gdb-command:print padding_at_end1 -// gdb-check:$6 = {__0 = 18, __1 = {__0 = 19, __1 = 20}} +// gdbg-check:$6 = {__0 = 18, __1 = {__0 = 19, __1 = 20}} +// gdbr-check:$6 = (18, (19, 20)) // gdb-command:print padding_at_end2 -// gdb-check:$7 = {__0 = {__0 = 21, __1 = 22}, __1 = 23} +// gdbg-check:$7 = {__0 = {__0 = 21, __1 = 22}, __1 = 23} +// gdbr-check:$7 = ((21, 22), 23) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-struct.rs b/src/test/debuginfo/tuple-struct.rs index a2ca8c2237b42..aa644d8419b54 100644 --- a/src/test/debuginfo/tuple-struct.rs +++ b/src/test/debuginfo/tuple-struct.rs @@ -17,22 +17,28 @@ // gdb-command:run // gdb-command:print no_padding16 -// gdb-check:$1 = {__0 = 10000, __1 = -10001} +// gdbg-check:$1 = {__0 = 10000, __1 = -10001} +// gdbr-check:$1 = tuple_struct::NoPadding16 (10000, -10001) // gdb-command:print no_padding32 -// gdb-check:$2 = {__0 = -10002, __1 = -10003.5, __2 = 10004} +// gdbg-check:$2 = {__0 = -10002, __1 = -10003.5, __2 = 10004} +// gdbr-check:$2 = tuple_struct::NoPadding32 (-10002, -10003.5, 10004) // gdb-command:print no_padding64 -// gdb-check:$3 = {__0 = -10005.5, __1 = 10006, __2 = 10007} +// gdbg-check:$3 = {__0 = -10005.5, __1 = 10006, __2 = 10007} +// gdbr-check:$3 = tuple_struct::NoPadding64 (-10005.5, 10006, 10007) // gdb-command:print no_padding163264 -// gdb-check:$4 = {__0 = -10008, __1 = 10009, __2 = 10010, __3 = 10011} +// gdbg-check:$4 = {__0 = -10008, __1 = 10009, __2 = 10010, __3 = 10011} +// gdbr-check:$4 = tuple_struct::NoPadding163264 (-10008, 10009, 10010, 10011) // gdb-command:print internal_padding -// gdb-check:$5 = {__0 = 10012, __1 = -10013} +// gdbg-check:$5 = {__0 = 10012, __1 = -10013} +// gdbr-check:$5 = tuple_struct::InternalPadding (10012, -10013) // gdb-command:print padding_at_end -// gdb-check:$6 = {__0 = -10014, __1 = 10015} +// gdbg-check:$6 = {__0 = -10014, __1 = 10015} +// gdbr-check:$6 = tuple_struct::PaddingAtEnd (-10014, 10015) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index 52f171434b037..d05edec3e737d 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbr-check:$1 = tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbr-check:$2 = tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbr-check:$3 = tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdb-check:$4 = {{__0 = -1}} +// gdbg-check:$4 = {{__0 = -1}} +// gdbr-check:$4 = tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 2419625cbd374..438a78743bb1e 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -20,160 +20,206 @@ // STRUCTS // gdb-command:whatis simple_struct -// gdb-check:type = struct Struct1 +// gdbg-check:type = struct Struct1 +// gdbr-check:type = type_names::Struct1 // gdb-command:whatis generic_struct1 -// gdb-check:type = struct GenericStruct +// gdbg-check:type = struct GenericStruct +// gdbr-check:type = type_names::GenericStruct // gdb-command:whatis generic_struct2 -// gdb-check:type = struct GenericStruct usize> +// gdbg-check:type = struct GenericStruct usize> +// gdbr-check:type = type_names::GenericStruct usize> // gdb-command:whatis mod_struct -// gdb-check:type = struct Struct2 +// gdbg-check:type = struct Struct2 +// gdbr-check:type = type_names::mod1::Struct2 // ENUMS // gdb-command:whatis simple_enum_1 -// gdb-check:type = union Enum1 +// gdbg-check:type = union Enum1 +// gdbr-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_2 -// gdb-check:type = union Enum1 +// gdbg-check:type = union Enum1 +// gdbr-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_3 -// gdb-check:type = union Enum2 +// gdbg-check:type = union Enum2 +// gdbr-check:type = type_names::mod1::Enum2 // gdb-command:whatis generic_enum_1 -// gdb-check:type = union Enum3 +// gdbg-check:type = union Enum3 +// gdbr-check:type = type_names::mod1::mod2::Enum3 // gdb-command:whatis generic_enum_2 -// gdb-check:type = union Enum3 +// gdbg-check:type = union Enum3 +// gdbr-check:type = type_names::mod1::mod2::Enum3 // TUPLES // gdb-command:whatis tuple1 -// gdb-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) // gdb-command:whatis tuple2 -// gdb-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) // BOX // gdb-command:whatis box1 -// gdb-check:type = struct (Box, i32) +// gdbg-check:type = struct (Box, i32) +// gdbr-check:type = (Box, i32) // gdb-command:whatis box2 -// gdb-check:type = struct (Box>, i32) +// gdbg-check:type = struct (Box>, i32) +// gdbr-check:type = (Box>, i32) // REFERENCES // gdb-command:whatis ref1 -// gdb-check:type = struct (&type_names::Struct1, i32) +// gdbg-check:type = struct (&type_names::Struct1, i32) +// gdbr-check:type = (&type_names::Struct1, i32) // gdb-command:whatis ref2 -// gdb-check:type = struct (&type_names::GenericStruct, i32) +// gdbg-check:type = struct (&type_names::GenericStruct, i32) +// gdbr-check:type = (&type_names::GenericStruct, i32) // gdb-command:whatis mut_ref1 -// gdb-check:type = struct (&mut type_names::Struct1, i32) +// gdbg-check:type = struct (&mut type_names::Struct1, i32) +// gdbr-check:type = (&mut type_names::Struct1, i32) // gdb-command:whatis mut_ref2 -// gdb-check:type = struct (&mut type_names::GenericStruct, i32) +// gdbg-check:type = struct (&mut type_names::GenericStruct, i32) +// gdbr-check:type = (&mut type_names::GenericStruct, i32) // RAW POINTERS // gdb-command:whatis mut_ptr1 -// gdb-check:type = struct (*mut type_names::Struct1, isize) +// gdbg-check:type = struct (*mut type_names::Struct1, isize) +// gdbr-check:type = (*mut type_names::Struct1, isize) // gdb-command:whatis mut_ptr2 -// gdb-check:type = struct (*mut isize, isize) +// gdbg-check:type = struct (*mut isize, isize) +// gdbr-check:type = (*mut isize, isize) // gdb-command:whatis mut_ptr3 -// gdb-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) +// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) +// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3, isize) // gdb-command:whatis const_ptr1 -// gdb-check:type = struct (*const type_names::Struct1, isize) +// gdbg-check:type = struct (*const type_names::Struct1, isize) +// gdbr-check:type = (*const type_names::Struct1, isize) // gdb-command:whatis const_ptr2 -// gdb-check:type = struct (*const isize, isize) +// gdbg-check:type = struct (*const isize, isize) +// gdbr-check:type = (*const isize, isize) // gdb-command:whatis const_ptr3 -// gdb-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) +// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) +// gdbr-check:type = (*const type_names::mod1::mod2::Enum3, isize) // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdb-check:type = struct ([type_names::Struct1; 3], i16) +// gdbg-check:type = struct ([type_names::Struct1; 3], i16) +// gdbr-check:type = ([type_names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 -// gdb-check:type = struct ([usize; 3], i16) +// gdbg-check:type = struct ([usize; 3], i16) +// gdbr-check:type = ([usize; 3], i16) // gdb-command:whatis slice1 -// gdb-check:type = struct &[usize] +// gdbg-check:type = struct &[usize] +// gdbr-check:type = &[usize] // gdb-command:whatis slice2 -// gdb-check:type = struct &[type_names::mod1::Enum2] +// gdbg-check:type = struct &[type_names::mod1::Enum2] +// gdbr-check:type = &[type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait -// gdb-check:type = struct Box +// gdbg-check:type = struct Box +// gdbr-check:type = type_names::Box // gdb-command:whatis ref_trait -// gdb-check:type = struct &Trait1 +// gdbg-check:type = struct &Trait1 +// gdbr-check:type = type_names::&Trait1 // gdb-command:whatis mut_ref_trait -// gdb-check:type = struct &mut Trait1 +// gdbg-check:type = struct &mut Trait1 +// gdbr-check:type = type_names::&mut Trait1 // gdb-command:whatis generic_box_trait -// gdb-check:type = struct Box> +// gdbg-check:type = struct Box> +// gdbr-check:type = type_names::Box> // gdb-command:whatis generic_ref_trait -// gdb-check:type = struct &Trait2 +// gdbg-check:type = struct &Trait2 +// gdbr-check:type = type_names::&Trait2 // gdb-command:whatis generic_mut_ref_trait -// gdb-check:type = struct &mut Trait2> +// gdbg-check:type = struct &mut Trait2> +// gdbr-check:type = type_names::&mut Trait2> // BARE FUNCTIONS // gdb-command:whatis rust_fn -// gdb-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdbg-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdbr-check:type = (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) // gdb-command:whatis extern_c_fn -// gdb-check:type = struct (extern "C" fn(isize), usize) +// gdbg-check:type = struct (extern "C" fn(isize), usize) +// gdbr-check:type = (extern "C" fn(isize), usize) // gdb-command:whatis unsafe_fn -// gdb-check:type = struct (unsafe fn(core::result::Result), usize) +// gdbg-check:type = struct (unsafe fn(core::result::Result), usize) +// gdbr-check:type = (unsafe fn(core::result::Result), usize) // gdb-command:whatis extern_stdcall_fn -// gdb-check:type = struct (extern "stdcall" fn(), usize) +// gdbg-check:type = struct (extern "stdcall" fn(), usize) +// gdbr-check:type = (extern "stdcall" fn(), usize) // gdb-command:whatis rust_fn_with_return_value -// gdb-check:type = struct (fn(f64) -> usize, usize) +// gdbg-check:type = struct (fn(f64) -> usize, usize) +// gdbr-check:type = (fn(f64) -> usize, usize) // gdb-command:whatis extern_c_fn_with_return_value -// gdb-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) +// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) +// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize) // gdb-command:whatis unsafe_fn_with_return_value -// gdb-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) +// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) +// gdbr-check:type = (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) // gdb-command:whatis extern_stdcall_fn_with_return_value -// gdb-check:type = struct (extern "stdcall" fn(Box) -> usize, usize) +// gdbg-check:type = struct (extern "stdcall" fn(Box) -> usize, usize) +// gdbr-check:type = (extern "stdcall" fn(Box) -> usize, usize) // gdb-command:whatis generic_function_int -// gdb-check:type = struct (fn(isize) -> isize, usize) +// gdbg-check:type = struct (fn(isize) -> isize, usize) +// gdbr-check:type = (fn(isize) -> isize, usize) // gdb-command:whatis generic_function_struct3 -// gdb-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) // gdb-command:whatis variadic_function -// gdb-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) // CLOSURES // gdb-command:whatis closure1 -// gdb-check:type = struct (closure, usize) +// gdbg-check:type = struct (closure, usize) +// gdbr-check:type = (closure, usize) // gdb-command:whatis closure2 -// gdb-check:type = struct (closure, usize) +// gdbg-check:type = struct (closure, usize) +// gdbr-check:type = (closure, usize) #![feature(box_syntax)] #![allow(unused_variables)] diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs index 319927c979bf8..26e73a08ea137 100644 --- a/src/test/debuginfo/union-smoke.rs +++ b/src/test/debuginfo/union-smoke.rs @@ -16,9 +16,11 @@ // gdb-command:run // gdb-command:print u -// gdb-check:$1 = {a = {__0 = 2 '\002', __1 = 2 '\002'}, b = 514} +// gdbg-check:$1 = {a = {__0 = 2 '\002', __1 = 2 '\002'}, b = 514} +// gdbr-check:$1 = union_smoke::U {a: (2, 2), b: 514} // gdb-command:print union_smoke::SU -// gdb-check:$2 = {a = {__0 = 1 '\001', __1 = 1 '\001'}, b = 257} +// gdbg-check:$2 = {a = {__0 = 1 '\001', __1 = 1 '\001'}, b = 257} +// gdbr-check:$2 = union_smoke::U {a: (1, 1), b: 257} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index bbf13ec756ad8..e882544b802bd 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print *the_a -// gdb-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$1 = unique_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b -// gdb-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbr-check:$2 = unique_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant -// gdb-check:$3 = {{__0 = 123234}} +// gdbg-check:$3 = {{__0 = 123234}} +// gdbr-check:$3 = unique_enum::Univariant::TheOnlyCase(123234) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 7090377e5db1b..b9a1d73b6d869 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -21,9 +21,11 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdb-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$3 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$4 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 // gdb-command:print closure_local @@ -35,9 +37,11 @@ // gdb-command:print constant // gdb-check:$8 = 2 // gdb-command:print a_struct -// gdb-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$9 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$10 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$10 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$10 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$11 = 6 // gdb-command:print closure_local diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index b415546faeac7..120bbdd7ba902 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -19,7 +19,8 @@ // gdb-command:print constant // gdb-check:$1 = 1 // gdb-command:print a_struct -// gdb-check:$2 = {a = -2, b = 3.5, c = 4} +// gdbg-check:$2 = {a = -2, b = 3.5, c = 4} +// gdbr-check:$2 = var_captured_in_sendable_closure::Struct {a: -2, b: 3.5, c: 4} // gdb-command:print *owned // gdb-check:$3 = 5 // gdb-command:continue diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index e60f964dd095e..c795a095b9769 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -21,9 +21,11 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdb-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$3 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$4 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 @@ -34,9 +36,11 @@ // gdb-command:print constant // gdb-check:$7 = 2 // gdb-command:print a_struct -// gdb-check:$8 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$8 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$8 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$9 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$10 = 6 diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs index cdb5bc4ecfb6e..5553f8427e90f 100644 --- a/src/test/debuginfo/vec-slices.rs +++ b/src/test/debuginfo/vec-slices.rs @@ -21,42 +21,57 @@ // gdb-command:print singleton.length // gdb-check:$2 = 1 -// gdb-command:print *((int64_t[1]*)(singleton.data_ptr)) -// gdb-check:$3 = {1} +// gdbg-command:print *((int64_t[1]*)(singleton.data_ptr)) +// gdbr-command:print *(singleton.data_ptr as &[i64; 1]) +// gdbg-check:$3 = {1} +// gdbr-check:$3 = [1] // gdb-command:print multiple.length // gdb-check:$4 = 4 -// gdb-command:print *((int64_t[4]*)(multiple.data_ptr)) -// gdb-check:$5 = {2, 3, 4, 5} +// gdbg-command:print *((int64_t[4]*)(multiple.data_ptr)) +// gdbr-command:print *(multiple.data_ptr as &[i64; 4]) +// gdbg-check:$5 = {2, 3, 4, 5} +// gdbr-check:$5 = [2, 3, 4, 5] // gdb-command:print slice_of_slice.length // gdb-check:$6 = 2 -// gdb-command:print *((int64_t[2]*)(slice_of_slice.data_ptr)) -// gdb-check:$7 = {3, 4} +// gdbg-command:print *((int64_t[2]*)(slice_of_slice.data_ptr)) +// gdbr-command:print *(slice_of_slice.data_ptr as &[i64; 2]) +// gdbg-check:$7 = {3, 4} +// gdbr-check:$7 = [3, 4] // gdb-command:print padded_tuple.length // gdb-check:$8 = 2 // gdb-command:print padded_tuple.data_ptr[0] -// gdb-check:$9 = {__0 = 6, __1 = 7} +// gdbg-check:$9 = {__0 = 6, __1 = 7} +// gdbr-check:$9 = (6, 7) // gdb-command:print padded_tuple.data_ptr[1] -// gdb-check:$10 = {__0 = 8, __1 = 9} +// gdbg-check:$10 = {__0 = 8, __1 = 9} +// gdbr-check:$10 = (8, 9) // gdb-command:print padded_struct.length // gdb-check:$11 = 2 // gdb-command:print padded_struct.data_ptr[0] -// gdb-check:$12 = {x = 10, y = 11, z = 12} +// gdbg-check:$12 = {x = 10, y = 11, z = 12} +// gdbr-check:$12 = vec_slices::AStruct {x: 10, y: 11, z: 12} // gdb-command:print padded_struct.data_ptr[1] -// gdb-check:$13 = {x = 13, y = 14, z = 15} +// gdbg-check:$13 = {x = 13, y = 14, z = 15} +// gdbr-check:$13 = vec_slices::AStruct {x: 13, y: 14, z: 15} -// gdb-command:print 'vec_slices::MUT_VECT_SLICE'.length +// gdbg-command:print 'vec_slices::MUT_VECT_SLICE'.length +// gdbr-command:print MUT_VECT_SLICE.length // gdb-check:$14 = 2 -// gdb-command:print *((int64_t[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) -// gdb-check:$15 = {64, 65} +// gdbg-command:print *((int64_t[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) +// gdbr-command:print *(MUT_VECT_SLICE.data_ptr as &[i64; 2]) +// gdbg-check:$15 = {64, 65} +// gdbr-check:$15 = [64, 65] //gdb-command:print mut_slice.length //gdb-check:$16 = 5 -//gdb-command:print *((int64_t[5]*)(mut_slice.data_ptr)) -//gdb-check:$17 = {1, 2, 3, 4, 5} +//gdbg-command:print *((int64_t[5]*)(mut_slice.data_ptr)) +//gdbr-command:print *(mut_slice.data_ptr as &[i64; 5]) +//gdbg-check:$17 = {1, 2, 3, 4, 5} +//gdbr-check:$17 = [1, 2, 3, 4, 5] // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs index c9827a02fc759..fbb33b94d9577 100644 --- a/src/test/debuginfo/vec.rs +++ b/src/test/debuginfo/vec.rs @@ -16,9 +16,11 @@ // gdb-command:run // gdb-command:print a -// gdb-check:$1 = {1, 2, 3} +// gdbg-check:$1 = {1, 2, 3} +// gdbr-check:$1 = [1, 2, 3] // gdb-command:print vec::VECT -// gdb-check:$2 = {4, 5, 6} +// gdbg-check:$2 = {4, 5, 6} +// gdbr-check:$2 = [4, 5, 6] // === LLDB TESTS ================================================================================== From 6554fb0d8d5d794db7a7532a5edd16eb28777a48 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 29 Oct 2016 14:29:18 +0200 Subject: [PATCH 05/41] add gdb_native_rust config to compiletest --- src/tools/compiletest/src/common.rs | 3 ++ src/tools/compiletest/src/main.rs | 1 + src/tools/compiletest/src/runtest.rs | 48 ++++++++++++++++++---------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 81cb927f26b02..b6b98d796e241 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -149,6 +149,9 @@ pub struct Config { // Version of GDB pub gdb_version: Option, + // Whether GDB has native rust support + pub gdb_native_rust: bool, + // Version of LLDB pub lldb_version: Option, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index e6efd45cad186..c0557d8ff107d 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -172,6 +172,7 @@ pub fn parse_config(args: Vec ) -> Config { target: opt_str2(matches.opt_str("target")), host: opt_str2(matches.opt_str("host")), gdb_version: extract_gdb_version(matches.opt_str("gdb-version")), + gdb_native_rust: false, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), android_cross_path: opt_path(matches, "android-cross-path"), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e10420bf291e7..f6cd56423fbc7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -430,11 +430,23 @@ actual:\n\ } fn run_debuginfo_gdb_test_no_opt(&self) { + let prefixes = if self.config.gdb_native_rust { + // GDB with Rust + static PREFIXES: &'static [&'static str] = &["gdb", "gdbr"]; + println!("NOTE: compiletest thinks it is using GDB with native rust support"); + PREFIXES + } else { + // Generic GDB + static PREFIXES: &'static [&'static str] = &["gdb", "gdbg"]; + println!("NOTE: compiletest thinks it is using GDB without native rust support"); + PREFIXES + }; + let DebuggerCommands { commands, check_lines, breakpoint_lines - } = self.parse_debugger_commands("gdb"); + } = self.parse_debugger_commands(prefixes); let mut cmds = commands.join("\n"); // compile test file (it should have 'compile-flags:-g' in the header) @@ -731,7 +743,7 @@ actual:\n\ check_lines, breakpoint_lines, .. - } = self.parse_debugger_commands("lldb"); + } = self.parse_debugger_commands(&["lldb"]); // Write debugger script: // We don't want to hang when calling `quit` while the process is still running @@ -826,9 +838,11 @@ actual:\n\ } } - fn parse_debugger_commands(&self, debugger_prefix: &str) -> DebuggerCommands { - let command_directive = format!("{}-command", debugger_prefix); - let check_directive = format!("{}-check", debugger_prefix); + fn parse_debugger_commands(&self, debugger_prefixes: &[&str]) -> DebuggerCommands { + let directives = debugger_prefixes.iter().map(|prefix| ( + format!("{}-command", prefix), + format!("{}-check", prefix), + )).collect::>(); let mut breakpoint_lines = vec!(); let mut commands = vec!(); @@ -842,17 +856,19 @@ actual:\n\ breakpoint_lines.push(counter); } - header::parse_name_value_directive( - &line, - &command_directive).map(|cmd| { - commands.push(cmd) - }); - - header::parse_name_value_directive( - &line, - &check_directive).map(|cmd| { - check_lines.push(cmd) - }); + for &(ref command_directive, ref check_directive) in &directives { + header::parse_name_value_directive( + &line, + &command_directive).map(|cmd| { + commands.push(cmd) + }); + + header::parse_name_value_directive( + &line, + &check_directive).map(|cmd| { + check_lines.push(cmd) + }); + } } Err(e) => { self.fatal(&format!("Error while parsing debugger commands: {}", e)) From dce460028e9c21ebadb28f6744d4b10bf0e8d501 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 29 Oct 2016 20:11:53 +0200 Subject: [PATCH 06/41] detect gdb version & rust support in compiletest --- configure | 7 -- mk/tests.mk | 2 +- src/bootstrap/check.rs | 4 +- src/bootstrap/config.rs | 6 + src/bootstrap/config.toml.example | 3 + src/bootstrap/lib.rs | 2 - src/bootstrap/sanity.rs | 7 +- src/tools/compiletest/src/common.rs | 7 +- src/tools/compiletest/src/header.rs | 23 +--- src/tools/compiletest/src/main.rs | 176 +++++++++++++++++++++------ src/tools/compiletest/src/runtest.rs | 32 ++--- 11 files changed, 180 insertions(+), 89 deletions(-) diff --git a/configure b/configure index 2bc8c72e3ea1c..dab44c4a82992 100755 --- a/configure +++ b/configure @@ -862,13 +862,6 @@ then fi fi -if [ -n "$CFG_GDB" ] -then - # Store GDB's version - CFG_GDB_VERSION=$($CFG_GDB --version 2>/dev/null | head -1) - putvar CFG_GDB_VERSION -fi - if [ -n "$CFG_LLDB" ] then # Store LLDB's version diff --git a/mk/tests.mk b/mk/tests.mk index 1957c989eb0d4..f3d8f0387bbd6 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -648,7 +648,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) = \ --host $(3) \ --docck-python $$(CFG_PYTHON) \ --lldb-python $$(CFG_LLDB_PYTHON) \ - --gdb-version="$(CFG_GDB_VERSION)" \ + --gdb="$(CFG_GDB)" \ --lldb-version="$(CFG_LLDB_VERSION)" \ --llvm-version="$$(LLVM_VERSION_$(3))" \ --android-cross-path=$(CFG_ARM_LINUX_ANDROIDEABI_NDK) \ diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index af76a49fed045..50a2337b30783 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -168,8 +168,8 @@ pub fn compiletest(build: &Build, cmd.arg("--lldb-python").arg(python_default); } - if let Some(ref vers) = build.gdb_version { - cmd.arg("--gdb-version").arg(vers); + if let Some(ref gdb) = build.config.gdb { + cmd.arg("--gdb").arg(gdb); } if let Some(ref vers) = build.lldb_version { cmd.arg("--lldb-version").arg(vers); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8c0ad1ccf825f..0948a7c130e5f 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -85,6 +85,7 @@ pub struct Config { pub mandir: Option, pub codegen_tests: bool, pub nodejs: Option, + pub gdb: Option, } /// Per-target configuration stored in the global configuration structure. @@ -122,6 +123,7 @@ struct Build { compiler_docs: Option, docs: Option, submodules: Option, + gdb: Option, } /// TOML representation of how the LLVM build is configured. @@ -226,6 +228,7 @@ impl Config { } config.rustc = build.rustc.map(PathBuf::from); config.cargo = build.cargo.map(PathBuf::from); + config.gdb = build.gdb.map(PathBuf::from); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs, build.docs); set(&mut config.submodules, build.submodules); @@ -392,6 +395,9 @@ impl Config { "CFG_DEFAULT_LINKER" if value.len() > 0 => { self.rustc_default_linker = Some(value.to_string()); } + "CFG_GDB" if value.len() > 0 => { + self.gdb = Some(PathBuf::from(value)); + } "CFG_RELEASE_CHANNEL" => { self.channel = value.to_string(); } diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index b4730c003d646..1289cdba59577 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -79,6 +79,9 @@ # Indicate whether submodules are managed and updated automatically. #submodules = true +# The path to (or name of) the GDB executable to use +#gdb = "gdb" + # ============================================================================= # Options for compiling Rust code itself # ============================================================================= diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7c5a0c7373f88..e99e088bffe36 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -123,7 +123,6 @@ pub struct Build { bootstrap_key_stage0: String, // Probed tools at runtime - gdb_version: Option, lldb_version: Option, lldb_python_dir: Option, @@ -196,7 +195,6 @@ impl Build { package_vers: String::new(), cc: HashMap::new(), cxx: HashMap::new(), - gdb_version: None, lldb_version: None, lldb_python_dir: None, } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 969cd70fd57eb..cc1b7136d475f 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -92,6 +92,12 @@ pub fn check(build: &mut Build) { need_cmd(s.as_ref()); } + if let Some(ref gdb) = build.config.gdb { + need_cmd(gdb.as_ref()); + } else { + build.config.gdb = have_cmd("gdb".as_ref()); + } + // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. for target in build.config.target.iter() { @@ -198,7 +204,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake .to_string() }) }; - build.gdb_version = run(Command::new("gdb").arg("--version")).ok(); build.lldb_version = run(Command::new("lldb").arg("--version")).ok(); if build.lldb_version.is_some() { build.lldb_python_dir = run(Command::new("lldb").arg("-P")).ok(); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index b6b98d796e241..34f3837d8bbb0 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -146,8 +146,11 @@ pub struct Config { // Host triple for the compiler being invoked pub host: String, - // Version of GDB - pub gdb_version: Option, + // Path to / name of the GDB executable + pub gdb: Option, + + // Version of GDB, encoded as ((major * 1000) + minor) * 1000 + patch + pub gdb_version: Option, // Whether GDB has native rust support pub gdb_native_rust: bool, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 503a851676925..e57c9949b1c57 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -18,6 +18,8 @@ use common::Config; use common; use util; +use extract_gdb_version; + /// Properties which must be known very early, before actually running /// the test. pub struct EarlyProps { @@ -75,7 +77,7 @@ impl EarlyProps { return true; } - if let Some(ref actual_version) = config.gdb_version { + if let Some(actual_version) = config.gdb_version { if line.contains("min-gdb-version") { let min_version = line.trim() .split(' ') @@ -83,7 +85,7 @@ impl EarlyProps { .expect("Malformed GDB version directive"); // Ignore if actual version is smaller the minimum required // version - gdb_version_to_int(actual_version) < gdb_version_to_int(min_version) + actual_version < extract_gdb_version(min_version).unwrap() } else { false } @@ -464,23 +466,6 @@ pub fn parse_name_value_directive(line: &str, directive: &str) -> Option } } -pub fn gdb_version_to_int(version_string: &str) -> isize { - let error_string = format!("Encountered GDB version string with unexpected format: {}", - version_string); - let error_string = error_string; - - let components: Vec<&str> = version_string.trim().split('.').collect(); - - if components.len() != 2 { - panic!("{}", error_string); - } - - let major: isize = components[0].parse().ok().expect(&error_string); - let minor: isize = components[1].parse().ok().expect(&error_string); - - return major * 1000 + minor; -} - pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index c0557d8ff107d..d6e64cc1752a9 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -12,6 +12,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] +#![feature(static_in_const)] #![feature(test)] #![feature(libc)] @@ -35,6 +36,7 @@ use std::ffi::OsString; use std::fs; use std::io; use std::path::{Path, PathBuf}; +use std::process::Command; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode}; @@ -98,7 +100,7 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "logfile", "file to log test execution to", "FILE"), optopt("", "target", "the target to build for", "TARGET"), optopt("", "host", "the host to build for", "HOST"), - optopt("", "gdb-version", "the version of GDB used", "VERSION STRING"), + optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH"), optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING"), optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING"), optopt("", "android-cross-path", "Android NDK standalone path", "PATH"), @@ -149,6 +151,8 @@ pub fn parse_config(args: Vec ) -> Config { } } + let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb")); + Config { compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), @@ -171,8 +175,9 @@ pub fn parse_config(args: Vec ) -> Config { target_rustcflags: matches.opt_str("target-rustcflags"), target: opt_str2(matches.opt_str("target")), host: opt_str2(matches.opt_str("host")), - gdb_version: extract_gdb_version(matches.opt_str("gdb-version")), - gdb_native_rust: false, + gdb: gdb, + gdb_version: gdb_version, + gdb_native_rust: gdb_native_rust, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), android_cross_path: opt_path(matches, "android-cross-path"), @@ -471,44 +476,96 @@ pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn })) } -fn extract_gdb_version(full_version_line: Option) -> Option { - match full_version_line { - Some(ref full_version_line) - if !full_version_line.trim().is_empty() => { - let full_version_line = full_version_line.trim(); +/// Returns (Path to GDB, GDB Version, GDB has Rust Support) +fn analyze_gdb(gdb: Option) -> (Option, Option, bool) { + #[cfg(not(windows))] + const GDB_FALLBACK: &str = "gdb"; + #[cfg(windows)] + const GDB_FALLBACK: &str = "gdb.exe"; - // used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)" - for (pos, c) in full_version_line.char_indices() { - if !c.is_digit(10) { - continue - } - if pos + 2 >= full_version_line.len() { - continue - } - if full_version_line[pos + 1..].chars().next().unwrap() != '.' { - continue - } - if !full_version_line[pos + 2..].chars().next().unwrap().is_digit(10) { - continue - } - if pos > 0 && full_version_line[..pos].chars().next_back() - .unwrap().is_digit(10) { - continue - } - let mut end = pos + 3; - while end < full_version_line.len() && - full_version_line[end..].chars().next() - .unwrap().is_digit(10) { - end += 1; - } - return Some(full_version_line[pos..end].to_owned()); - } - println!("Could not extract GDB version from line '{}'", - full_version_line); - None - }, - _ => None + const MIN_GDB_WITH_RUST: u32 = 7011010; + + let gdb = match gdb { + None => GDB_FALLBACK, + Some(ref s) if s.is_empty() => GDB_FALLBACK, // may be empty if configure found no gdb + Some(ref s) => s, + }; + + let version_line = Command::new(gdb).arg("--version").output().map(|output| { + String::from_utf8_lossy(&output.stdout).lines().next().unwrap().to_string() + }).ok(); + + let version = match version_line { + Some(line) => extract_gdb_version(&line), + None => return (None, None, false), + }; + + let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST); + + return (Some(gdb.to_owned()), version, gdb_native_rust); +} + +fn extract_gdb_version(full_version_line: &str) -> Option { + let full_version_line = full_version_line.trim(); + + // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both + // of the ? sections being optional + + // We will parse up to 3 digits for minor and patch, ignoring the date + // We limit major to 1 digit, otherwise, on openSUSE, we parse the openSUSE version + + // don't start parsing in the middle of a number + let mut prev_was_digit = false; + for (pos, c) in full_version_line.char_indices() { + if prev_was_digit || !c.is_digit(10) { + prev_was_digit = c.is_digit(10); + continue + } + + prev_was_digit = true; + + let line = &full_version_line[pos..]; + + let next_split = match line.find(|c: char| !c.is_digit(10)) { + Some(idx) => idx, + None => continue, // no minor version + }; + + if line.as_bytes()[next_split] != b'.' { + continue; // no minor version + } + + let major = &line[..next_split]; + let line = &line[next_split + 1..]; + + let (minor, patch) = match line.find(|c: char| !c.is_digit(10)) { + Some(idx) => if line.as_bytes()[idx] == b'.' { + let patch = &line[idx + 1..]; + + let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or(patch.len()); + let patch = &patch[..patch_len]; + let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; + + (&line[..idx], patch) + } else { + (&line[..idx], None) + }, + None => (line, None), + }; + + if major.len() != 1 || minor.is_empty() { + continue; + } + + let major: u32 = major.parse().unwrap(); + let minor: u32 = minor.parse().unwrap(); + let patch: u32 = patch.unwrap_or("0").parse().unwrap(); + + return Some(((major * 1000) + minor) * 1000 + patch); } + + println!("Could not extract GDB version from line '{}'", full_version_line); + None } fn extract_lldb_version(full_version_line: Option) -> Option { @@ -554,3 +611,44 @@ fn extract_lldb_version(full_version_line: Option) -> Option { fn is_blacklisted_lldb_version(version: &str) -> bool { version == "350" } + +#[test] +fn test_extract_gdb_version() { + macro_rules! test { ($($expectation:tt: $input:tt,)*) => {{$( + assert_eq!(extract_gdb_version($input), Some($expectation)); + )*}}} + + test! { + 7000001: "GNU gdb (GDB) CentOS (7.0.1-45.el5.centos)", + + 7002000: "GNU gdb (GDB) Red Hat Enterprise Linux (7.2-90.el6)", + + 7004000: "GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04", + 7004001: "GNU gdb (GDB) 7.4.1-debian", + + 7006001: "GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7", + + 7007001: "GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1", + 7007001: "GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1", + 7007001: "GNU gdb (GDB) Fedora 7.7.1-21.fc20", + + 7008000: "GNU gdb (GDB; openSUSE 13.2) 7.8", + 7009001: "GNU gdb (GDB) Fedora 7.9.1-20.fc22", + 7010001: "GNU gdb (GDB) Fedora 7.10.1-31.fc23", + + 7011000: "GNU gdb (Ubuntu 7.11-0ubuntu1) 7.11", + 7011001: "GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1", + 7011001: "GNU gdb (Debian 7.11.1-2) 7.11.1", + 7011001: "GNU gdb (GDB) Fedora 7.11.1-86.fc24", + 7011001: "GNU gdb (GDB; openSUSE Leap 42.1) 7.11.1", + 7011001: "GNU gdb (GDB; openSUSE Tumbleweed) 7.11.1", + + 7011090: "7.11.90", + 7011090: "GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu1) 7.11.90.20161005-git", + + 7012000: "7.12", + 7012000: "GNU gdb (GDB) 7.12", + 7012000: "GNU gdb (GDB) 7.12.20161027-git", + 7012050: "GNU gdb (GDB) 7.12.50.20161027-git", + } +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6cd56423fbc7..3c6903ac21d51 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -32,6 +32,8 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Output, ExitStatus}; use std::str; +use extract_gdb_version; + pub fn run(config: Config, testpaths: &TestPaths) { match &*config.target { @@ -44,6 +46,10 @@ pub fn run(config: Config, testpaths: &TestPaths) { _=> { } } + if config.mode == DebugInfoGdb && config.gdb.is_none() { + panic!("gdb not available but debuginfo gdb debuginfo test requested"); + } + if config.verbose { // We're going to be dumping a lot of info. Start on a new line. print!("\n\n"); @@ -598,19 +604,18 @@ actual:\n\ script_str.push_str("show version\n"); match self.config.gdb_version { - Some(ref version) => { + Some(version) => { println!("NOTE: compiletest thinks it is using GDB version {}", version); - if header::gdb_version_to_int(version) > - header::gdb_version_to_int("7.4") { - // Add the directory containing the pretty printers to - // GDB's script auto loading safe path - script_str.push_str( - &format!("add-auto-load-safe-path {}\n", - rust_pp_module_abs_path.replace(r"\", r"\\")) - ); - } + if version > extract_gdb_version("7.4").unwrap() { + // Add the directory containing the pretty printers to + // GDB's script auto loading safe path + script_str.push_str( + &format!("add-auto-load-safe-path {}\n", + rust_pp_module_abs_path.replace(r"\", r"\\")) + ); + } } _ => { println!("NOTE: compiletest does not know which version of \ @@ -645,11 +650,6 @@ actual:\n\ debug!("script_str = {}", script_str); self.dump_output_file(&script_str, "debugger.script"); - // run debugger script with gdb - fn debugger() -> &'static str { - if cfg!(windows) {"gdb.exe"} else {"gdb"} - } - let debugger_script = self.make_out_name("debugger.script"); // FIXME (#9639): This needs to handle non-utf8 paths @@ -660,7 +660,7 @@ actual:\n\ format!("-command={}", debugger_script.to_str().unwrap())); let proc_args = ProcArgs { - prog: debugger().to_owned(), + prog: self.config.gdb.as_ref().unwrap().to_owned(), args: debugger_opts, }; From 5cb5c85152e2a8b7f3480a46f4619b572f162056 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Mon, 31 Oct 2016 21:00:32 +0100 Subject: [PATCH 07/41] rustbuild+configure: improve bin/exe joining --- src/bootstrap/config.rs | 8 +++++--- src/bootstrap/util.rs | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0948a7c130e5f..9f6e91c85661c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -23,6 +23,7 @@ use std::process; use num_cpus; use rustc_serialize::Decodable; use toml::{Parser, Decoder, Value}; +use util::push_exe_path; /// Global configuration for the entire build and/or bootstrap. /// @@ -417,7 +418,7 @@ impl Config { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); let root = PathBuf::from(value); - target.llvm_config = Some(root.join("bin/llvm-config")); + target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) @@ -449,8 +450,9 @@ impl Config { target.ndk = Some(PathBuf::from(value)); } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { - self.rustc = Some(PathBuf::from(value).join("bin/rustc")); - self.cargo = Some(PathBuf::from(value).join("bin/cargo")); + let path = PathBuf::from(value); + self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); + self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); } _ => {} } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6c0a32a54d919..84ba03b2502e2 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -172,3 +172,21 @@ pub fn dylib_path() -> Vec { env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new())) .collect() } + +/// `push` all components to `buf`. On windows, append `.exe` to the last component. +pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf { + let (&file, components) = components.split_last().expect("at least one component required"); + let mut file = file.to_owned(); + + if cfg!(windows) { + file.push_str(".exe"); + } + + for c in components { + buf.push(c); + } + + buf.push(file); + + buf +} From f7107f32c2fabef7a5b33c514d9f0310c96492d0 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Mon, 31 Oct 2016 21:06:27 +0100 Subject: [PATCH 08/41] rustbuild+configure: convert unix style paths on windows --- src/bootstrap/config.rs | 51 ++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 9f6e91c85661c..2b1d8e67dd8f2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -358,37 +358,37 @@ impl Config { .collect(); } "CFG_MUSL_ROOT" if value.len() > 0 => { - self.musl_root = Some(PathBuf::from(value)); + self.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => { let target = "x86_64-unknown-linux-musl".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_I686" if value.len() > 0 => { let target = "i686-unknown-linux-musl".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARM" if value.len() > 0 => { let target = "arm-unknown-linux-musleabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => { let target = "arm-unknown-linux-musleabihf".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => { let target = "armv7-unknown-linux-musleabihf".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_DEFAULT_AR" if value.len() > 0 => { self.rustc_default_ar = Some(value.to_string()); @@ -397,7 +397,7 @@ impl Config { self.rustc_default_linker = Some(value.to_string()); } "CFG_GDB" if value.len() > 0 => { - self.gdb = Some(PathBuf::from(value)); + self.gdb = Some(parse_configure_path(value)); } "CFG_RELEASE_CHANNEL" => { self.channel = value.to_string(); @@ -417,40 +417,40 @@ impl Config { "CFG_LLVM_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - let root = PathBuf::from(value); + let root = parse_configure_path(value); target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - target.jemalloc = Some(PathBuf::from(value)); + target.jemalloc = Some(parse_configure_path(value)); } "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "arm-linux-androideabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "armv7-linux-androideabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { let target = "i686-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { let target = "aarch64-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { - let path = PathBuf::from(value); + let path = parse_configure_path(value); self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); } @@ -460,6 +460,29 @@ impl Config { } } +#[cfg(not(windows))] +fn parse_configure_path(path: &str) -> PathBuf { + path.into() +} + +#[cfg(windows)] +fn parse_configure_path(path: &str) -> PathBuf { + // on windows, configure produces unix style paths e.g. /c/some/path but we + // only want real windows paths + + use build_helper; + + // '/' is invalid in windows paths, so we can detect unix paths by the presence of it + if !path.contains('/') { + return path.into(); + } + + let win_path = build_helper::output(Command::new("cygpath").arg("-w").arg(path)); + let win_path = win_path.trim(); + + win_path.into() +} + fn set(field: &mut T, val: Option) { if let Some(v) = val { *field = v; From 6a8d131e5df60ba48c2382f9a3027b2c75c14e18 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 27 Oct 2016 04:52:10 +0300 Subject: [PATCH 09/41] rustc: make all read access to tcx.tables go through a method. --- src/librustc/cfg/construct.rs | 6 +- src/librustc/middle/dead.rs | 8 +- src/librustc/middle/effect.rs | 4 +- src/librustc/middle/intrinsicck.rs | 2 +- src/librustc/middle/liveness.rs | 12 +-- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/stability.rs | 6 +- src/librustc/ty/context.rs | 69 +++++++++++++-- src/librustc/ty/mod.rs | 73 ++-------------- .../borrowck/gather_loans/gather_moves.rs | 2 +- src/librustc_const_eval/check_match.rs | 6 +- src/librustc_const_eval/eval.rs | 14 +-- src/librustc_const_eval/pattern.rs | 17 ++-- src/librustc_driver/pretty.rs | 2 +- src/librustc_lint/builtin.rs | 35 ++++---- src/librustc_lint/types.rs | 12 +-- src/librustc_lint/unused.rs | 4 +- src/librustc_metadata/astencode.rs | 6 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/hair/cx/block.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 86 +++++++++---------- src/librustc_mir/mir_map.rs | 4 +- src/librustc_passes/consts.rs | 19 ++-- src/librustc_privacy/lib.rs | 8 +- src/librustc_save_analysis/dump_visitor.rs | 11 ++- src/librustc_save_analysis/lib.rs | 4 +- src/librustc_trans/callee.rs | 2 +- src/librustc_trans/collector.rs | 5 +- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/mod.rs | 6 +- src/librustc_typeck/check/wfcheck.rs | 6 +- src/librustc_typeck/check/writeback.rs | 2 +- src/librustc_typeck/lib.rs | 4 +- 35 files changed, 219 insertions(+), 230 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 1b2976b7435d8..8c7805b5450e3 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -311,11 +311,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprIndex(ref l, ref r) | - hir::ExprBinary(_, ref l, ref r) if self.tcx.is_method_call(expr.id) => { + hir::ExprBinary(_, ref l, ref r) if self.tcx.tables().is_method_call(expr.id) => { self.call(expr, pred, &l, Some(&**r).into_iter()) } - hir::ExprUnary(_, ref e) if self.tcx.is_method_call(expr.id) => { + hir::ExprUnary(_, ref e) if self.tcx.tables().is_method_call(expr.id) => { self.call(expr, pred, &e, None::.iter()) } @@ -372,7 +372,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { func_or_rcvr: &hir::Expr, args: I) -> CFGIndex { let method_call = ty::MethodCall::expr(call_expr.id); - let fn_ty = match self.tcx.tables.borrow().method_map.get(&method_call) { + let fn_ty = match self.tcx.tables().method_map.get(&method_call) { Some(method) => method.ty, None => self.tcx.expr_ty_adjusted(func_or_rcvr) }; diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index dc634b08784a4..daa32fc760faa 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -92,7 +92,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { match def { Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_) if self.tcx.trait_of_item(def.def_id()).is_some() => { - if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) { + if let Some(substs) = self.tcx.tables().item_substs.get(&id) { if let ty::TyAdt(tyid, _) = substs.substs.type_at(0).sty { self.check_def_id(tyid.did); } @@ -123,7 +123,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_method(&mut self, id: ast::NodeId) { let method_call = ty::MethodCall::expr(id); - let method = self.tcx.tables.borrow().method_map[&method_call]; + let method = self.tcx.tables().method_map[&method_call]; self.check_def_id(method.def_id); } @@ -148,7 +148,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, pats: &[codemap::Spanned]) { - let variant = match self.tcx.node_id_to_type(lhs.id).sty { + let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty { ty::TyAdt(adt, _) => { adt.variant_of_def(self.tcx.expect_def(lhs.id)) } @@ -433,7 +433,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { } fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool { - let field_type = self.tcx.node_id_to_type(field.id); + let field_type = self.tcx.tables().node_id_to_type(field.id); let is_marker_field = match field_type.ty_to_def_id() { Some(def_id) => self.tcx.lang_items.items().iter().any(|item| *item == Some(def_id)), _ => false diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 2a75b6620fd61..8964405fb7f77 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -159,7 +159,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = MethodCall::expr(expr.id); - let base_type = self.tcx.tables.borrow().method_map[&method_call].ty; + let base_type = self.tcx.tables().method_map[&method_call].ty; debug!("effect: method call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -214,7 +214,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &hir::Pat) { if let PatKind::Struct(_, ref fields, _) = pat.node { - if let ty::TyAdt(adt, ..) = self.tcx.pat_ty(pat).sty { + if let ty::TyAdt(adt, ..) = self.tcx.tables().pat_ty(pat).sty { if adt.is_union() { for field in fields { self.require_unsafe(field.span, "matching on union field"); diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 1acd0fb0f79c0..57503398cfe57 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> { if let hir::ExprPath(..) = expr.node { match self.infcx.tcx.expect_def(expr.id) { Def::Fn(did) if self.def_id_is_transmute(did) => { - let typ = self.infcx.tcx.node_id_to_type(expr.id); + let typ = self.infcx.tcx.tables().node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { let from = bare_fn_ty.sig.0.inputs[0]; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 79396b9ca4dab..e544ddc402b5f 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1081,7 +1081,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAssignOp(_, ref l, ref r) => { // an overloaded assign op is like a method call - if self.ir.tcx.is_method_call(expr.id) { + if self.ir.tcx.tables().is_method_call(expr.id) { let succ = self.propagate_through_expr(&l, succ); self.propagate_through_expr(&r, succ) } else { @@ -1113,7 +1113,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprCall(ref f, ref args) => { // FIXME(canndrew): This is_never should really be an is_uninhabited - let diverges = !self.ir.tcx.is_method_call(expr.id) && + let diverges = !self.ir.tcx.tables().is_method_call(expr.id) && self.ir.tcx.expr_ty_adjusted(&f).fn_ret().0.is_never(); let succ = if diverges { self.s.exit_ln @@ -1126,7 +1126,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprMethodCall(.., ref args) => { let method_call = ty::MethodCall::expr(expr.id); - let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty; + let method_ty = self.ir.tcx.tables().method_map[&method_call].ty; // FIXME(canndrew): This is_never should really be an is_uninhabited let succ = if method_ty.fn_ret().0.is_never() { self.s.exit_ln @@ -1409,7 +1409,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { } hir::ExprAssignOp(_, ref l, _) => { - if !this.ir.tcx.is_method_call(expr.id) { + if !this.ir.tcx.tables().is_method_call(expr.id) { this.check_lvalue(&l); } @@ -1459,7 +1459,7 @@ fn check_fn(_v: &Liveness, impl<'a, 'tcx> Liveness<'a, 'tcx> { fn fn_ret(&self, id: NodeId) -> ty::Binder> { - let fn_ty = self.ir.tcx.node_id_to_type(id); + let fn_ty = self.ir.tcx.tables().node_id_to_type(id); match fn_ty.sty { ty::TyClosure(closure_def_id, substs) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), @@ -1502,7 +1502,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { None if !body.stmts.is_empty() => match body.stmts.last().unwrap().node { hir::StmtSemi(ref e, _) => { - self.ir.tcx.expr_ty(&e) == fn_ret + self.ir.tcx.tables().expr_ty(&e) == fn_ret }, _ => false }, diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index a476d0f6f30a6..1a50d7aa0adc7 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -116,7 +116,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { } hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let def_id = self.tcx.tables().method_map[&method_call].def_id; // Mark the trait item (and, possibly, its default impl) as reachable // Or mark inherent impl item as reachable diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5192575972b02..a03cf708e8c19 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -555,7 +555,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, hir::ExprMethodCall(i, ..) => { span = i.span; let method_call = ty::MethodCall::expr(e.id); - tcx.tables.borrow().method_map[&method_call].def_id + tcx.tables().method_map[&method_call].def_id } hir::ExprField(ref base_e, ref field) => { span = field.span; @@ -580,7 +580,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, } } hir::ExprStruct(_, ref expr_fields, _) => { - match tcx.expr_ty(e).sty { + match tcx.tables().expr_ty(e).sty { ty::TyAdt(adt, ..) => match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { // check the stability of each field that appears @@ -637,7 +637,7 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat, debug!("check_pat(pat = {:?})", pat); if is_internal(tcx, pat.span) { return; } - let v = match tcx.pat_ty_opt(pat).map(|ty| &ty.sty) { + let v = match tcx.tables().pat_ty_opt(pat).map(|ty| &ty.sty) { Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => adt.struct_variant(), _ => return, }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 62cc78141db46..9a707a49b093f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -41,7 +41,7 @@ use rustc_data_structures::accumulate_vec::AccumulateVec; use arena::TypedArena; use std::borrow::Borrow; -use std::cell::{Cell, RefCell, Ref}; +use std::cell::{Cell, RefCell}; use std::hash::{Hash, Hasher}; use std::mem; use std::ops::Deref; @@ -255,6 +255,65 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { fru_field_types: NodeMap() } } + + pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> { + match self.node_id_to_type_opt(id) { + Some(ty) => ty, + None => { + bug!("node_id_to_type: no type for node `{}`", + tls::with(|tcx| tcx.map.node_to_string(id))) + } + } + } + + pub fn node_id_to_type_opt(&self, id: NodeId) -> Option> { + self.node_types.get(&id).cloned() + } + + pub fn node_id_item_substs(&self, id: NodeId) -> Option<&'tcx Substs<'tcx>> { + self.item_substs.get(&id).map(|ts| ts.substs) + } + + // Returns the type of a pattern as a monotype. Like @expr_ty, this function + // doesn't provide type parameter substitutions. + pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { + self.node_id_to_type(pat.id) + } + + pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option> { + self.node_id_to_type_opt(pat.id) + } + + // Returns the type of an expression as a monotype. + // + // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in + // some cases, we insert `AutoAdjustment` annotations such as auto-deref or + // auto-ref. The type returned by this function does not consider such + // adjustments. See `expr_ty_adjusted()` instead. + // + // NB (2): This type doesn't provide type parameter substitutions; e.g. if you + // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" + // instead of "fn(ty) -> T with T = isize". + pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> { + self.node_id_to_type(expr.id) + } + + pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option> { + self.node_id_to_type_opt(expr.id) + } + + + pub fn is_method_call(&self, expr_id: NodeId) -> bool { + self.method_map.contains_key(&ty::MethodCall::expr(expr_id)) + } + + pub fn is_overloaded_autoderef(&self, expr_id: NodeId, autoderefs: u32) -> bool { + self.method_map.contains_key(&ty::MethodCall::autoderef(expr_id, autoderefs)) + } + + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { + Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone()) + } } impl<'tcx> CommonTypes<'tcx> { @@ -599,14 +658,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.ty_param_defs.borrow().get(&node_id).unwrap().clone() } - pub fn node_types(self) -> Ref<'a, NodeMap>> { - fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap> { - &tables.node_types - } - - Ref::map(self.tables.borrow(), projection) - } - pub fn node_type_insert(self, id: NodeId, ty: Ty<'gcx>) { self.tables.borrow_mut().node_types.insert(id, ty); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 588857e557c22..a378e22e5efd4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2120,52 +2120,8 @@ impl BorrowKind { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn node_id_to_type(self, id: NodeId) -> Ty<'gcx> { - match self.node_id_to_type_opt(id) { - Some(ty) => ty, - None => bug!("node_id_to_type: no type for node `{}`", - self.map.node_to_string(id)) - } - } - - pub fn node_id_to_type_opt(self, id: NodeId) -> Option> { - self.tables.borrow().node_types.get(&id).cloned() - } - - pub fn node_id_item_substs(self, id: NodeId) -> ItemSubsts<'gcx> { - match self.tables.borrow().item_substs.get(&id) { - None => ItemSubsts { - substs: self.global_tcx().intern_substs(&[]) - }, - Some(ts) => ts.clone(), - } - } - - // Returns the type of a pattern as a monotype. Like @expr_ty, this function - // doesn't provide type parameter substitutions. - pub fn pat_ty(self, pat: &hir::Pat) -> Ty<'gcx> { - self.node_id_to_type(pat.id) - } - pub fn pat_ty_opt(self, pat: &hir::Pat) -> Option> { - self.node_id_to_type_opt(pat.id) - } - - // Returns the type of an expression as a monotype. - // - // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in - // some cases, we insert `AutoAdjustment` annotations such as auto-deref or - // auto-ref. The type returned by this function does not consider such - // adjustments. See `expr_ty_adjusted()` instead. - // - // NB (2): This type doesn't provide type parameter substitutions; e.g. if you - // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" - // instead of "fn(ty) -> T with T = isize". - pub fn expr_ty(self, expr: &hir::Expr) -> Ty<'gcx> { - self.node_id_to_type(expr.id) - } - - pub fn expr_ty_opt(self, expr: &hir::Expr) -> Option> { - self.node_id_to_type_opt(expr.id) + pub fn tables(self) -> Ref<'a, Tables<'gcx>> { + self.tables.borrow() } /// Returns the type of `expr`, considering any `AutoAdjustment` @@ -2178,21 +2134,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// unless it was to fix it properly, which seemed a distraction from the /// thread at hand! -nmatsakis pub fn expr_ty_adjusted(self, expr: &hir::Expr) -> Ty<'gcx> { - self.expr_ty(expr) + self.tables().expr_ty(expr) .adjust(self.global_tcx(), expr.span, expr.id, - self.tables.borrow().adjustments.get(&expr.id), + self.tables().adjustments.get(&expr.id), |method_call| { - self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) + self.tables().method_map.get(&method_call).map(|method| method.ty) }) } pub fn expr_ty_adjusted_opt(self, expr: &hir::Expr) -> Option> { - self.expr_ty_opt(expr).map(|t| t.adjust(self.global_tcx(), + self.tables().expr_ty_opt(expr).map(|t| t.adjust(self.global_tcx(), expr.span, expr.id, - self.tables.borrow().adjustments.get(&expr.id), + self.tables().adjustments.get(&expr.id), |method_call| { - self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) + self.tables().method_map.get(&method_call).map(|method| method.ty) })) } @@ -2908,19 +2864,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_region(ty::ReScope(self.region_maps.node_extent(id))) } - pub fn is_method_call(self, expr_id: NodeId) -> bool { - self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id)) - } - - pub fn is_overloaded_autoderef(self, expr_id: NodeId, autoderefs: u32) -> bool { - self.tables.borrow().method_map.contains_key(&MethodCall::autoderef(expr_id, - autoderefs)) - } - - pub fn upvar_capture(self, upvar_id: ty::UpvarId) -> Option> { - Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone()) - } - pub fn visit_all_items_in_krate(self, dep_node_fn: F, visitor: &mut V) diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 9bdc6887f6d03..51574868f9bfb 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -37,7 +37,7 @@ pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, decl_id: ast::NodeId, _decl_span: Span, var_id: ast::NodeId) { - let ty = bccx.tcx.node_id_to_type(var_id); + let ty = bccx.tcx.tables().node_id_to_type(var_id); let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty)); move_data.add_move(bccx.tcx, loan_path, decl_id, Declared); } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 9aa1ac62f5523..615aca90db8bf 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Finally, check if the whole match expression is exhaustive. // Check for empty enum, because is_useful only works on inhabited types. - let pat_ty = self.tcx.node_id_to_type(scrut.id); + let pat_ty = self.tcx.tables().node_id_to_type(scrut.id); if inlined_arms.is_empty() { if !pat_ty.is_uninhabited(self.tcx) { // We know the type is inhabited, so this must be wrong @@ -262,7 +262,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node { - let pat_ty = cx.tcx.pat_ty(p); + let pat_ty = cx.tcx.tables().pat_ty(p); if let ty::TyAdt(edef, _) = pat_ty.sty { if edef.is_enum() { if let Def::Local(..) = cx.tcx.expect_def(p.id) { @@ -486,7 +486,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(..), _, ref sub) = p.node { - let pat_ty = cx.tcx.node_id_to_type(p.id); + let pat_ty = cx.tcx.tables().node_id_to_type(p.id); if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { check_move(p, sub.as_ref().map(|p| &**p)); } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c02cca0da7225..1f66d71406826 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -246,7 +246,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat_id: ast::NodeId, span: Span) -> Result, DefId> { - let pat_ty = tcx.expr_ty(expr); + let pat_ty = tcx.tables().expr_ty(expr); debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id); match pat_ty.sty { ty::TyFloat(_) => { @@ -329,7 +329,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Def::StructCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Const) => PatKind::Path(None, path.clone()), Def::Const(def_id) | Def::AssociatedConst(def_id) => { - let substs = Some(tcx.node_id_item_substs(expr.id).substs); + let substs = Some(tcx.tables().node_id_item_substs(expr.id) + .unwrap_or_else(|| tcx.intern_substs(&[]))); let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap(); return const_expr_to_pat(tcx, expr, pat_id, span); }, @@ -606,7 +607,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ety = match ty_hint { ExprTypeChecked => { // After type-checking, expr_ty is guaranteed to succeed. - Some(tcx.expr_ty(e)) + Some(tcx.tables().expr_ty(e)) } UncheckedExprHint(ty) => { // Use the type hint; it's not guaranteed to be right, but it's @@ -617,7 +618,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // This expression might not be type-checked, and we have no hint. // Try to query the context for a type anyway; we might get lucky // (for example, if the expression was imported from another crate). - tcx.expr_ty_opt(e) + tcx.tables().expr_ty_opt(e) } }; let result = match e.node { @@ -759,7 +760,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let base_hint = if let ExprTypeChecked = ty_hint { ExprTypeChecked } else { - match tcx.expr_ty_opt(&base) { + match tcx.tables().expr_ty_opt(&base) { Some(t) => UncheckedExprHint(t), None => ty_hint } @@ -798,7 +799,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = if let ExprTypeChecked = ty_hint { - Some(tcx.node_id_item_substs(e.id).substs) + Some(tcx.tables().node_id_item_substs(e.id) + .unwrap_or_else(|| tcx.intern_substs(&[]))) } else { None }; diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 946a397474765..10b2a7625cacf 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { - let mut ty = self.tcx.node_id_to_type(pat.id); + let mut ty = self.tcx.tables().node_id_to_type(pat.id); let kind = match pat.node { PatKind::Wild => PatternKind::Wild, @@ -167,8 +167,9 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { match self.tcx.expect_def(pat.id) { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let tcx = self.tcx.global_tcx(); - let substs = Some(self.tcx.node_id_item_substs(pat.id).substs); - match eval::lookup_const_by_id(tcx, def_id, substs) { + let substs = tcx.tables().node_id_item_substs(pat.id) + .unwrap_or_else(|| tcx.intern_substs(&[])); + match eval::lookup_const_by_id(tcx, def_id, Some(substs)) { Some((const_expr, _const_ty)) => { match eval::const_expr_to_pat( tcx, const_expr, pat.id, pat.span) @@ -197,7 +198,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Slice(ref prefix, ref slice, ref suffix) => { - let ty = self.tcx.node_id_to_type(pat.id); + let ty = self.tcx.tables().node_id_to_type(pat.id); match ty.sty { ty::TyRef(_, mt) => PatternKind::Deref { @@ -222,7 +223,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Tuple(ref subpatterns, ddpos) => { - match self.tcx.node_id_to_type(pat.id).sty { + match self.tcx.tables().node_id_to_type(pat.id).sty { ty::TyTuple(ref tys) => { let subpatterns = subpatterns.iter() @@ -243,7 +244,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { PatKind::Binding(bm, ref ident, ref sub) => { let def_id = self.tcx.expect_def(pat.id).def_id(); let id = self.tcx.map.as_local_node_id(def_id).unwrap(); - let var_ty = self.tcx.node_id_to_type(pat.id); + let var_ty = self.tcx.tables().node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(r, _) => Some(r), _ => None, @@ -280,7 +281,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::TupleStruct(_, ref subpatterns, ddpos) => { - let pat_ty = self.tcx.node_id_to_type(pat.id); + let pat_ty = self.tcx.tables().node_id_to_type(pat.id); let adt_def = match pat_ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"), @@ -299,7 +300,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Struct(_, ref fields, _) => { - let pat_ty = self.tcx.node_id_to_type(pat.id); + let pat_ty = self.tcx.tables().node_id_to_type(pat.id); let adt_def = match pat_ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 10ff7dc89f9a3..8dee9b6ddd44d 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -501,7 +501,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { pp::space(&mut s.s)?; pp::word(&mut s.s, "as")?; pp::space(&mut s.s)?; - pp::word(&mut s.s, &self.tcx.expr_ty(expr).to_string())?; + pp::word(&mut s.s, &self.tcx.tables().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index eee34324a6583..6afcd18df0ad3 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -118,7 +118,9 @@ impl LateLintPass for BoxPointers { hir::ItemTy(..) | hir::ItemEnum(..) | hir::ItemStruct(..) | - hir::ItemUnion(..) => self.check_heap_type(cx, it.span, cx.tcx.node_id_to_type(it.id)), + hir::ItemUnion(..) => { + self.check_heap_type(cx, it.span, cx.tcx.tables().node_id_to_type(it.id)) + } _ => (), } @@ -129,7 +131,7 @@ impl LateLintPass for BoxPointers { for struct_field in struct_def.fields() { self.check_heap_type(cx, struct_field.span, - cx.tcx.node_id_to_type(struct_field.id)); + cx.tcx.tables().node_id_to_type(struct_field.id)); } } _ => (), @@ -137,7 +139,7 @@ impl LateLintPass for BoxPointers { } fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { - let ty = cx.tcx.node_id_to_type(e.id); + let ty = cx.tcx.tables().node_id_to_type(e.id); self.check_heap_type(cx, e.span, ty); } } @@ -585,7 +587,7 @@ impl LateLintPass for MissingDebugImplementations { let mut impls = NodeSet(); debug_def.for_each_impl(cx.tcx, |d| { if let Some(n) = cx.tcx.map.as_local_node_id(d) { - if let Some(ty_def) = cx.tcx.node_id_to_type(n).ty_to_def_id() { + if let Some(ty_def) = cx.tcx.tables().node_id_to_type(n).ty_to_def_id() { if let Some(node_id) = cx.tcx.map.as_local_node_id(ty_def) { impls.insert(node_id); } @@ -940,7 +942,7 @@ impl LateLintPass for UnconditionalRecursion { id: ast::NodeId) -> bool { // Check for method calls and overloaded operators. - let opt_m = tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)).cloned(); + let opt_m = tcx.tables().method_map.get(&ty::MethodCall::expr(id)).cloned(); if let Some(m) = opt_m { if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { return true; @@ -948,15 +950,12 @@ impl LateLintPass for UnconditionalRecursion { } // Check for overloaded autoderef method calls. - let opt_adj = tcx.tables.borrow().adjustments.get(&id).cloned(); + let opt_adj = tcx.tables().adjustments.get(&id).cloned(); if let Some(adjustment::AdjustDerefRef(adj)) = opt_adj { for i in 0..adj.autoderefs { let method_call = ty::MethodCall::autoderef(id, i as u32); - if let Some(m) = tcx.tables - .borrow() - .method_map - .get(&method_call) - .cloned() { + if let Some(m) = tcx.tables().method_map.get(&method_call) + .cloned() { if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { return true; } @@ -971,12 +970,10 @@ impl LateLintPass for UnconditionalRecursion { // it doesn't necessarily have a definition. match tcx.expect_def_or_none(callee.id) { Some(Def::Method(def_id)) => { - let item_substs = tcx.node_id_item_substs(callee.id); - method_call_refers_to_method(tcx, - method, - def_id, - &item_substs.substs, - id) + let substs = tcx.tables().node_id_item_substs(callee.id) + .unwrap_or_else(|| tcx.intern_substs(&[])); + method_call_refers_to_method( + tcx, method, def_id, substs, id) } _ => false, } @@ -1213,7 +1210,7 @@ impl LateLintPass for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tcx.node_id_to_type(expr.id); + let typ = cx.tcx.tables().node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(.., ref bare_fn) if bare_fn.abi == RustIntrinsic => { let from = bare_fn.sig.0.inputs[0]; @@ -1284,7 +1281,7 @@ impl LateLintPass for UnionsWithDropFields { if let hir::ItemUnion(ref vdata, _) = item.node { let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id); for field in vdata.fields() { - let field_ty = ctx.tcx.node_id_to_type(field.id); + let field_ty = ctx.tcx.tables().node_id_to_type(field.id); if ctx.tcx.type_needs_drop_given_env(field_ty, param_env) { ctx.span_lint(UNIONS_WITH_DROP_FIELDS, field.span, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 9464bf30b693f..b04759955a956 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -113,14 +113,14 @@ impl LateLintPass for TypeLimits { forbid_unsigned_negation(cx, e.span); } ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { - if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty { + if let ty::TyUint(_) = cx.tcx.tables().node_id_to_type(e.id).sty { forbid_unsigned_negation(cx, e.span); } } _ => (), } } else { - let t = cx.tcx.node_id_to_type(expr.id); + let t = cx.tcx.tables().node_id_to_type(expr.id); if let ty::TyUint(_) = t.sty { forbid_unsigned_negation(cx, e.span); } @@ -138,7 +138,7 @@ impl LateLintPass for TypeLimits { } if binop.node.is_shift() { - let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty { + let opt_ty_bits = match cx.tcx.tables().node_id_to_type(l.id).sty { ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), _ => None, @@ -171,7 +171,7 @@ impl LateLintPass for TypeLimits { } } hir::ExprLit(ref lit) => { - match cx.tcx.node_id_to_type(e.id).sty { + match cx.tcx.tables().node_id_to_type(e.id).sty { ty::TyInt(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | @@ -324,7 +324,7 @@ impl LateLintPass for TypeLimits { // Normalize the binop so that the literal is always on the RHS in // the comparison let norm_binop = if swap { rev_binop(binop) } else { binop }; - match tcx.node_id_to_type(expr.id).sty { + match tcx.tables().node_id_to_type(expr.id).sty { ty::TyInt(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i64 = match lit.node { @@ -740,7 +740,7 @@ impl LateLintPass for VariantSizeDifferences { if let hir::ItemEnum(ref enum_definition, ref gens) = it.node { if gens.ty_params.is_empty() { // sizes only make sense for non-generic types - let t = cx.tcx.node_id_to_type(it.id); + let t = cx.tcx.tables().node_id_to_type(it.id); let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { let ty = cx.tcx.erase_regions(&t); ty.layout(&infcx) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index a29ff18ab5318..2df09aa25c8be 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -140,7 +140,7 @@ impl LateLintPass for UnusedResults { return; } - let t = cx.tcx.expr_ty(&expr); + let t = cx.tcx.tables().expr_ty(&expr); let warned = match t.sty { ty::TyTuple(ref tys) if tys.is_empty() => return, ty::TyNever => return, @@ -441,7 +441,7 @@ impl LateLintPass for UnusedAllocation { _ => return, } - if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) { + if let Some(adjustment) = cx.tcx.tables().adjustments.get(&e.id) { if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef { ref autoref, .. }) = *adjustment { match autoref { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index f001f85131978..63ec6a7069bb2 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -94,9 +94,9 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> }; encode(tcx.expect_def_or_none(id).map(TableEntry::Def)); - encode(tcx.node_types().get(&id).cloned().map(TableEntry::NodeType)); - encode(tcx.tables.borrow().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); - encode(tcx.tables.borrow().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); + encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType)); + encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); + encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); encode(tcx.const_qualif_map.borrow().get(&id).cloned().map(TableEntry::ConstQualif)); } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e8734e4275712..fdb117ef81b13 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1016,7 +1016,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.tables.borrow().closure_tys[&def_id]), + ty: self.lazy(&tcx.tables().closure_tys[&def_id]), }; Entry { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index d6fcc79a9a213..58526a3444e24 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -191,7 +191,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, assert_eq!(block, builder.return_block()); let mut spread_arg = None; - match tcx.node_id_to_type(fn_id).sty { + match tcx.tables().node_id_to_type(fn_id).sty { ty::TyFnDef(_, _, f) if f.abi == Abi::RustCall => { // RustCall pseudo-ABI untuples the last argument. spread_arg = Some(Local::new(arguments.len())); @@ -203,7 +203,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = tcx.map.as_local_node_id(fv.def.def_id()).unwrap(); - let by_ref = tcx.upvar_capture(ty::UpvarId { + let by_ref = tcx.tables().upvar_capture(ty::UpvarId { var_id: var_id, closure_expr_id: fn_id }).map_or(false, |capture| match capture { diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index ec1136368c135..cb69de2cb3cac 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -77,7 +77,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> { - let block_ty = cx.tcx.node_id_to_type(block.id); + let block_ty = cx.tcx.tables().node_id_to_type(block.id); let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id); let expr = Expr { ty: block_ty, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 1b324ac3132fc..ddf487e9d7659 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -37,10 +37,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { let mut expr = make_mirror_unadjusted(cx, self); debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}", - expr, cx.tcx.tables.borrow().adjustments.get(&self.id)); + expr, cx.tcx.tables().adjustments.get(&self.id)); // Now apply adjustments, if any. - match cx.tcx.tables.borrow().adjustments.get(&self.id) { + match cx.tcx.tables().adjustments.get(&self.id) { None => {} Some(&ty::adjustment::AdjustReifyFnPointer) => { let adjusted_ty = cx.tcx.expr_ty_adjusted(self); @@ -86,11 +86,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { self.id, self.span, i, - |mc| cx.tcx.tables.borrow().method_map.get(&mc).map(|m| m.ty)); + |mc| cx.tcx.tables().method_map.get(&mc).map(|m| m.ty)); debug!("make_mirror: autoderef #{}, adjusted_ty={:?}", i, adjusted_ty); let method_key = ty::MethodCall::autoderef(self.id, i); let meth_ty = - cx.tcx.tables.borrow().method_map.get(&method_key).map(|m| m.ty); + cx.tcx.tables().method_map.get(&method_key).map(|m| m.ty); let kind = if let Some(meth_ty) = meth_ty { debug!("make_mirror: overloaded autoderef (meth_ty={:?})", meth_ty); @@ -212,7 +212,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> { - let expr_ty = cx.tcx.expr_ty(expr); + let expr_ty = cx.tcx.tables().expr_ty(expr); let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); let kind = match expr.node { @@ -231,7 +231,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprCall(ref fun, ref args) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { // The callee is something implementing Fn, FnMut, or FnOnce. // Find the actual method implementation being called and // build the appropriate UFCS call expression with the @@ -282,7 +282,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }) } else { None }; if let Some((adt_def, index)) = adt_data { - let substs = cx.tcx.node_id_item_substs(fun.id).substs; + let substs = cx.tcx.tables().node_id_item_substs(fun.id) + .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let field_refs = args.iter().enumerate().map(|(idx, e)| FieldExprRef { name: Field::new(idx), expr: e.to_ref() @@ -296,7 +297,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } else { ExprKind::Call { - ty: cx.tcx.node_id_to_type(fun.id), + ty: cx.tcx.tables().node_id_to_type(fun.id), fun: fun.to_ref(), args: args.to_ref(), } @@ -328,7 +329,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprAssignOp(op, ref lhs, ref rhs) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -350,7 +351,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }, hir::ExprBinary(op, ref lhs, ref rhs) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -406,7 +407,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprIndex(ref lhs, ref index) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, lhs.to_ref(), vec![index]) } else { @@ -418,7 +419,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, arg.to_ref(), vec![]) } else { @@ -427,7 +428,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNot, ref arg) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, arg.to_ref(), vec![]) } else { @@ -439,7 +440,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, arg.to_ref(), vec![]) } else { @@ -470,10 +471,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, base: base.as_ref().map(|base| { FruInfo { base: base.to_ref(), - field_types: cx.tcx.tables - .borrow() - .fru_field_types[&expr.id] - .clone() + field_types: + cx.tcx.tables().fru_field_types[&expr.id].clone() } }) } @@ -512,7 +511,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprClosure(..) => { - let closure_ty = cx.tcx.expr_ty(expr); + let closure_ty = cx.tcx.tables().expr_ty(expr); let (def_id, substs) = match closure_ty.sty { ty::TyClosure(def_id, substs) => (def_id, substs), _ => { @@ -551,7 +550,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat { value: v.to_ref(), count: TypedConstVal { - ty: cx.tcx.expr_ty(c), + ty: cx.tcx.tables().expr_ty(c), span: c.span, value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) { ConstVal::Integral(ConstInt::Usize(u)) => u, @@ -631,8 +630,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &hir::Expr, method_call: ty::MethodCall) -> Expr<'tcx> { - let tables = cx.tcx.tables.borrow(); - let callee = &tables.method_map[&method_call]; + let callee = cx.tcx.tables().method_map[&method_call]; let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); Expr { temp_lifetime: temp_lifetime, @@ -666,8 +664,8 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> ExprKind<'tcx> { - let substs = cx.tcx.node_id_item_substs(expr.id).substs; - // Otherwise there may be def_map borrow conflicts + let substs = cx.tcx.tables().node_id_item_substs(expr.id) + .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let def = cx.tcx.expect_def(expr.id); let def_id = match def { // A regular function, constructor function or a constant. @@ -677,18 +675,20 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => def_id, Def::StructCtor(def_id, CtorKind::Const) | - Def::VariantCtor(def_id, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty { - // A unit struct/variant which is used as a value. - // We return a completely different ExprKind here to account for this special case. - ty::TyAdt(adt_def, substs) => return ExprKind::Adt { - adt_def: adt_def, - variant_index: adt_def.variant_index_with_id(def_id), - substs: substs, - fields: vec![], - base: None, - }, - ref sty => bug!("unexpected sty: {:?}", sty) - }, + Def::VariantCtor(def_id, CtorKind::Const) => { + match cx.tcx.tables().node_id_to_type(expr.id).sty { + // A unit struct/variant which is used as a value. + // We return a completely different ExprKind here to account for this special case. + ty::TyAdt(adt_def, substs) => return ExprKind::Adt { + adt_def: adt_def, + variant_index: adt_def.variant_index_with_id(def_id), + substs: substs, + fields: vec![], + base: None, + }, + ref sty => bug!("unexpected sty: {:?}", sty) + } + } Def::Static(node_id, _) => return ExprKind::StaticRef { id: node_id, @@ -720,7 +720,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Upvar(def_id, index, closure_expr_id) => { let id_var = cx.tcx.map.as_local_node_id(def_id).unwrap(); debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id); - let var_ty = cx.tcx.node_id_to_type(id_var); + let var_ty = cx.tcx.tables().node_id_to_type(id_var); let body_id = match cx.tcx.map.find(closure_expr_id) { Some(map::NodeExpr(expr)) => { @@ -737,7 +737,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; // FIXME free regions in closures are not right - let closure_ty = cx.tcx.node_id_to_type(closure_expr_id); + let closure_ty = cx.tcx.tables().node_id_to_type(closure_expr_id); // FIXME we're just hard-coding the idea that the // signature will be &self or &mut self and hence will @@ -809,7 +809,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr_id, }; - let upvar_capture = match cx.tcx.upvar_capture(upvar_id) { + let upvar_capture = match cx.tcx.tables().upvar_capture(upvar_id) { Some(c) => c, None => { span_bug!( @@ -931,9 +931,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // line up (this is because `*x` and `x[y]` represent lvalues): // to find the type &T of the content returned by the method; - let tables = cx.tcx.tables.borrow(); - let callee = &tables.method_map[&method_call]; - let ref_ty = callee.ty.fn_ret(); + let ref_ty = cx.tcx.tables().method_map[&method_call].ty.fn_ret(); let ref_ty = cx.tcx.no_late_bound_regions(&ref_ty).unwrap(); // callees always have all late-bound regions fully instantiated, @@ -962,9 +960,9 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr.id, }; - let upvar_capture = cx.tcx.upvar_capture(upvar_id).unwrap(); + let upvar_capture = cx.tcx.tables().upvar_capture(upvar_id).unwrap(); let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id); - let var_ty = cx.tcx.node_id_to_type(id_var); + let var_ty = cx.tcx.tables().node_id_to_type(id_var); let captured_var = Expr { temp_lifetime: temp_lifetime, ty: var_ty, diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index b0e2d6e73d37a..0ffc59fe6bf45 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { id: ast::NodeId) { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) - let fn_sig = match self.tcx.tables.borrow().liberated_fn_sigs.get(&id) { + let fn_sig = match self.tcx.tables().liberated_fn_sigs.get(&id) { Some(f) => f.clone(), None => { span_bug!(span, "no liberated fn sig for {:?}", id); @@ -248,7 +248,7 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, closure_expr_id: ast::NodeId, body_id: ast::NodeId) -> Ty<'tcx> { - let closure_ty = tcx.node_id_to_type(closure_expr_id); + let closure_ty = tcx.tables().node_id_to_type(closure_expr_id); // We're just hard-coding the idea that the signature will be // &self or &mut self and hence will have a bound region with diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 8ad4d7f57a6f0..20e9e76ab843d 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -319,7 +319,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { let mut outer = self.qualif; self.qualif = ConstQualif::empty(); - let node_ty = self.tcx.node_id_to_type(ex.id); + let node_ty = self.tcx.tables().node_id_to_type(ex.id); check_expr(self, ex, node_ty); check_adjustments(self, ex); @@ -449,14 +449,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node match e.node { hir::ExprUnary(..) | hir::ExprBinary(..) | - hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => { + hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => { v.add_qualif(ConstQualif::NOT_CONST); } hir::ExprBox(_) => { v.add_qualif(ConstQualif::NOT_CONST); } hir::ExprUnary(op, ref inner) => { - match v.tcx.node_id_to_type(inner.id).sty { + match v.tcx.tables().node_id_to_type(inner.id).sty { ty::TyRawPtr(_) => { assert!(op == hir::UnDeref); @@ -466,7 +466,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprBinary(op, ref lhs, _) => { - match v.tcx.node_id_to_type(lhs.id).sty { + match v.tcx.tables().node_id_to_type(lhs.id).sty { ty::TyRawPtr(_) => { assert!(op.node == hir::BiEq || op.node == hir::BiNe || op.node == hir::BiLe || op.node == hir::BiLt || @@ -503,7 +503,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } Def::Const(did) | Def::AssociatedConst(did) => { - let substs = Some(v.tcx.node_id_item_substs(e.id).substs); + let substs = Some(v.tcx.tables().node_id_item_substs(e.id) + .unwrap_or_else(|| v.tcx.intern_substs(&[]))); if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) { let inner = v.global_expr(Mode::Const, expr); v.add_qualif(inner); @@ -555,7 +556,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprMethodCall(..) => { - let method = v.tcx.tables.borrow().method_map[&method_call]; + let method = v.tcx.tables().method_map[&method_call]; let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() { ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty), ty::TraitContainer(_) => false @@ -565,7 +566,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprStruct(..) => { - if let ty::TyAdt(adt, ..) = v.tcx.expr_ty(e).sty { + if let ty::TyAdt(adt, ..) = v.tcx.tables().expr_ty(e).sty { // unsafe_cell_type doesn't necessarily exist with no_core if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() { v.add_qualif(ConstQualif::MUTABLE_MEM); @@ -624,7 +625,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node /// Check the adjustments of an expression fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) { - match v.tcx.tables.borrow().adjustments.get(&e.id) { + match v.tcx.tables().adjustments.get(&e.id) { None | Some(&ty::adjustment::AdjustNeverToAny(..)) | Some(&ty::adjustment::AdjustReifyFnPointer) | @@ -633,7 +634,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp Some(&ty::adjustment::AdjustDerefRef(ty::adjustment::AutoDerefRef { autoderefs, .. })) => { if (0..autoderefs as u32) - .any(|autoderef| v.tcx.is_overloaded_autoderef(e.id, autoderef)) { + .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) { v.add_qualif(ConstQualif::NOT_CONST); } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 77b3e76fc541f..8fdfecd4a5865 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -430,11 +430,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method = self.tcx.tables.borrow().method_map[&method_call]; + let method = self.tcx.tables().method_map[&method_call]; self.check_method(expr.span, method.def_id); } hir::ExprStruct(_, ref expr_fields, _) => { - let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap(); + let adt = self.tcx.tables().expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(expr.id)); // RFC 736: ensure all unmentioned fields are visible. // Rather than computing the set of unmentioned fields @@ -495,14 +495,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { match pattern.node { PatKind::Struct(_, ref fields, _) => { - let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap(); + let adt = self.tcx.tables().pat_ty(pattern).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(pattern.id)); for field in fields { self.check_field(field.span, adt, variant.field_named(field.node.name)); } } PatKind::TupleStruct(_, ref fields, ddpos) => { - match self.tcx.pat_ty(pattern).sty { + match self.tcx.tables().pat_ty(pattern).sty { // enum fields have no privacy at this time ty::TyAdt(def, _) if !def.is_enum() => { let expected_len = def.struct_variant().fields.len(); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 8a628289b7f94..3a092613a054a 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -356,7 +356,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { collector.visit_pat(&arg.pat); let span_utils = self.span.clone(); for &(id, ref p, ..) in &collector.collected_paths { - let typ = self.tcx.node_types().get(&id).unwrap().to_string(); + let typ = self.tcx.tables().node_types.get(&id).unwrap().to_string(); // get the span only for the name of the variable (I hope the path is only ever a // variable name, but who knows?) let sub_span = span_utils.span_for_last_ident(p.span); @@ -988,7 +988,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { match p.node { PatKind::Struct(ref path, ref fields, _) => { visit::walk_path(self, path); - let adt = self.tcx.node_id_to_type(p.id).ty_adt_def().unwrap(); + let adt = self.tcx.tables().node_id_to_type(p.id).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(p.id)); for &Spanned { node: ref field, span } in fields { @@ -1023,8 +1023,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ast::Mutability::Immutable => value.to_string(), _ => String::new(), }; - let types = self.tcx.node_types(); - let typ = match types.get(&id) { + let typ = match self.tcx.tables().node_types.get(&id) { Some(typ) => { let typ = typ.to_string(); if !value.is_empty() { @@ -1355,7 +1354,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> } ast::ExprKind::Struct(ref path, ref fields, ref base) => { let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id); - let adt = self.tcx.expr_ty(&hir_expr).ty_adt_def().unwrap(); + let adt = self.tcx.tables().expr_ty(&hir_expr).ty_adt_def().unwrap(); let def = self.tcx.expect_def(hir_expr.id); self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base) } @@ -1468,7 +1467,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> } else { "".to_string() }; - let typ = self.tcx.node_types() + let typ = self.tcx.tables().node_types .get(&id).map(|t| t.to_string()).unwrap_or(String::new()); value.push_str(": "); value.push_str(&typ); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 15c74f2ed6ab5..c111824a30cb5 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -286,7 +286,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: NodeId) -> Option { if let Some(ident) = field.ident { let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); - let typ = self.tcx.node_types().get(&field.id).unwrap().to_string(); + let typ = self.tcx.tables().node_types.get(&field.id).unwrap().to_string(); let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon); filter!(self.span_utils, sub_span, field.span, None); Some(VariableData { @@ -472,7 +472,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::MethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let method_id = self.tcx.tables().method_map[&method_call].def_id; let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index cd81d114eb770..ffb13a833a582 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -74,7 +74,7 @@ impl<'tcx> Callee<'tcx> { pub fn method_call<'blk>(bcx: Block<'blk, 'tcx>, method_call: ty::MethodCall) -> Callee<'tcx> { - let method = bcx.tcx().tables.borrow().method_map[&method_call]; + let method = bcx.tcx().tables().method_map[&method_call]; Callee::method(bcx, method) } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 8348da9f7b7bf..a439d415ede15 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1082,10 +1082,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { hir::ItemStruct(_, ref generics) | hir::ItemUnion(_, ref generics) => { if !generics.is_parameterized() { - let ty = { - let tables = self.scx.tcx().tables.borrow(); - tables.node_types[&item.id] - }; + let ty = self.scx.tcx().tables().node_types[&item.id]; if self.mode == TransItemCollectionMode::Eager { debug!("RootCollector: ADT drop-glue for {}", diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 863aecc824433..4bb34850e0870 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1765,7 +1765,7 @@ pub fn create_global_var_metadata(cx: &CrateContext, }; let is_local_to_unit = is_node_local_to_unit(cx, node_id); - let variable_type = tcx.erase_regions(&tcx.node_id_to_type(node_id)); + let variable_type = tcx.erase_regions(&tcx.tables().node_id_to_type(node_id)); let type_metadata = type_metadata(cx, variable_type, span); let var_name = tcx.item_name(node_def_id).to_string(); let linkage_name = mangled_name_of_item(cx, node_def_id, ""); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8799050b1b999..2db58ef066296 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1551,7 +1551,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.prohibit_type_params(base_segments); let impl_id = tcx.map.as_local_node_id(def_id).unwrap(); - let ty = tcx.node_id_to_type(impl_id); + let ty = tcx.tables().node_id_to_type(impl_id); if let Some(free_substs) = self.get_free_substs() { ty.subst(tcx, free_substs) } else { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 75a14bb3db922..3fec347b75b93 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -773,7 +773,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { check_union(ccx, it.id, it.span); } hir::ItemTy(_, ref generics) => { - let pty_ty = ccx.tcx.node_id_to_type(it.id); + let pty_ty = ccx.tcx.tables().node_id_to_type(it.id); check_bounds_are_used(ccx, generics, pty_ty); } hir::ItemForeignMod(ref m) => { @@ -1188,7 +1188,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, item_id: ast::NodeId) -> bool { - let rty = tcx.node_id_to_type(item_id); + let rty = tcx.tables().node_id_to_type(item_id); // Check that it is possible to represent this type. This call identifies // (1) types that contain themselves and (2) types that contain a different @@ -1207,7 +1207,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, id: ast::NodeId) { - let t = tcx.node_id_to_type(id); + let t = tcx.tables().node_id_to_type(id); match t.sty { ty::TyAdt(def, substs) if def.is_struct() => { let fields = &def.struct_variant().fields; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e3634cfe5f5e3..be1f2e35679d7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -416,7 +416,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } } None => { - let self_ty = fcx.tcx.node_id_to_type(item.id); + let self_ty = fcx.tcx.tables().node_id_to_type(item.id); let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty); fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone()); } @@ -519,7 +519,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { item: &hir::Item, ast_generics: &hir::Generics) { - let ty = self.tcx().node_id_to_type(item.id); + let ty = self.tcx().tables().node_id_to_type(item.id); if self.tcx().has_error_field(ty) { return; } @@ -649,7 +649,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let fields = struct_def.fields().iter() .map(|field| { - let field_ty = self.tcx.node_id_to_type(field.id); + let field_ty = self.tcx.tables().node_id_to_type(field.id); let field_ty = self.instantiate_type_scheme(field.span, &self.parameter_environment .free_substs, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 8685f703a599c..688bcbdcd121c 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -229,7 +229,7 @@ impl<'cx, 'gcx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'gcx, 'tcx> { debug!("Type for pattern binding {} (id {}) resolved to {:?}", pat_to_string(p), p.id, - self.tcx().node_id_to_type(p.id)); + self.tcx().tables().node_id_to_type(p.id)); intravisit::walk_pat(self, p); } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c16dd788c4ec8..5a48b5f0e1fd1 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -211,7 +211,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, main_id: ast::NodeId, main_span: Span) { let tcx = ccx.tcx; - let main_t = tcx.node_id_to_type(main_id); + let main_t = tcx.tables().node_id_to_type(main_id); match main_t.sty { ty::TyFnDef(..) => { match tcx.map.find(main_id) { @@ -263,7 +263,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, start_id: ast::NodeId, start_span: Span) { let tcx = ccx.tcx; - let start_t = tcx.node_id_to_type(start_id); + let start_t = tcx.tables().node_id_to_type(start_id); match start_t.sty { ty::TyFnDef(..) => { match tcx.map.find(start_id) { From 0d7201ef46b9bdf8474b07b839d029e56d4f29b7 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 20 Oct 2016 06:33:20 +0300 Subject: [PATCH 10/41] rustc: record the target type of every adjustment. --- src/librustc/cfg/construct.rs | 2 +- src/librustc/infer/mod.rs | 26 +- src/librustc/middle/dead.rs | 4 +- src/librustc/middle/effect.rs | 6 +- src/librustc/middle/expr_use_visitor.rs | 55 ++-- src/librustc/middle/liveness.rs | 2 +- src/librustc/middle/mem_categorization.rs | 26 +- src/librustc/middle/stability.rs | 4 +- src/librustc/ty/adjustment.rs | 289 ++++++++------------ src/librustc/ty/context.rs | 15 +- src/librustc/ty/fold.rs | 4 +- src/librustc/ty/mod.rs | 28 -- src/librustc/ty/structural_impls.rs | 24 +- src/librustc/util/ppaux.rs | 27 +- src/librustc_lint/builtin.rs | 7 +- src/librustc_lint/unused.rs | 7 +- src/librustc_metadata/astencode.rs | 2 +- src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 35 ++- src/librustc_passes/consts.rs | 14 +- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_save_analysis/lib.rs | 6 +- src/librustc_typeck/check/callee.rs | 2 +- src/librustc_typeck/check/coercion.rs | 125 +++++---- src/librustc_typeck/check/method/confirm.rs | 136 ++++----- src/librustc_typeck/check/method/mod.rs | 28 +- src/librustc_typeck/check/mod.rs | 52 ++-- src/librustc_typeck/check/regionck.rs | 38 +-- src/librustc_typeck/check/writeback.rs | 36 +-- 29 files changed, 422 insertions(+), 582 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 8c7805b5450e3..a2fc6e044e74c 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -374,7 +374,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let method_call = ty::MethodCall::expr(call_expr.id); let fn_ty = match self.tcx.tables().method_map.get(&method_call) { Some(method) => method.ty, - None => self.tcx.expr_ty_adjusted(func_or_rcvr) + None => self.tcx.tables().expr_ty_adjusted(func_or_rcvr) }; let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index af994e884fe47..689f45cd709d5 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1256,26 +1256,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.region_vars.new_bound(debruijn) } - /// Apply `adjustment` to the type of `expr` - pub fn adjust_expr_ty(&self, - expr: &hir::Expr, - adjustment: Option<&adjustment::AutoAdjustment<'tcx>>) - -> Ty<'tcx> - { - let raw_ty = self.expr_ty(expr); - let raw_ty = self.shallow_resolve(raw_ty); - let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty); - raw_ty.adjust(self.tcx, - expr.span, - expr.id, - adjustment, - |method_call| self.tables - .borrow() - .method_map - .get(&method_call) - .map(|method| resolve_ty(method.ty))) - } - /// True if errors have been reported since this infcx was /// created. This is sometimes used as a heuristic to skip /// reporting errors that often occur as a result of earlier @@ -1612,7 +1592,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id)); + let ty = self.tables.borrow().expr_ty_adjusted(expr); self.resolve_type_vars_or_error(&ty) } @@ -1656,9 +1636,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .map(|method| method.def_id) } - pub fn adjustments(&self) -> Ref>> { + pub fn adjustments(&self) -> Ref>> { fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { + -> &'a NodeMap> { &tables.adjustments } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index daa32fc760faa..4212b1fb05ee3 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -128,7 +128,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) { - match self.tcx.expr_ty_adjusted(lhs).sty { + match self.tcx.tables().expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().field_named(name).did); } @@ -137,7 +137,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) { - match self.tcx.expr_ty_adjusted(lhs).sty { + match self.tcx.tables().expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().fields[idx].did); } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 8964405fb7f77..8ca3c75eaa4b1 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -168,7 +168,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprCall(ref base, _) => { - let base_type = self.tcx.expr_ty_adjusted(base); + let base_type = self.tcx.tables().expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -176,7 +176,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprUnary(hir::UnDeref, ref base) => { - let base_type = self.tcx.expr_ty_adjusted(base); + let base_type = self.tcx.tables().expr_ty_adjusted(base); debug!("effect: unary case, base type is {:?}", base_type); if let ty::TyRawPtr(_) = base_type.sty { @@ -200,7 +200,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprField(ref base_expr, field) => { - if let ty::TyAdt(adt, ..) = self.tcx.expr_ty_adjusted(base_expr).sty { + if let ty::TyAdt(adt, ..) = self.tcx.tables().expr_ty_adjusted(base_expr).sty { if adt.is_union() { self.require_unsafe(field.span, "access to union field"); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index c37b6df369dfc..0543d1303a5f1 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -720,11 +720,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { //NOTE(@jroesch): mixed RefCell borrow causes crash let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone()); if let Some(adjustment) = adj { - match adjustment { - adjustment::AdjustNeverToAny(..) | - adjustment::AdjustReifyFnPointer | - adjustment::AdjustUnsafeFnPointer | - adjustment::AdjustMutToConstPointer => { + match adjustment.kind { + adjustment::Adjust::NeverToAny | + adjustment::Adjust::ReifyFnPointer | + adjustment::Adjust::UnsafeFnPointer | + adjustment::Adjust::MutToConstPointer => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. debug!("walk_adjustment: trivial adjustment"); @@ -732,8 +732,21 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { return_if_err!(self.mc.cat_expr_unadjusted(expr)); self.delegate_consume(expr.id, expr.span, cmt_unadjusted); } - adjustment::AdjustDerefRef(ref adj) => { - self.walk_autoderefref(expr, adj); + adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => { + debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); + + self.walk_autoderefs(expr, autoderefs); + + let cmt_derefd = + return_if_err!(self.mc.cat_expr_autoderefd(expr, autoderefs)); + + let cmt_refd = + self.walk_autoref(expr, cmt_derefd, autoref); + + if unsize { + // Unsizing consumes the thin pointer and produces a fat one. + self.delegate_consume(expr.id, expr.span, cmt_refd); + } } } } @@ -770,28 +783,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } - fn walk_autoderefref(&mut self, - expr: &hir::Expr, - adj: &adjustment::AutoDerefRef<'tcx>) { - debug!("walk_autoderefref expr={:?} adj={:?}", - expr, - adj); - - self.walk_autoderefs(expr, adj.autoderefs); - - let cmt_derefd = - return_if_err!(self.mc.cat_expr_autoderefd(expr, adj.autoderefs)); - - let cmt_refd = - self.walk_autoref(expr, cmt_derefd, adj.autoref); - - if adj.unsize.is_some() { - // Unsizing consumes the thin pointer and produces a fat one. - self.delegate_consume(expr.id, expr.span, cmt_refd); - } - } - - /// Walks the autoref `opt_autoref` applied to the autoderef'd /// `expr`. `cmt_derefd` is the mem-categorized form of `expr` /// after all relevant autoderefs have occurred. Because AutoRefs @@ -803,7 +794,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_autoref(&mut self, expr: &hir::Expr, cmt_base: mc::cmt<'tcx>, - opt_autoref: Option>) + opt_autoref: Option>) -> mc::cmt<'tcx> { debug!("walk_autoref(expr.id={} cmt_derefd={:?} opt_autoref={:?})", @@ -822,7 +813,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { }; match *autoref { - adjustment::AutoPtr(r, m) => { + adjustment::AutoBorrow::Ref(r, m) => { self.delegate.borrow(expr.id, expr.span, cmt_base, @@ -831,7 +822,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { AutoRef); } - adjustment::AutoUnsafe(m) => { + adjustment::AutoBorrow::RawPtr(m) => { debug!("walk_autoref: expr.id={} cmt_base={:?}", expr.id, cmt_base); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index e544ddc402b5f..46bea00cca3cb 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1114,7 +1114,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprCall(ref f, ref args) => { // FIXME(canndrew): This is_never should really be an is_uninhabited let diverges = !self.ir.tcx.tables().is_method_call(expr.id) && - self.ir.tcx.expr_ty_adjusted(&f).fn_ret().0.is_never(); + self.ir.tcx.tables().expr_ty_adjusted(&f).fn_ret().0.is_never(); let succ = if diverges { self.s.exit_ln } else { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 9214138d21077..e3ed13e1e4017 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -354,11 +354,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - let unadjusted_ty = self.expr_ty(expr)?; - Ok(unadjusted_ty.adjust( - self.tcx(), expr.span, expr.id, - self.infcx.adjustments().get(&expr.id), - |method_call| self.infcx.node_method_ty(method_call))) + self.infcx.expr_ty_adjusted(expr) } fn node_ty(&self, id: ast::NodeId) -> McResult> { @@ -396,19 +392,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Some(adjustment) => { - match *adjustment { - adjustment::AdjustDerefRef( - adjustment::AutoDerefRef { - autoref: None, unsize: None, autoderefs, ..}) => { + match adjustment.kind { + adjustment::Adjust::DerefRef { + autoderefs, + autoref: None, + unsize: false + } => { // Equivalent to *expr or something similar. self.cat_expr_autoderefd(expr, autoderefs) } - adjustment::AdjustNeverToAny(..) | - adjustment::AdjustReifyFnPointer | - adjustment::AdjustUnsafeFnPointer | - adjustment::AdjustMutToConstPointer | - adjustment::AdjustDerefRef(_) => { + adjustment::Adjust::NeverToAny | + adjustment::Adjust::ReifyFnPointer | + adjustment::Adjust::UnsafeFnPointer | + adjustment::Adjust::MutToConstPointer | + adjustment::Adjust::DerefRef {..} => { debug!("cat_expr({:?}): {:?}", adjustment, expr); diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index a03cf708e8c19..fd17e378787a5 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -559,7 +559,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, } hir::ExprField(ref base_e, ref field) => { span = field.span; - match tcx.expr_ty_adjusted(base_e).sty { + match tcx.tables().expr_ty_adjusted(base_e).sty { ty::TyAdt(def, _) => { def.struct_variant().field_named(field.node).did } @@ -569,7 +569,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, } hir::ExprTupField(ref base_e, ref field) => { span = field.span; - match tcx.expr_ty_adjusted(base_e).sty { + match tcx.tables().expr_ty_adjusted(base_e).sty { ty::TyAdt(def, _) => { def.struct_variant().fields[field.node].did } diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index cfe370343ae49..333a5c74cb45c 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::AutoAdjustment::*; -pub use self::AutoRef::*; - -use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFoldable}; +use ty::{self, Ty, TyCtxt, TypeAndMut}; use ty::LvaluePreference::{NoPreference}; use syntax::ast; @@ -20,116 +17,122 @@ use syntax_pos::Span; use hir; #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub enum AutoAdjustment<'tcx> { - AdjustNeverToAny(Ty<'tcx>), // go from ! to any type - AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type - AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer - AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer - AdjustDerefRef(AutoDerefRef<'tcx>), +pub struct Adjustment<'tcx> { + pub kind: Adjust<'tcx>, + pub target: Ty<'tcx> } -/// Represents coercing a pointer to a different kind of pointer - where 'kind' -/// here means either or both of raw vs borrowed vs unique and fat vs thin. -/// -/// We transform pointers by following the following steps in order: -/// 1. Deref the pointer `self.autoderefs` times (may be 0). -/// 2. If `autoref` is `Some(_)`, then take the address and produce either a -/// `&` or `*` pointer. -/// 3. If `unsize` is `Some(_)`, then apply the unsize transformation, -/// which will do things like convert thin pointers to fat -/// pointers, or convert structs containing thin pointers to -/// structs containing fat pointers, or convert between fat -/// pointers. We don't store the details of how the transform is -/// done (in fact, we don't know that, because it might depend on -/// the precise type parameters). We just store the target -/// type. Trans figures out what has to be done at monomorphization -/// time based on the precise source/target type at hand. -/// -/// To make that more concrete, here are some common scenarios: -/// -/// 1. The simplest cases are where the pointer is not adjusted fat vs thin. -/// Here the pointer will be dereferenced N times (where a dereference can -/// happen to raw or borrowed pointers or any smart pointer which implements -/// Deref, including Box<_>). The number of dereferences is given by -/// `autoderefs`. It can then be auto-referenced zero or one times, indicated -/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is -/// None. -/// -/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start -/// with a thin pointer, deref a number of times, unsize the underlying data, -/// then autoref. The 'unsize' phase may change a fixed length array to a -/// dynamically sized one, a concrete object to a trait object, or statically -/// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is -/// represented by: -/// -/// ``` -/// AutoDerefRef { -/// autoderefs: 1, // &[i32; 4] -> [i32; 4] -/// autoref: Some(AutoPtr), // [i32] -> &[i32] -/// unsize: Some([i32]), // [i32; 4] -> [i32] -/// } -/// ``` -/// -/// Note that for a struct, the 'deep' unsizing of the struct is not recorded. -/// E.g., `struct Foo { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]> -/// The autoderef and -ref are the same as in the above example, but the type -/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about -/// the underlying conversions from `[i32; 4]` to `[i32]`. -/// -/// 3. Coercing a `Box` to `Box` is an interesting special case. In -/// that case, we have the pointer we need coming in, so there are no -/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. -/// At some point, of course, `Box` should move out of the compiler, in which -/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> -> -/// Box<[i32]> is represented by: -/// -/// ``` -/// AutoDerefRef { -/// autoderefs: 0, -/// autoref: None, -/// unsize: Some(Box<[i32]>), -/// } -/// ``` -#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub struct AutoDerefRef<'tcx> { - /// Step 1. Apply a number of dereferences, producing an lvalue. - pub autoderefs: usize, - - /// Step 2. Optionally produce a pointer/reference from the value. - pub autoref: Option>, - - /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to - /// `&[T]`. The stored type is the target pointer type. Note that - /// the source could be a thin or fat pointer. - pub unsize: Option>, +#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] +pub enum Adjust<'tcx> { + /// Go from ! to any type. + NeverToAny, + + /// Go from a fn-item type to a fn-pointer type. + ReifyFnPointer, + + /// Go from a safe fn pointer to an unsafe fn pointer. + UnsafeFnPointer, + + /// Go from a mut raw pointer to a const raw pointer. + MutToConstPointer, + + /// Represents coercing a pointer to a different kind of pointer - where 'kind' + /// here means either or both of raw vs borrowed vs unique and fat vs thin. + /// + /// We transform pointers by following the following steps in order: + /// 1. Deref the pointer `self.autoderefs` times (may be 0). + /// 2. If `autoref` is `Some(_)`, then take the address and produce either a + /// `&` or `*` pointer. + /// 3. If `unsize` is `Some(_)`, then apply the unsize transformation, + /// which will do things like convert thin pointers to fat + /// pointers, or convert structs containing thin pointers to + /// structs containing fat pointers, or convert between fat + /// pointers. We don't store the details of how the transform is + /// done (in fact, we don't know that, because it might depend on + /// the precise type parameters). We just store the target + /// type. Trans figures out what has to be done at monomorphization + /// time based on the precise source/target type at hand. + /// + /// To make that more concrete, here are some common scenarios: + /// + /// 1. The simplest cases are where the pointer is not adjusted fat vs thin. + /// Here the pointer will be dereferenced N times (where a dereference can + /// happen to raw or borrowed pointers or any smart pointer which implements + /// Deref, including Box<_>). The number of dereferences is given by + /// `autoderefs`. It can then be auto-referenced zero or one times, indicated + /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is + /// None. + /// + /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start + /// with a thin pointer, deref a number of times, unsize the underlying data, + /// then autoref. The 'unsize' phase may change a fixed length array to a + /// dynamically sized one, a concrete object to a trait object, or statically + /// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is + /// represented by: + /// + /// ``` + /// Adjust::DerefRef { + /// autoderefs: 1, // &[i32; 4] -> [i32; 4] + /// autoref: Some(AutoBorrow::Ref), // [i32] -> &[i32] + /// unsize: Some([i32]), // [i32; 4] -> [i32] + /// } + /// ``` + /// + /// Note that for a struct, the 'deep' unsizing of the struct is not recorded. + /// E.g., `struct Foo { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]> + /// The autoderef and -ref are the same as in the above example, but the type + /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about + /// the underlying conversions from `[i32; 4]` to `[i32]`. + /// + /// 3. Coercing a `Box` to `Box` is an interesting special case. In + /// that case, we have the pointer we need coming in, so there are no + /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. + /// At some point, of course, `Box` should move out of the compiler, in which + /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> -> + /// Box<[i32]> is represented by: + /// + /// ``` + /// Adjust::DerefRef { + /// autoderefs: 0, + /// autoref: None, + /// unsize: Some(Box<[i32]>), + /// } + /// ``` + DerefRef { + /// Step 1. Apply a number of dereferences, producing an lvalue. + autoderefs: usize, + + /// Step 2. Optionally produce a pointer/reference from the value. + autoref: Option>, + + /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to + /// `&[T]`. Note that the source could be a thin or fat pointer. + unsize: bool, + } } -impl<'tcx> AutoAdjustment<'tcx> { +impl<'tcx> Adjustment<'tcx> { pub fn is_identity(&self) -> bool { - match *self { - AdjustNeverToAny(ty) => ty.is_never(), - AdjustReifyFnPointer | - AdjustUnsafeFnPointer | - AdjustMutToConstPointer => false, - AdjustDerefRef(ref r) => r.is_identity(), + match self.kind { + Adjust::NeverToAny => self.target.is_never(), + + Adjust::DerefRef { autoderefs: 0, autoref: None, unsize: false } => true, + + Adjust::ReifyFnPointer | + Adjust::UnsafeFnPointer | + Adjust::MutToConstPointer | + Adjust::DerefRef {..} => false, } } } -impl<'tcx> AutoDerefRef<'tcx> { - pub fn is_identity(&self) -> bool { - self.autoderefs == 0 && self.unsize.is_none() && self.autoref.is_none() - } -} - #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] -pub enum AutoRef<'tcx> { +pub enum AutoBorrow<'tcx> { /// Convert from T to &T. - AutoPtr(&'tcx ty::Region, hir::Mutability), + Ref(&'tcx ty::Region, hir::Mutability), /// Convert from T to *T. - /// Value to thin pointer. - AutoUnsafe(hir::Mutability), + RawPtr(hir::Mutability), } #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] @@ -139,84 +142,6 @@ pub enum CustomCoerceUnsized { } impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> { - /// See `expr_ty_adjusted` - pub fn adjust(&'tcx self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - span: Span, - expr_id: ast::NodeId, - adjustment: Option<&AutoAdjustment<'tcx>>, - mut method_type: F) - -> Ty<'tcx> where - F: FnMut(ty::MethodCall) -> Option>, - { - if let ty::TyError = self.sty { - return self; - } - - return match adjustment { - Some(adjustment) => { - match *adjustment { - AdjustNeverToAny(ref ty) => ty, - - AdjustReifyFnPointer => { - match self.sty { - ty::TyFnDef(.., f) => tcx.mk_fn_ptr(f), - _ => { - bug!("AdjustReifyFnPointer adjustment on non-fn-item: {:?}", - self); - } - } - } - - AdjustUnsafeFnPointer => { - match self.sty { - ty::TyFnPtr(b) => tcx.safe_to_unsafe_fn_ty(b), - ref b => { - bug!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: {:?}", - b); - } - } - } - - AdjustMutToConstPointer => { - match self.sty { - ty::TyRawPtr(mt) => tcx.mk_ptr(ty::TypeAndMut { - ty: mt.ty, - mutbl: hir::MutImmutable - }), - ref b => { - bug!("AdjustMutToConstPointer on non-raw-ptr: {:?}", - b); - } - } - } - - AdjustDerefRef(ref adj) => { - let mut adjusted_ty = self; - - if !adjusted_ty.references_error() { - for i in 0..adj.autoderefs { - adjusted_ty = - adjusted_ty.adjust_for_autoderef(tcx, - expr_id, - span, - i as u32, - &mut method_type); - } - } - - if let Some(target) = adj.unsize { - target - } else { - adjusted_ty.adjust_for_autoref(tcx, adj.autoref) - } - } - } - } - None => self - }; - } - pub fn adjust_for_autoderef(&'tcx self, tcx: TyCtxt<'a, 'gcx, 'tcx>, expr_id: ast::NodeId, @@ -247,14 +172,14 @@ impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> { } pub fn adjust_for_autoref(&'tcx self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - autoref: Option>) + autoref: Option>) -> Ty<'tcx> { match autoref { None => self, - Some(AutoPtr(r, m)) => { + Some(AutoBorrow::Ref(r, m)) => { tcx.mk_ref(r, TypeAndMut { ty: self, mutbl: m }) } - Some(AutoUnsafe(m)) => { + Some(AutoBorrow::RawPtr(m)) => { tcx.mk_ptr(TypeAndMut { ty: self, mutbl: m }) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 9a707a49b093f..7e5e10435d516 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -212,7 +212,7 @@ pub struct Tables<'tcx> { /// other items. pub item_substs: NodeMap>, - pub adjustments: NodeMap>, + pub adjustments: NodeMap>, pub method_map: ty::MethodMap<'tcx>, @@ -287,7 +287,7 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { // Returns the type of an expression as a monotype. // // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in - // some cases, we insert `AutoAdjustment` annotations such as auto-deref or + // some cases, we insert `Adjustment` annotations such as auto-deref or // auto-ref. The type returned by this function does not consider such // adjustments. See `expr_ty_adjusted()` instead. // @@ -302,6 +302,17 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { self.node_id_to_type_opt(expr.id) } + /// Returns the type of `expr`, considering any `Adjustment` + /// entry recorded for that expression. + pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> { + self.adjustments.get(&expr.id) + .map_or_else(|| self.expr_ty(expr), |adj| adj.target) + } + + pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr) -> Option> { + self.adjustments.get(&expr.id) + .map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr)) + } pub fn is_method_call(&self, expr_id: NodeId) -> bool { self.method_map.contains_key(&ty::MethodCall::expr(expr_id)) diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index ae0a4a0e6bd11..b79ebdb14f552 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -176,8 +176,8 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { r.super_fold_with(self) } - fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>) - -> adjustment::AutoRef<'tcx> { + fn fold_autoref(&mut self, ar: &adjustment::AutoBorrow<'tcx>) + -> adjustment::AutoBorrow<'tcx> { ar.super_fold_with(self) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a378e22e5efd4..2c15f08e89822 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2124,34 +2124,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.tables.borrow() } - /// Returns the type of `expr`, considering any `AutoAdjustment` - /// entry recorded for that expression. - /// - /// It would almost certainly be better to store the adjusted ty in with - /// the `AutoAdjustment`, but I opted not to do this because it would - /// require serializing and deserializing the type and, although that's not - /// hard to do, I just hate that code so much I didn't want to touch it - /// unless it was to fix it properly, which seemed a distraction from the - /// thread at hand! -nmatsakis - pub fn expr_ty_adjusted(self, expr: &hir::Expr) -> Ty<'gcx> { - self.tables().expr_ty(expr) - .adjust(self.global_tcx(), expr.span, expr.id, - self.tables().adjustments.get(&expr.id), - |method_call| { - self.tables().method_map.get(&method_call).map(|method| method.ty) - }) - } - - pub fn expr_ty_adjusted_opt(self, expr: &hir::Expr) -> Option> { - self.tables().expr_ty_opt(expr).map(|t| t.adjust(self.global_tcx(), - expr.span, - expr.id, - self.tables().adjustments.get(&expr.id), - |method_call| { - self.tables().method_map.get(&method_call).map(|method| method.ty) - })) - } - pub fn expr_span(self, id: NodeId) -> Span { match self.map.find(id) { Some(ast_map::NodeExpr(e)) => { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 3165edebf1a46..9ca911837b517 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -218,15 +218,15 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ItemSubsts<'a> { } } -impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoRef<'a> { - type Lifted = ty::adjustment::AutoRef<'tcx>; +impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoBorrow<'a> { + type Lifted = ty::adjustment::AutoBorrow<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { match *self { - ty::adjustment::AutoPtr(r, m) => { - tcx.lift(&r).map(|r| ty::adjustment::AutoPtr(r, m)) + ty::adjustment::AutoBorrow::Ref(r, m) => { + tcx.lift(&r).map(|r| ty::adjustment::AutoBorrow::Ref(r, m)) } - ty::adjustment::AutoUnsafe(m) => { - Some(ty::adjustment::AutoUnsafe(m)) + ty::adjustment::AutoBorrow::RawPtr(m) => { + Some(ty::adjustment::AutoBorrow::RawPtr(m)) } } } @@ -676,13 +676,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { - ty::adjustment::AutoPtr(ref r, m) => { - ty::adjustment::AutoPtr(r.fold_with(folder), m) + ty::adjustment::AutoBorrow::Ref(ref r, m) => { + ty::adjustment::AutoBorrow::Ref(r.fold_with(folder), m) } - ty::adjustment::AutoUnsafe(m) => ty::adjustment::AutoUnsafe(m) + ty::adjustment::AutoBorrow::RawPtr(m) => ty::adjustment::AutoBorrow::RawPtr(m) } } @@ -692,8 +692,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { - ty::adjustment::AutoPtr(r, _m) => r.visit_with(visitor), - ty::adjustment::AutoUnsafe(_m) => false, + ty::adjustment::AutoBorrow::Ref(r, _m) => r.visit_with(visitor), + ty::adjustment::AutoBorrow::RawPtr(_m) => false, } } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 5ca567410291a..2ad2a23489de4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -436,32 +436,9 @@ impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> { } } -impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> { +impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::adjustment::AdjustNeverToAny(ref target) => { - write!(f, "AdjustNeverToAny({:?})", target) - } - ty::adjustment::AdjustReifyFnPointer => { - write!(f, "AdjustReifyFnPointer") - } - ty::adjustment::AdjustUnsafeFnPointer => { - write!(f, "AdjustUnsafeFnPointer") - } - ty::adjustment::AdjustMutToConstPointer => { - write!(f, "AdjustMutToConstPointer") - } - ty::adjustment::AdjustDerefRef(ref data) => { - write!(f, "{:?}", data) - } - } - } -} - -impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "AutoDerefRef({}, unsize={:?}, {:?})", - self.autoderefs, self.unsize, self.autoref) + write!(f, "{:?} -> {}", self.kind, self.target) } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 6afcd18df0ad3..b3c0e9ef2b727 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -34,7 +34,6 @@ use middle::stability; use rustc::cfg; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::adjustment; use rustc::traits::{self, Reveal}; use rustc::hir::map as hir_map; use util::nodemap::NodeSet; @@ -941,6 +940,8 @@ impl LateLintPass for UnconditionalRecursion { method: &ty::Method, id: ast::NodeId) -> bool { + use rustc::ty::adjustment::*; + // Check for method calls and overloaded operators. let opt_m = tcx.tables().method_map.get(&ty::MethodCall::expr(id)).cloned(); if let Some(m) = opt_m { @@ -951,8 +952,8 @@ impl LateLintPass for UnconditionalRecursion { // Check for overloaded autoderef method calls. let opt_adj = tcx.tables().adjustments.get(&id).cloned(); - if let Some(adjustment::AdjustDerefRef(adj)) = opt_adj { - for i in 0..adj.autoderefs { + if let Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) = opt_adj { + for i in 0..autoderefs { let method_call = ty::MethodCall::autoderef(id, i as u32); if let Some(m) = tcx.tables().method_map.get(&method_call) .cloned() { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 2df09aa25c8be..15430a5c9f99d 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -442,15 +442,14 @@ impl LateLintPass for UnusedAllocation { } if let Some(adjustment) = cx.tcx.tables().adjustments.get(&e.id) { - if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef { ref autoref, .. }) = - *adjustment { + if let adjustment::Adjust::DerefRef { autoref, .. } = adjustment.kind { match autoref { - &Some(adjustment::AutoPtr(_, hir::MutImmutable)) => { + Some(adjustment::AutoBorrow::Ref(_, hir::MutImmutable)) => { cx.span_lint(UNUSED_ALLOCATION, e.span, "unnecessary allocation, use & instead"); } - &Some(adjustment::AutoPtr(_, hir::MutMutable)) => { + Some(adjustment::AutoBorrow::Ref(_, hir::MutMutable)) => { cx.span_lint(UNUSED_ALLOCATION, e.span, "unnecessary allocation, use &mut instead"); diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 63ec6a7069bb2..e009955b92ee4 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -38,7 +38,7 @@ enum TableEntry<'tcx> { Def(Def), NodeType(Ty<'tcx>), ItemSubsts(ty::ItemSubsts<'tcx>), - Adjustment(ty::adjustment::AutoAdjustment<'tcx>), + Adjustment(ty::adjustment::Adjustment<'tcx>), ConstQualif(ConstQualif), } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 58526a3444e24..b37dd8dd0a907 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -233,7 +233,7 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, ast_expr: &'tcx hir::Expr) -> (Mir<'tcx>, ScopeAuxiliaryVec) { let tcx = hir.tcx(); - let ty = tcx.expr_ty_adjusted(ast_expr); + let ty = tcx.tables().expr_ty_adjusted(ast_expr); let span = tcx.map.span(item_id); let mut builder = Builder::new(hir, span, 0, ty); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index ddf487e9d7659..ba0d3b49a6c1a 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -35,15 +35,15 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); let mut expr = make_mirror_unadjusted(cx, self); + let adj = cx.tcx.tables().adjustments.get(&self.id).cloned(); debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}", - expr, cx.tcx.tables().adjustments.get(&self.id)); + expr, adj); // Now apply adjustments, if any. - match cx.tcx.tables().adjustments.get(&self.id) { + match adj.map(|adj| (adj.kind, adj.target)) { None => {} - Some(&ty::adjustment::AdjustReifyFnPointer) => { - let adjusted_ty = cx.tcx.expr_ty_adjusted(self); + Some((ty::adjustment::Adjust::ReifyFnPointer, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -51,8 +51,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::ReifyFnPointer { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustUnsafeFnPointer) => { - let adjusted_ty = cx.tcx.expr_ty_adjusted(self); + Some((ty::adjustment::Adjust::UnsafeFnPointer, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -60,7 +59,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustNeverToAny(adjusted_ty)) => { + Some((ty::adjustment::Adjust::NeverToAny, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -68,8 +67,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::NeverToAny { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustMutToConstPointer) => { - let adjusted_ty = cx.tcx.expr_ty_adjusted(self); + Some((ty::adjustment::Adjust::MutToConstPointer, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -77,8 +75,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::Cast { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustDerefRef(ref adj)) => { - for i in 0..adj.autoderefs { + Some((ty::adjustment::Adjust::DerefRef { autoderefs, autoref, unsize }, + adjusted_ty)) => { + for i in 0..autoderefs { let i = i as u32; let adjusted_ty = expr.ty.adjust_for_autoderef( @@ -128,10 +127,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { }; } - if let Some(autoref) = adj.autoref { + if let Some(autoref) = autoref { let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref)); match autoref { - ty::adjustment::AutoPtr(r, m) => { + ty::adjustment::AutoBorrow::Ref(r, m) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -143,7 +142,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { }, }; } - ty::adjustment::AutoUnsafe(m) => { + ty::adjustment::AutoBorrow::RawPtr(m) => { // Convert this to a suitable `&foo` and // then an unsafe coercion. Limit the region to be just this // expression. @@ -169,10 +168,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { } } - if let Some(target) = adj.unsize { + if unsize { expr = Expr { temp_lifetime: temp_lifetime, - ty: target, + ty: adjusted_ty, span: self.span, kind: ExprKind::Unsize { source: expr.to_ref() }, }; @@ -578,7 +577,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Loop { condition: None, body: block::to_expr_ref(cx, body) }, hir::ExprField(ref source, name) => { - let index = match cx.tcx.expr_ty_adjusted(source).sty { + let index = match cx.tcx.tables().expr_ty_adjusted(source).sty { ty::TyAdt(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node), ref ty => @@ -893,7 +892,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, argrefs.extend( args.iter() .map(|arg| { - let arg_ty = cx.tcx.expr_ty_adjusted(arg); + let arg_ty = cx.tcx.tables().expr_ty_adjusted(arg); let adjusted_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: arg_ty, diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 20e9e76ab843d..f23539e88f78d 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -625,14 +625,16 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node /// Check the adjustments of an expression fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) { - match v.tcx.tables().adjustments.get(&e.id) { + use rustc::ty::adjustment::*; + + match v.tcx.tables().adjustments.get(&e.id).map(|adj| adj.kind) { None | - Some(&ty::adjustment::AdjustNeverToAny(..)) | - Some(&ty::adjustment::AdjustReifyFnPointer) | - Some(&ty::adjustment::AdjustUnsafeFnPointer) | - Some(&ty::adjustment::AdjustMutToConstPointer) => {} + Some(Adjust::NeverToAny) | + Some(Adjust::ReifyFnPointer) | + Some(Adjust::UnsafeFnPointer) | + Some(Adjust::MutToConstPointer) => {} - Some(&ty::adjustment::AdjustDerefRef(ty::adjustment::AutoDerefRef { autoderefs, .. })) => { + Some(Adjust::DerefRef { autoderefs, .. }) => { if (0..autoderefs as u32) .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) { v.add_qualif(ConstQualif::NOT_CONST); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 3a092613a054a..db4788c3ceadb 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1380,7 +1380,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> return; } }; - let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty; + let ty = &self.tcx.tables().expr_ty_adjusted(&hir_node).sty; match *ty { ty::TyAdt(def, _) => { let sub_span = self.span.sub_span_after_token(ex.span, token::Dot); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c111824a30cb5..7e008f741624b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -418,7 +418,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_expr_data(&self, expr: &ast::Expr) -> Option { let hir_node = self.tcx.map.expect_expr(expr.id); - let ty = self.tcx.expr_ty_adjusted_opt(&hir_node); + let ty = self.tcx.tables().expr_ty_adjusted_opt(&hir_node); if ty.is_none() || ty.unwrap().sty == ty::TyError { return None; } @@ -432,7 +432,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { return None; } }; - match self.tcx.expr_ty_adjusted(&hir_node).sty { + match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let f = def.struct_variant().field_named(ident.node.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); @@ -451,7 +451,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprKind::Struct(ref path, ..) => { - match self.tcx.expr_ty_adjusted(&hir_node).sty { + match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index c5a21d7dd91ce..3cf64fa439d7d 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -103,7 +103,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match self.structurally_resolved_type(callee_expr.span, adjusted_ty).sty { ty::TyFnDef(..) | ty::TyFnPtr(_) => { - self.write_autoderef_adjustment(callee_expr.id, autoderefs); + self.write_autoderef_adjustment(callee_expr.id, autoderefs, adjusted_ty); return Some(CallStep::Builtin); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index ccc944813ff18..16493412d690b 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -65,10 +65,7 @@ use check::FnCtxt; use rustc::hir; use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace}; use rustc::traits::{self, ObligationCause}; -use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef}; -use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer}; -use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer}; -use rustc::ty::adjustment::AdjustNeverToAny; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; @@ -93,7 +90,7 @@ impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> { } } -type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, AutoAdjustment<'tcx>)>; +type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, Adjust<'tcx>)>; fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability, to_mutbl: hir::Mutability) @@ -144,12 +141,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { /// Synthesize an identity adjustment. fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> { - Ok((ty, - AdjustDerefRef(AutoDerefRef { - autoderefs: 0, - autoref: None, - unsize: None, - }))) + Ok((ty, Adjust::DerefRef { + autoderefs: 0, + autoref: None, + unsize: false, + })) } fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> @@ -166,7 +162,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } if a.is_never() { - return Ok((b, AdjustNeverToAny(b))); + return Ok((b, Adjust::NeverToAny)); } // Consider coercing the subtype to a DST @@ -396,17 +392,16 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { ty::TyRef(r_borrow, _) => r_borrow, _ => span_bug!(span, "expected a ref type, got {:?}", ty), }; - let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl)); + let autoref = Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl)); debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}", ty, autoderefs, autoref); - Ok((ty, - AdjustDerefRef(AutoDerefRef { - autoderefs: autoderefs, - autoref: autoref, - unsize: None, - }))) + Ok((ty, Adjust::DerefRef { + autoderefs: autoderefs, + autoref: autoref, + unsize: false, + })) } @@ -437,11 +432,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let coercion = Coercion(self.origin.span()); let r_borrow = self.next_region_var(coercion); - (mt_a.ty, Some(AutoPtr(r_borrow, mt_b.mutbl))) + (mt_a.ty, Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl))) } (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => { coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?; - (mt_a.ty, Some(AutoUnsafe(mt_b.mutbl))) + (mt_a.ty, Some(AutoBorrow::RawPtr(mt_b.mutbl))) } _ => (source, None), }; @@ -497,13 +492,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { *self.unsizing_obligations.borrow_mut() = leftover_predicates; - let adjustment = AutoDerefRef { + let adjustment = Adjust::DerefRef { autoderefs: if reborrow.is_some() { 1 } else { 0 }, autoref: reborrow, - unsize: Some(target), + unsize: true, }; debug!("Success, coerced with {:?}", adjustment); - Ok((target, AdjustDerefRef(adjustment))) + Ok((target, adjustment)) } fn coerce_from_safe_fn(&self, @@ -516,7 +511,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); return self.unify_and_identity(unsafe_a, b) - .map(|(ty, _)| (ty, AdjustUnsafeFnPointer)); + .map(|(ty, _)| (ty, Adjust::UnsafeFnPointer)); } _ => {} } @@ -555,7 +550,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { ty::TyFnPtr(_) => { let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a); self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b) - .map(|(ty, _)| (ty, AdjustReifyFnPointer)) + .map(|(ty, _)| (ty, Adjust::ReifyFnPointer)) } _ => self.unify_and_identity(a, b), } @@ -585,17 +580,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { coerce_mutbls(mt_a.mutbl, mutbl_b)?; // Although references and unsafe ptrs have the same - // representation, we still register an AutoDerefRef so that + // representation, we still register an Adjust::DerefRef so that // regionck knows that the region for `a` must be valid here. Ok((ty, if is_ref { - AdjustDerefRef(AutoDerefRef { + Adjust::DerefRef { autoderefs: 1, - autoref: Some(AutoUnsafe(mutbl_b)), - unsize: None, - }) + autoref: Some(AutoBorrow::RawPtr(mutbl_b)), + unsize: false, + } } else if mt_a.mutbl != mutbl_b { - AdjustMutToConstPointer + Adjust::MutToConstPointer } else { noop })) @@ -606,24 +601,25 @@ fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) - -> CoerceResult<'tcx> + -> RelateResult<'tcx, Adjustment<'tcx>> where E: Fn() -> I, I: IntoIterator { - let (ty, adjustment) = indent(|| coerce.coerce(exprs, a, b))?; + let (ty, adjust) = indent(|| coerce.coerce(exprs, a, b))?; let fcx = coerce.fcx; - if let AdjustDerefRef(auto) = adjustment { - if auto.unsize.is_some() { - let mut obligations = coerce.unsizing_obligations.borrow_mut(); - for obligation in obligations.drain(..) { - fcx.register_predicate(obligation); - } + if let Adjust::DerefRef { unsize: true, .. } = adjust { + let mut obligations = coerce.unsizing_obligations.borrow_mut(); + for obligation in obligations.drain(..) { + fcx.register_predicate(obligation); } } - Ok((ty, adjustment)) + Ok(Adjustment { + kind: adjust, + target: ty + }) } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { @@ -641,17 +637,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span)); self.commit_if_ok(|_| { - let (ty, adjustment) = apply(&mut coerce, &|| Some(expr), source, target)?; + let adjustment = apply(&mut coerce, &|| Some(expr), source, target)?; if !adjustment.is_identity() { debug!("Success, coerced with {:?}", adjustment); match self.tables.borrow().adjustments.get(&expr.id) { None | - Some(&AdjustNeverToAny(..)) => (), + Some(&Adjustment { kind: Adjust::NeverToAny, .. }) => (), _ => bug!("expr already has an adjustment on it!"), }; self.write_adjustment(expr.id, adjustment); } - Ok(ty) + Ok(adjustment.target) }) } @@ -705,12 +701,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Reify both sides and return the reified fn pointer type. + let fn_ptr = self.tcx.mk_fn_ptr(fty); for expr in exprs().into_iter().chain(Some(new)) { // No adjustments can produce a fn item, so this should never trip. assert!(!self.tables.borrow().adjustments.contains_key(&expr.id)); - self.write_adjustment(expr.id, AdjustReifyFnPointer); + self.write_adjustment(expr.id, Adjustment { + kind: Adjust::ReifyFnPointer, + target: fn_ptr + }); } - return Ok(self.tcx.mk_fn_ptr(fty)); + return Ok(fn_ptr); } _ => {} } @@ -724,11 +724,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !self.tables.borrow().adjustments.contains_key(&new.id) { let result = self.commit_if_ok(|_| apply(&mut coerce, &|| Some(new), new_ty, prev_ty)); match result { - Ok((ty, adjustment)) => { + Ok(adjustment) => { if !adjustment.is_identity() { self.write_adjustment(new.id, adjustment); } - return Ok(ty); + return Ok(adjustment.target); } Err(e) => first_error = Some(e), } @@ -738,10 +738,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This requires ensuring there are no coercions applied to *any* of the // previous expressions, other than noop reborrows (ignoring lifetimes). for expr in exprs() { - let noop = match self.tables.borrow().adjustments.get(&expr.id) { - Some(&AdjustDerefRef(AutoDerefRef { autoderefs: 1, - autoref: Some(AutoPtr(_, mutbl_adj)), - unsize: None })) => { + let noop = match self.tables.borrow().adjustments.get(&expr.id).map(|adj| adj.kind) { + Some(Adjust::DerefRef { + autoderefs: 1, + autoref: Some(AutoBorrow::Ref(_, mutbl_adj)), + unsize: false + }) => { match self.node_ty(expr.id).sty { ty::TyRef(_, mt_orig) => { // Reborrow that we can safely ignore. @@ -750,7 +752,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => false, } } - Some(&AdjustNeverToAny(_)) => true, + Some(Adjust::NeverToAny) => true, Some(_) => false, None => true, }; @@ -783,18 +785,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }) } } - Ok((ty, adjustment)) => { + Ok(adjustment) => { if !adjustment.is_identity() { + let mut tables = self.tables.borrow_mut(); for expr in exprs() { - let previous = self.tables.borrow().adjustments.get(&expr.id).cloned(); - if let Some(AdjustNeverToAny(_)) = previous { - self.write_adjustment(expr.id, AdjustNeverToAny(ty)); - } else { - self.write_adjustment(expr.id, adjustment); + if let Some(&mut Adjustment { + kind: Adjust::NeverToAny, + ref mut target + }) = tables.adjustments.get_mut(&expr.id) { + *target = adjustment.target; + continue; } + tables.adjustments.insert(expr.id, adjustment); } } - Ok(ty) + Ok(adjustment.target) } } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 722089cd50c0c..f88bb355d1270 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -15,7 +15,7 @@ use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; -use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::fold::TypeFoldable; use rustc::infer::{self, InferOk, TypeOrigin}; use syntax_pos::Span; @@ -140,20 +140,19 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) -> Ty<'tcx> { - let (autoref, unsize) = if let Some(mutbl) = pick.autoref { + let autoref = if let Some(mutbl) = pick.autoref { let region = self.next_region_var(infer::Autoref(self.span)); - let autoref = AutoPtr(region, mutbl); - (Some(autoref), - pick.unsize.map(|target| target.adjust_for_autoref(self.tcx, Some(autoref)))) + Some(AutoBorrow::Ref(region, mutbl)) } else { // No unsizing should be performed without autoref (at // least during method dispach). This is because we // currently only unsize `[T;N]` to `[T]`, and naturally // that must occur being a reference. assert!(pick.unsize.is_none()); - (None, None) + None }; + // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various tables. let mut autoderef = self.autoderef(self.span, unadjusted_self_ty); @@ -163,19 +162,20 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { autoderef.unambiguous_final_ty(); autoderef.finalize(LvaluePreference::NoPreference, Some(self.self_expr)); + let target = pick.unsize.unwrap_or(autoderefd_ty); + let target = target.adjust_for_autoref(self.tcx, autoref); + // Write out the final adjustment. - self.write_adjustment(self.self_expr.id, - AdjustDerefRef(AutoDerefRef { - autoderefs: pick.autoderefs, - autoref: autoref, - unsize: unsize, - })); - - if let Some(target) = unsize { - target - } else { - autoderefd_ty.adjust_for_autoref(self.tcx, autoref) - } + self.write_adjustment(self.self_expr.id, Adjustment { + kind: Adjust::DerefRef { + autoderefs: pick.autoderefs, + autoref: autoref, + unsize: pick.unsize.is_some(), + }, + target: target + }); + + target } /////////////////////////////////////////////////////////////////////////// @@ -463,29 +463,23 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Fix up autoderefs and derefs. for (i, &expr) in exprs.iter().rev().enumerate() { + debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr); + // Count autoderefs. - let autoderef_count = match self.tables - .borrow() - .adjustments - .get(&expr.id) { - Some(&AdjustDerefRef(ref adj)) => adj.autoderefs, - Some(_) | None => 0, - }; - - debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?} \ - autoderef_count={}", - i, - expr, - autoderef_count); - - if autoderef_count > 0 { - let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id)); - autoderef.nth(autoderef_count).unwrap_or_else(|| { - span_bug!(expr.span, - "expr was deref-able {} times but now isn't?", - autoderef_count); - }); - autoderef.finalize(PreferMutLvalue, Some(expr)); + let adjustment = self.tables.borrow().adjustments.get(&expr.id).cloned(); + match adjustment { + Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => { + if autoderefs > 0 { + let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id)); + autoderef.nth(autoderefs).unwrap_or_else(|| { + span_bug!(expr.span, + "expr was deref-able {} times but now isn't?", + autoderefs); + }); + autoderef.finalize(PreferMutLvalue, Some(expr)); + } + } + Some(_) | None => {} } // Don't retry the first one or we might infinite loop! @@ -503,45 +497,55 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // ought to recode this routine so it doesn't // (ab)use the normal type checking paths. let adj = self.tables.borrow().adjustments.get(&base_expr.id).cloned(); - let (autoderefs, unsize) = match adj { - Some(AdjustDerefRef(adr)) => { - match adr.autoref { + let (autoderefs, unsize, adjusted_base_ty) = match adj { + Some(Adjustment { + kind: Adjust::DerefRef { autoderefs, autoref, unsize }, + target + }) => { + match autoref { None => { - assert!(adr.unsize.is_none()); - (adr.autoderefs, None) - } - Some(AutoPtr(..)) => { - (adr.autoderefs, - adr.unsize.map(|target| { - target.builtin_deref(false, NoPreference) - .expect("fixup: AutoPtr is not &T") - .ty - })) + assert!(!unsize); } + Some(AutoBorrow::Ref(..)) => {} Some(_) => { span_bug!(base_expr.span, "unexpected adjustment autoref {:?}", - adr); + adj); } } + + (autoderefs, unsize, if unsize { + target.builtin_deref(false, NoPreference) + .expect("fixup: AutoBorrow::Ref is not &T") + .ty + } else { + let ty = self.node_ty(base_expr.id); + let mut ty = self.shallow_resolve(ty); + let mut method_type = |method_call: ty::MethodCall| { + self.tables.borrow().method_map.get(&method_call).map(|m| { + self.resolve_type_vars_if_possible(&m.ty) + }) + }; + + if !ty.references_error() { + for i in 0..autoderefs { + ty = ty.adjust_for_autoderef(self.tcx, + base_expr.id, + base_expr.span, + i as u32, + &mut method_type); + } + } + + ty + }) } - None => (0, None), + None => (0, false, self.node_ty(base_expr.id)), Some(_) => { span_bug!(base_expr.span, "unexpected adjustment type"); } }; - let (adjusted_base_ty, unsize) = if let Some(target) = unsize { - (target, true) - } else { - (self.adjust_expr_ty(base_expr, - Some(&AdjustDerefRef(AutoDerefRef { - autoderefs: autoderefs, - autoref: None, - unsize: None, - }))), - false) - }; let index_expr_ty = self.node_ty(index_expr.id); let result = self.try_index_step(ty::MethodCall::expr(expr.id), diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f084b85a45f81..2df562f9ade46 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -16,7 +16,7 @@ use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; -use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::infer; use syntax::ast; @@ -294,11 +294,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { unsize, method_ty.explicit_self); - match method_ty.explicit_self { + let autoref = match method_ty.explicit_self { ty::ExplicitSelfCategory::ByValue => { // Trait method is fn(self), no transformation needed. assert!(!unsize); - self.write_autoderef_adjustment(self_expr.id, autoderefs); + None } ty::ExplicitSelfCategory::ByReference(..) => { @@ -306,16 +306,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // autoref. Pull the region etc out of the type of first argument. match transformed_self_ty.sty { ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => { - self.write_adjustment(self_expr.id, - AdjustDerefRef(AutoDerefRef { - autoderefs: autoderefs, - autoref: Some(AutoPtr(region, mutbl)), - unsize: if unsize { - Some(transformed_self_ty) - } else { - None - }, - })); + Some(AutoBorrow::Ref(region, mutbl)) } _ => { @@ -331,7 +322,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "unexpected explicit self type in operator method: {:?}", method_ty.explicit_self); } - } + }; + + self.write_adjustment(self_expr.id, Adjustment { + kind: Adjust::DerefRef { + autoderefs: autoderefs, + autoref: autoref, + unsize: unsize + }, + target: transformed_self_ty + }); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3fec347b75b93..1c9c80bb7fc61 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1564,20 +1564,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn write_autoderef_adjustment(&self, node_id: ast::NodeId, - derefs: usize) { - self.write_adjustment( - node_id, - adjustment::AdjustDerefRef(adjustment::AutoDerefRef { + derefs: usize, + adjusted_ty: Ty<'tcx>) { + self.write_adjustment(node_id, adjustment::Adjustment { + kind: adjustment::Adjust::DerefRef { autoderefs: derefs, autoref: None, - unsize: None - }) - ); + unsize: false + }, + target: adjusted_ty + }); } pub fn write_adjustment(&self, node_id: ast::NodeId, - adj: adjustment::AutoAdjustment<'tcx>) { + adj: adjustment::Adjustment<'tcx>) { debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj); if adj.is_identity() { @@ -1743,21 +1744,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { t } - /// Apply `adjustment` to the type of `expr` - pub fn adjust_expr_ty(&self, - expr: &hir::Expr, - adjustment: Option<&adjustment::AutoAdjustment<'tcx>>) - -> Ty<'tcx> - { - let raw_ty = self.node_ty(expr.id); - let raw_ty = self.shallow_resolve(raw_ty); - let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty); - raw_ty.adjust(self.tcx, expr.span, expr.id, adjustment, |method_call| { - self.tables.borrow().method_map.get(&method_call) - .map(|method| resolve_ty(method.ty)) - }) - } - pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { match self.tables.borrow().node_types.get(&id) { Some(&t) => t, @@ -2294,7 +2280,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("try_index_step: success, using built-in indexing"); // If we had `[T; N]`, we should've caught it before unsizing to `[T]`. assert!(!unsize); - self.write_autoderef_adjustment(base_expr.id, autoderefs); + self.write_autoderef_adjustment(base_expr.id, autoderefs, adjusted_ty); return Some((tcx.types.usize, ty)); } _ => {} @@ -2850,9 +2836,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // In case we did perform an adjustment, we have to update // the type of the block, because old trans still uses it. - let adj = self.tables.borrow().adjustments.get(&then.id).cloned(); - if res.is_ok() && adj.is_some() { - self.write_ty(then_blk.id, self.adjust_expr_ty(then, adj.as_ref())); + if res.is_ok() { + let adj = self.tables.borrow().adjustments.get(&then.id).cloned(); + if let Some(adj) = adj { + self.write_ty(then_blk.id, adj.target); + } } res @@ -2913,7 +2901,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let field_ty = self.field_ty(expr.span, field, substs); if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { autoderef.finalize(lvalue_pref, Some(base)); - self.write_autoderef_adjustment(base.id, autoderefs); + self.write_autoderef_adjustment(base.id, autoderefs, base_t); return field_ty; } private_candidate = Some((base_def.did, field_ty)); @@ -3031,7 +3019,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(field_ty) = field { autoderef.finalize(lvalue_pref, Some(base)); - self.write_autoderef_adjustment(base.id, autoderefs); + self.write_autoderef_adjustment(base.id, autoderefs, base_t); return field_ty; } } @@ -3341,8 +3329,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if ty.is_never() { if let Some(hir::map::NodeExpr(_)) = self.tcx.map.find(expr.id) { let adj_ty = self.next_diverging_ty_var(); - let adj = adjustment::AdjustNeverToAny(adj_ty); - self.write_adjustment(expr.id, adj); + self.write_adjustment(expr.id, adjustment::Adjustment { + kind: adjustment::Adjust::NeverToAny, + target: adj_ty + }); return adj_ty; } } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 939deee27c602..63f7a59f24fde 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -259,23 +259,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.resolve_type(t) } - fn resolve_method_type(&self, method_call: MethodCall) -> Option> { - let method_ty = self.tables.borrow().method_map - .get(&method_call).map(|method| method.ty); - method_ty.map(|method_ty| self.resolve_type(method_ty)) - } - /// Try to resolve the type for the given node. pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> { - let ty_unadjusted = self.resolve_node_type(expr.id); - if ty_unadjusted.references_error() { - ty_unadjusted - } else { - ty_unadjusted.adjust( - self.tcx, expr.span, expr.id, - self.tables.borrow().adjustments.get(&expr.id), - |method_call| self.resolve_method_type(method_call)) - } + let ty = self.tables.borrow().expr_ty_adjusted(expr); + self.resolve_type(ty) } fn visit_fn_body(&mut self, @@ -558,10 +545,8 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> { let adjustment = self.tables.borrow().adjustments.get(&expr.id).map(|a| a.clone()); if let Some(adjustment) = adjustment { debug!("adjustment={:?}", adjustment); - match adjustment { - adjustment::AdjustDerefRef(adjustment::AutoDerefRef { - autoderefs, ref autoref, .. - }) => { + match adjustment.kind { + adjustment::Adjust::DerefRef { autoderefs, ref autoref, .. } => { let expr_ty = self.resolve_node_type(expr.id); self.constrain_autoderefs(expr, autoderefs, expr_ty); if let Some(ref autoref) = *autoref { @@ -951,7 +936,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let origin = infer::ParameterOrigin::OverloadedDeref; self.substs_wf_in_scope(origin, method.substs, deref_expr.span, r_deref_expr); - // Treat overloaded autoderefs as if an AutoRef adjustment + // Treat overloaded autoderefs as if an AutoBorrow adjustment // was applied on the base type, as that is always the case. let fn_sig = method.ty.fn_sig(); let fn_sig = // late-bound regions should have been instantiated @@ -1065,15 +1050,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { id: ast::NodeId, minimum_lifetime: &'tcx ty::Region) { - let tcx = self.tcx; - // Try to resolve the type. If we encounter an error, then typeck // is going to fail anyway, so just stop here and let typeck // report errors later on in the writeback phase. let ty0 = self.resolve_node_type(id); - let ty = ty0.adjust(tcx, origin.span(), id, - self.tables.borrow().adjustments.get(&id), - |method_call| self.resolve_method_type(method_call)); + let ty = self.tables.borrow().adjustments.get(&id).map_or(ty0, |adj| adj.target); + let ty = self.resolve_type(ty); debug!("constrain_regions_in_type_of_node(\ ty={}, ty0={}, id={}, minimum_lifetime={:?})", ty, ty0, @@ -1170,7 +1152,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn link_autoref(&self, expr: &hir::Expr, autoderefs: usize, - autoref: &adjustment::AutoRef<'tcx>) + autoref: &adjustment::AutoBorrow<'tcx>) { debug!("link_autoref(autoref={:?})", autoref); let mc = mc::MemCategorizationContext::new(self); @@ -1178,12 +1160,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { debug!("expr_cmt={:?}", expr_cmt); match *autoref { - adjustment::AutoPtr(r, m) => { + adjustment::AutoBorrow::Ref(r, m) => { self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt); } - adjustment::AutoUnsafe(m) => { + adjustment::AutoBorrow::RawPtr(m) => { let r = self.tcx.node_scope_region(expr.id); self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 688bcbdcd121c..5ef3e8699602b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -381,36 +381,40 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } Some(adjustment) => { - let resolved_adjustment = match adjustment { - adjustment::AdjustNeverToAny(ty) => { - adjustment::AdjustNeverToAny(self.resolve(&ty, reason)) + let resolved_adjustment = match adjustment.kind { + adjustment::Adjust::NeverToAny => { + adjustment::Adjust::NeverToAny } - adjustment::AdjustReifyFnPointer => { - adjustment::AdjustReifyFnPointer + adjustment::Adjust::ReifyFnPointer => { + adjustment::Adjust::ReifyFnPointer } - adjustment::AdjustMutToConstPointer => { - adjustment::AdjustMutToConstPointer + adjustment::Adjust::MutToConstPointer => { + adjustment::Adjust::MutToConstPointer } - adjustment::AdjustUnsafeFnPointer => { - adjustment::AdjustUnsafeFnPointer + adjustment::Adjust::UnsafeFnPointer => { + adjustment::Adjust::UnsafeFnPointer } - adjustment::AdjustDerefRef(adj) => { - for autoderef in 0..adj.autoderefs { + adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => { + for autoderef in 0..autoderefs { let method_call = MethodCall::autoderef(id, autoderef as u32); self.visit_method_map_entry(reason, method_call); } - adjustment::AdjustDerefRef(adjustment::AutoDerefRef { - autoderefs: adj.autoderefs, - autoref: self.resolve(&adj.autoref, reason), - unsize: self.resolve(&adj.unsize, reason), - }) + adjustment::Adjust::DerefRef { + autoderefs: autoderefs, + autoref: self.resolve(&autoref, reason), + unsize: unsize, + } } }; + let resolved_adjustment = adjustment::Adjustment { + kind: resolved_adjustment, + target: self.resolve(&adjustment.target, reason) + }; debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); self.tcx().tables.borrow_mut().adjustments.insert( id, resolved_adjustment); From 942f909c1f6d2d203661831366e828ef030588c6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 2 Nov 2016 19:08:10 +0100 Subject: [PATCH 11/41] Add missing urls for ErrorKind's variants --- src/libstd/io/error.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index ddf0030858eda..54372d91c893e 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -124,23 +124,28 @@ pub enum ErrorKind { InvalidInput, /// Data not valid for the operation were encountered. /// - /// Unlike `InvalidInput`, this typically means that the operation + /// Unlike [`InvalidInput`], this typically means that the operation /// parameters were valid, however the error was caused by malformed /// input data. /// /// For example, a function that reads a file into a string will error with /// `InvalidData` if the file's contents are not valid UTF-8. + /// + /// [`InvalidInput`]: #variant.InvalidInput #[stable(feature = "io_invalid_data", since = "1.2.0")] InvalidData, /// The I/O operation's timeout expired, causing it to be canceled. #[stable(feature = "rust1", since = "1.0.0")] TimedOut, /// An error returned when an operation could not be completed because a - /// call to `write` returned `Ok(0)`. + /// call to [`write()`] returned [`Ok(0)`]. /// /// This typically means that an operation could only succeed if it wrote a /// particular number of bytes but only a smaller number of bytes could be /// written. + /// + /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`Ok(0)`]: ../../std/io/type.Result.html #[stable(feature = "rust1", since = "1.0.0")] WriteZero, /// This operation was interrupted. From 50ecee241008a17a3d296f0a0d2a4ff9080a5c57 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 15 Sep 2016 00:51:46 +0300 Subject: [PATCH 12/41] Add feature gate for Self and associated types in struct expressions and patterns --- src/librustc_typeck/check/mod.rs | 10 +++++++ src/libsyntax/feature_gate.rs | 3 ++ .../struct-path-associated-type.rs | 2 ++ .../struct-path-self-feature-gate.rs | 29 +++++++++++++++++++ .../struct-path-self-type-mismatch.rs | 2 ++ src/test/compile-fail/struct-path-self.rs | 2 ++ .../run-pass/struct-path-associated-type.rs | 2 ++ src/test/run-pass/struct-path-self.rs | 2 ++ 8 files changed, 52 insertions(+) create mode 100644 src/test/compile-fail/struct-path-self-feature-gate.rs diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 75a14bb3db922..9a40cbb824a04 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3235,6 +3235,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { + match def { + Def::AssociatedTy(..) | Def::SelfTy(..) + if !self.tcx.sess.features.borrow().more_struct_aliases => { + emit_feature_err(&self.tcx.sess.parse_sess, + "more_struct_aliases", path.span, GateIssue::Language, + "`Self` and associated types in struct \ + expressions and patterns are unstable"); + } + _ => {} + } match ty.sty { ty::TyAdt(adt, substs) if !adt.is_enum() => { Some((adt.struct_variant(), adt.did, substs)) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 129e4a8233803..69dfe8e862095 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -309,6 +309,9 @@ declare_features! ( // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (active, field_init_shorthand, "1.14.0", Some(37340)), + + // Allows using `Self` and associated types in struct expressions and patterns. + (active, more_struct_aliases, "1.14.0", Some(37544)), ); declare_features! ( diff --git a/src/test/compile-fail/struct-path-associated-type.rs b/src/test/compile-fail/struct-path-associated-type.rs index 660ac44ce0b53..ecaf269fcb1ae 100644 --- a/src/test/compile-fail/struct-path-associated-type.rs +++ b/src/test/compile-fail/struct-path-associated-type.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct S; trait Tr { diff --git a/src/test/compile-fail/struct-path-self-feature-gate.rs b/src/test/compile-fail/struct-path-self-feature-gate.rs new file mode 100644 index 0000000000000..a2050182a7e30 --- /dev/null +++ b/src/test/compile-fail/struct-path-self-feature-gate.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +trait Tr { + type A; +} + +fn f>() { + let _ = T::A {}; + //~^ ERROR `Self` and associated types in struct expressions and patterns are unstable +} + +impl S { + fn f() { + let _ = Self {}; + //~^ ERROR `Self` and associated types in struct expressions and patterns are unstable + } +} + +fn main() {} diff --git a/src/test/compile-fail/struct-path-self-type-mismatch.rs b/src/test/compile-fail/struct-path-self-type-mismatch.rs index f694e7d277c7f..8352bd6751f50 100644 --- a/src/test/compile-fail/struct-path-self-type-mismatch.rs +++ b/src/test/compile-fail/struct-path-self-type-mismatch.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct Foo { inner: A } trait Bar { fn bar(); } diff --git a/src/test/compile-fail/struct-path-self.rs b/src/test/compile-fail/struct-path-self.rs index 067d6ac22dc6f..aeac199227b75 100644 --- a/src/test/compile-fail/struct-path-self.rs +++ b/src/test/compile-fail/struct-path-self.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct S; trait Tr { diff --git a/src/test/run-pass/struct-path-associated-type.rs b/src/test/run-pass/struct-path-associated-type.rs index b033ed5c80210..292761dfd005f 100644 --- a/src/test/run-pass/struct-path-associated-type.rs +++ b/src/test/run-pass/struct-path-associated-type.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct S { a: T, b: U, diff --git a/src/test/run-pass/struct-path-self.rs b/src/test/run-pass/struct-path-self.rs index c7a282c2a2fa0..b569ab62c1bfa 100644 --- a/src/test/run-pass/struct-path-self.rs +++ b/src/test/run-pass/struct-path-self.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + use std::ops::Add; struct S { From a270b8014cbd3af6e03f7f808a2fea1e9f22ed88 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 21 Oct 2016 13:18:09 -0700 Subject: [PATCH 13/41] rustbuild: Rewrite user-facing interface This commit is a rewrite of the user-facing interface to the rustbuild build system. The intention here is to make it much easier to compile/test the project without having to remember weird rule names and such. An overall view of the new interface is: # build everything ./x.py build # document everyting ./x.py doc # test everything ./x.py test # test libstd ./x.py test src/libstd # build libcore stage0 ./x.py build src/libcore --stage 0 # run stage1 run-pass tests ./x.py test src/test/run-pass --stage 1 The `src/bootstrap/bootstrap.py` script is now aliased as a top-level `x.py` script. This `x` was chosen to be both short and easily tab-completable (no collisions in that namespace!). The build system now accepts a "subcommand" of what to do next, the main ones being build/doc/test. Each subcommand then receives an optional list of arguments. These arguments are paths in the source repo of what to work with. That is, if you want to test a directory, you just pass that directory as an argument. The purpose of this rewrite is to do away with all of the arcane renames like "rpass" is the "run-pass" suite, "cfail" is the "compile-fail" suite, etc. By simply working with directories and files it's much more intuitive of how to run a test (just pass it as an argument). The rustbuild step/dependency management was also rewritten along the way to make this easy to work with and define, but that's largely just a refactoring of what was there before. The *intention* is that this support is extended for arbitrary files (e.g. `src/test/run-pass/my-test-case.rs`), but that isn't quite implemented just yet. Instead directories work for now but we can follow up with stricter path filtering logic to plumb through all the arguments. --- README.md | 4 +- src/Cargo.lock | 20 +- src/bootstrap/Cargo.toml | 2 +- src/bootstrap/README.md | 70 +- src/bootstrap/bootstrap.py | 6 +- src/bootstrap/check.rs | 91 +-- src/bootstrap/clean.rs | 22 +- src/bootstrap/compile.rs | 28 +- src/bootstrap/doc.rs | 39 +- src/bootstrap/flags.rs | 239 ++++++- src/bootstrap/lib.rs | 271 +------- src/bootstrap/metadata.rs | 95 +++ src/bootstrap/mk/Makefile.in | 31 +- src/bootstrap/step.rs | 1179 +++++++++++++++++--------------- src/bootstrap/util.rs | 3 +- src/librustc_errors/Cargo.toml | 2 +- x.py | 19 + 17 files changed, 1136 insertions(+), 985 deletions(-) create mode 100644 src/bootstrap/metadata.rs create mode 100755 x.py diff --git a/README.md b/README.md index b79c9703f44ef..7360651095bb5 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ ones from MSYS if you have it installed). You'll also need Visual Studio 2013 or newer with the C++ tools. Then all you need to do is to kick off rustbuild. ``` -python .\src\bootstrap\bootstrap.py +python x.py build ``` Currently rustbuild only works with some known versions of Visual Studio. If you @@ -137,7 +137,7 @@ by manually calling the appropriate vcvars file before running the bootstrap. ``` CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" -python .\src\bootstrap\bootstrap.py +python x.py build ``` ## Building Documentation diff --git a/src/Cargo.lock b/src/Cargo.lock index 5826995cc3cfc..c3a8923c6de56 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -40,9 +40,9 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)", + "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -63,7 +63,7 @@ version = "0.1.0" [[package]] name = "cmake" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", @@ -131,11 +131,6 @@ dependencies = [ name = "fmt_macros" version = "0.0.0" -[[package]] -name = "gcc" -version = "0.3.38" -source = "git+https://github.com/alexcrichton/gcc-rs#be620ac6d3ddb498cd0c700d5312c6a4c3c19597" - [[package]] name = "gcc" version = "0.3.38" @@ -189,7 +184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "linkchecker" version = "0.1.0" dependencies = [ - "url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -725,7 +720,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "url" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -743,10 +738,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978" +"checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" -"checksum gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)" = "" "checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" @@ -760,6 +754,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f" "checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172" -"checksum url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba5a45db1d2e0effb7a1c00cc73ffc63a973da8c7d1fcd5b46f24285ade6c54" +"checksum url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "48ccf7bd87a81b769cf84ad556e034541fb90e1cd6d4bc375c822ed9500cd9d7" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index c96690754387b..9d44ca033e45d 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -27,7 +27,7 @@ num_cpus = "0.2" toml = "0.1" getopts = "0.2" rustc-serialize = "0.3" -gcc = { git = "https://github.com/alexcrichton/gcc-rs" } +gcc = "0.3.36" libc = "0.2" md5 = "0.1" diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 57d644d635cf7..f73f41ffae29d 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -10,24 +10,72 @@ system. ## Using rustbuild -When configuring Rust via `./configure`, pass the following to enable building -via this build system: +The rustbuild build system has a primary entry point, a top level `x.py` script: ``` -./configure --enable-rustbuild -make +python ./x.py build ``` -Afterwards the `Makefile` which is generated will have a few commands like -`make check`, `make tidy`, etc. For finer-grained control, the -`bootstrap.py` entry point can be used: +Note that if you're on Unix you should be able to execute the script directly: ``` -python src/bootstrap/bootstrap.py +./x.py build ``` -This accepts a number of options like `--stage` and `--step` which can configure -what's actually being done. +The script accepts commands, flags, and filters to determine what to do: + +* `build` - a general purpose command for compiling code. Alone `build` will + bootstrap the entire compiler, and otherwise arguments passed indicate what to + build. For example: + + ``` + # build the whole compiler + ./x.py build + + # build the stage1 compier + ./x.py build --stage 1 + + # build stage0 libstd + ./x.py build --stage 0 src/libstd + + # build a particular crate in stage0 + ./x.py build --stage 0 src/libtest + ``` + +* `test` - a command for executing unit tests. Like the `build` command this + will execute the entire test suite by default, and otherwise it can be used to + select which test suite is run: + + ``` + # run all unit tests + ./x.py test + + # execute the run-pass test suite + ./x.py test src/test/run-pass + + # execute only some tests in the run-pass test suite + ./x.py test src/test/run-pass --filter my-filter + + # execute tests in the standard library in stage0 + ./x.py test --stage 0 src/libstd + + # execute all doc tests + ./x.py test src/doc + ``` + +* `doc` - a command for building documentation. Like above can take arguments + for what to document. + +If you're more used to `./configure` and `make`, however, then you can also +configure the build system to use rustbuild instead of the old makefiles: + +``` +./configure --enable-rustbuild +make +``` + +Afterwards the `Makefile` which is generated will have a few commands like +`make check`, `make tidy`, etc. ## Configuring rustbuild @@ -47,7 +95,7 @@ being invoked manually (via the python script). The rustbuild build system goes through a few phases to actually build the compiler. What actually happens when you invoke rustbuild is: -1. The entry point script, `src/bootstrap/bootstrap.py` is run. This script is +1. The entry point script, `x.py` is run. This script is responsible for downloading the stage0 compiler/Cargo binaries, and it then compiles the build system itself (this folder). Finally, it then invokes the actual `bootstrap` binary build system. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 2c2260a8e60c7..76bbb9d22e082 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -399,12 +399,10 @@ def main(): # Run the bootstrap args = [os.path.join(rb.build_dir, "bootstrap/debug/bootstrap")] - args.append('--src') - args.append(rb.rust_root) - args.append('--build') - args.append(rb.build) args.extend(sys.argv[1:]) env = os.environ.copy() + env["BUILD"] = rb.build + env["SRC"] = rb.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) rb.run(args, env) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0a281b89c571f..e5b666ab3b689 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -13,44 +13,19 @@ //! This file implements the various regression test suites that we execute on //! our CI. -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::env; use std::fs; use std::path::{PathBuf, Path}; use std::process::Command; use build_helper::output; -use rustc_serialize::json; use {Build, Compiler, Mode}; use util::{self, dylib_path, dylib_path_var}; const ADB_TEST_DIR: &'static str = "/data/tmp"; -#[derive(RustcDecodable)] -struct Output { - packages: Vec, - resolve: Resolve, -} - -#[derive(RustcDecodable)] -struct Package { - id: String, - name: String, - source: Option, -} - -#[derive(RustcDecodable)] -struct Resolve { - nodes: Vec, -} - -#[derive(RustcDecodable)] -struct ResolveNode { - id: String, - dependencies: Vec, -} - /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. /// /// This tool in `src/tools` will verify the validity of all our links in the @@ -181,7 +156,7 @@ pub fn compiletest(build: &Build, let llvm_version = output(Command::new(&llvm_config).arg("--version")); cmd.arg("--llvm-version").arg(llvm_version); - cmd.args(&build.flags.args); + cmd.args(&build.flags.cmd.test_args()); if build.config.verbose || build.flags.verbose { cmd.arg("--verbose"); @@ -282,7 +257,7 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { cmd.arg("--test"); cmd.arg(markdown); - let mut test_args = build.flags.args.join(" "); + let mut test_args = build.flags.cmd.test_args().join(" "); if build.config.quiet_tests { test_args.push_str(" --quiet"); } @@ -302,7 +277,8 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { pub fn krate(build: &Build, compiler: &Compiler, target: &str, - mode: Mode) { + mode: Mode, + krate: Option<&str>) { let (name, path, features, root) = match mode { Mode::Libstd => { ("libstd", "src/rustc/std_shim", build.std_features(), "std_shim") @@ -318,24 +294,6 @@ pub fn krate(build: &Build, println!("Testing {} stage{} ({} -> {})", name, compiler.stage, compiler.host, target); - // Run `cargo metadata` to figure out what crates we're testing. - // - // Down below we're going to call `cargo test`, but to test the right set - // of packages we're going to have to know what `-p` arguments to pass it - // to know what crates to test. Here we run `cargo metadata` to learn about - // the dependency graph and what `-p` arguments there are. - let mut cargo = Command::new(&build.cargo); - cargo.arg("metadata") - .arg("--manifest-path").arg(build.src.join(path).join("Cargo.toml")); - let output = output(&mut cargo); - let output: Output = json::decode(&output).unwrap(); - let id2pkg = output.packages.iter() - .map(|pkg| (&pkg.id, pkg)) - .collect::>(); - let id2deps = output.resolve.nodes.iter() - .map(|node| (&node.id, &node.dependencies)) - .collect::>(); - // Build up the base `cargo test` command. // // Pass in some standard flags then iterate over the graph we've discovered @@ -346,24 +304,25 @@ pub fn krate(build: &Build, .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); - let mut visited = HashSet::new(); - let root_pkg = output.packages.iter().find(|p| p.name == root).unwrap(); - let mut next = vec![&root_pkg.id]; - while let Some(id) = next.pop() { - // Skip any packages with sources listed, as these come from crates.io - // and we shouldn't be testing them. - if id2pkg[id].source.is_some() { - continue - } - // Right now jemalloc is our only target-specific crate in the sense - // that it's not present on all platforms. Custom skip it here for now, - // but if we add more this probably wants to get more generalized. - if !id.contains("jemalloc") { - cargo.arg("-p").arg(&id2pkg[id].name); + match krate { + Some(krate) => { + cargo.arg("-p").arg(krate); } - for dep in id2deps[id] { - if visited.insert(dep) { - next.push(dep); + None => { + let mut visited = HashSet::new(); + let mut next = vec![root]; + while let Some(name) = next.pop() { + // Right now jemalloc is our only target-specific crate in the sense + // that it's not present on all platforms. Custom skip it here for now, + // but if we add more this probably wants to get more generalized. + if !name.contains("jemalloc") { + cargo.arg("-p").arg(name); + } + for dep in build.crates[name].deps.iter() { + if visited.insert(dep) { + next.push(dep); + } + } } } } @@ -389,7 +348,7 @@ pub fn krate(build: &Build, build.run(cargo.arg("--no-run")); krate_emscripten(build, compiler, target, mode); } else { - cargo.args(&build.flags.args); + cargo.args(&build.flags.cmd.test_args()); build.run(&mut cargo); } } @@ -421,7 +380,7 @@ fn krate_android(build: &Build, target = target, test = test_file_name, log = log, - args = build.flags.args.join(" ")); + args = build.flags.cmd.test_args().join(" ")); let output = output(Command::new("adb").arg("shell").arg(&program)); println!("{}", output); diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index a1e286e162ffa..3d338cf4f94d8 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -25,17 +25,17 @@ pub fn clean(build: &Build) { rm_rf(build, &build.out.join("tmp")); for host in build.config.host.iter() { - - let out = build.out.join(host); - - rm_rf(build, &out.join("doc")); - - for stage in 0..4 { - rm_rf(build, &out.join(format!("stage{}", stage))); - rm_rf(build, &out.join(format!("stage{}-std", stage))); - rm_rf(build, &out.join(format!("stage{}-rustc", stage))); - rm_rf(build, &out.join(format!("stage{}-tools", stage))); - rm_rf(build, &out.join(format!("stage{}-test", stage))); + let entries = match build.out.join(host).read_dir() { + Ok(iter) => iter, + Err(_) => continue, + }; + + for entry in entries { + let entry = t!(entry); + if entry.file_name().to_str() == Some("llvm") { + continue + } + t!(fs::remove_dir_all(&entry.path())); } } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ff8e4757bd1f1..5fc4f006729d3 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -64,8 +64,8 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { } build.run(&mut cargo); - update_mtime(&libstd_stamp(build, compiler, target)); - std_link(build, target, compiler, compiler.host); + update_mtime(&libstd_stamp(build, &compiler, target)); + std_link(build, target, compiler.stage, compiler.host); } /// Link all libstd rlibs/dylibs into the sysroot location. @@ -74,11 +74,12 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// by `compiler` into `host`'s sysroot. pub fn std_link(build: &Build, target: &str, - compiler: &Compiler, + stage: u32, host: &str) { + let compiler = Compiler::new(stage, &build.config.build); let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); - let out_dir = build.cargo_out(compiler, Mode::Libstd, target); + let out_dir = build.cargo_out(&compiler, Mode::Libstd, target); // If we're linking one compiler host's output into another, then we weren't // called from the `std` method above. In that case we clean out what's @@ -146,7 +147,7 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); build.run(&mut cargo); update_mtime(&libtest_stamp(build, compiler, target)); - test_link(build, target, compiler, compiler.host); + test_link(build, target, compiler.stage, compiler.host); } /// Link all libtest rlibs/dylibs into the sysroot location. @@ -155,11 +156,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// by `compiler` into `host`'s sysroot. pub fn test_link(build: &Build, target: &str, - compiler: &Compiler, + stage: u32, host: &str) { + let compiler = Compiler::new(stage, &build.config.build); let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); - let out_dir = build.cargo_out(compiler, Mode::Libtest, target); + let out_dir = build.cargo_out(&compiler, Mode::Libtest, target); add_to_sysroot(&out_dir, &libdir); } @@ -218,7 +220,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { } build.run(&mut cargo); - rustc_link(build, target, compiler, compiler.host); + rustc_link(build, target, compiler.stage, compiler.host); } /// Link all librustc rlibs/dylibs into the sysroot location. @@ -227,11 +229,12 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// by `compiler` into `host`'s sysroot. pub fn rustc_link(build: &Build, target: &str, - compiler: &Compiler, + stage: u32, host: &str) { + let compiler = Compiler::new(stage, &build.config.build); let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); - let out_dir = build.cargo_out(compiler, Mode::Librustc, target); + let out_dir = build.cargo_out(&compiler, Mode::Librustc, target); add_to_sysroot(&out_dir, &libdir); } @@ -259,7 +262,10 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { /// must have been previously produced by the `stage - 1` build.config.build /// compiler. pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { - assert!(stage > 0, "the stage0 compiler isn't assembled, it's downloaded"); + // nothing to do in stage0 + if stage == 0 { + return + } // The compiler that we're assembling let target_compiler = Compiler::new(stage, host); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index c2636384dbb2b..30c7fefad8745 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -19,7 +19,6 @@ use std::fs::{self, File}; use std::io::prelude::*; -use std::path::Path; use std::process::Command; use {Build, Compiler, Mode}; @@ -30,8 +29,9 @@ use util::{up_to_date, cp_r}; /// /// This will not actually generate any documentation if the documentation has /// already been generated. -pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) { - t!(fs::create_dir_all(out)); +pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str) { + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let out = out.join(name); let compiler = Compiler::new(stage, &build.config.build); @@ -57,9 +57,10 @@ pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) /// `STAMP` alongw ith providing the various header/footer HTML we've cutomized. /// /// In the end, this is just a glorified wrapper around rustdoc! -pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn standalone(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} standalone ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); @@ -109,7 +110,7 @@ pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { .arg("--html-in-header").arg(&favicon) .arg("--markdown-playground-url") .arg("https://play.rust-lang.org/") - .arg("-o").arg(out) + .arg("-o").arg(&out) .arg(&path); if filename == "reference.md" { @@ -131,9 +132,10 @@ pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { /// /// This will generate all documentation for the standard library and its /// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn std(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn std(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} std ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let out_dir = build.stage_out(&compiler, Mode::Libstd) .join(target).join("doc"); @@ -146,16 +148,17 @@ pub fn std(build: &Build, stage: u32, target: &str, out: &Path) { .arg(build.src.join("src/rustc/std_shim/Cargo.toml")) .arg("--features").arg(build.std_features()); build.run(&mut cargo); - cp_r(&out_dir, out) + cp_r(&out_dir, &out) } /// Compile all libtest documentation. /// /// This will generate all documentation for libtest and its dependencies. This /// is largely just a wrapper around `cargo doc`. -pub fn test(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn test(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} test ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let out_dir = build.stage_out(&compiler, Mode::Libtest) .join(target).join("doc"); @@ -167,16 +170,17 @@ pub fn test(build: &Build, stage: u32, target: &str, out: &Path) { cargo.arg("--manifest-path") .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); build.run(&mut cargo); - cp_r(&out_dir, out) + cp_r(&out_dir, &out) } /// Generate all compiler documentation. /// /// This will generate all documentation for the compiler libraries and their /// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn rustc(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} compiler ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let out_dir = build.stage_out(&compiler, Mode::Librustc) .join(target).join("doc"); @@ -189,14 +193,15 @@ pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) { .arg(build.src.join("src/rustc/Cargo.toml")) .arg("--features").arg(build.rustc_features()); build.run(&mut cargo); - cp_r(&out_dir, out) + cp_r(&out_dir, &out) } /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. -pub fn error_index(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn error_index(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} error index ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let mut index = build.tool_cmd(&compiler, "error_index_generator"); index.arg("html"); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index d925997f36c21..d7516954f12d5 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -13,30 +13,46 @@ //! This module implements the command-line parsing of the build system which //! has various flags to configure how it's run. +use std::env; use std::fs; use std::path::PathBuf; use std::process; -use std::slice; -use getopts::Options; +use getopts::{Matches, Options}; + +use Build; +use config::Config; +use metadata; +use step; /// Deserialized version of all flags for this compile. pub struct Flags { pub verbose: bool, pub stage: Option, pub build: String, - pub host: Filter, - pub target: Filter, - pub step: Vec, + pub host: Vec, + pub target: Vec, pub config: Option, pub src: Option, pub jobs: Option, - pub args: Vec, - pub clean: bool, + pub cmd: Subcommand, } -pub struct Filter { - values: Vec, +pub enum Subcommand { + Build { + paths: Vec, + }, + Doc { + paths: Vec, + }, + Test { + paths: Vec, + test_args: Vec, + }, + Clean, + Dist { + install: bool, + }, } impl Flags { @@ -44,29 +60,177 @@ impl Flags { let mut opts = Options::new(); opts.optflag("v", "verbose", "use verbose output"); opts.optopt("", "config", "TOML configuration file for build", "FILE"); + opts.optopt("", "build", "build target of the stage0 compiler", "BUILD"); opts.optmulti("", "host", "host targets to build", "HOST"); - opts.reqopt("", "build", "build target of the stage0 compiler", "BUILD"); - opts.optmulti("", "target", "targets to build", "TARGET"); - opts.optmulti("s", "step", "build step to execute", "STEP"); + opts.optmulti("", "target", "target targets to build", "TARGET"); opts.optopt("", "stage", "stage to build", "N"); - opts.optopt("", "src", "path to repo root", "DIR"); + opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS"); - opts.optflag("", "clean", "clean output directory"); opts.optflag("h", "help", "print this help message"); - let usage = |n| -> ! { - let brief = format!("Usage: rust.py [options]"); - print!("{}", opts.usage(&brief)); + let usage = |n, opts: &Options| -> ! { + let command = args.get(0).map(|s| &**s); + let brief = format!("Usage: x.py {} [options] [...]", + command.unwrap_or("")); + + println!("{}", opts.usage(&brief)); + match command { + Some("build") => { + println!("\ +Arguments: + This subcommand accepts a number of positional arguments of directories to + the crates and/or artifacts to compile. For example: + + ./x.py build src/libcore + ./x.py build src/libproc_macro + ./x.py build src/libstd --stage 1 + + If no arguments are passed then the complete artifacts for that stage are + also compiled. + + ./x.py build + ./x.py build --stage 1 + + For a quick build with a usable compile, you can pass: + + ./x.py build --stage 1 src/libtest +"); + } + + Some("test") => { + println!("\ +Arguments: + This subcommand accepts a number of positional arguments of directories to + tests that should be compiled and run. For example: + + ./x.py test src/test/run-pass + ./x.py test src/test/run-pass/assert-* + ./x.py test src/libstd --test-args hash_map + ./x.py test src/libstd --stage 0 + + If no arguments are passed then the complete artifacts for that stage are + compiled and tested. + + ./x.py test + ./x.py test --stage 1 +"); + } + + Some("doc") => { + println!("\ +Arguments: + This subcommand accepts a number of positional arguments of directories of + documentation to build. For example: + + ./x.py doc src/doc/book + ./x.py doc src/doc/nomicon + ./x.py doc src/libstd + + If no arguments are passed then everything is documented: + + ./x.py doc + ./x.py doc --stage 1 +"); + } + + _ => {} + } + + if let Some(command) = command { + if command == "build" || + command == "dist" || + command == "doc" || + command == "test" || + command == "clean" { + println!("Available invocations:"); + if args.iter().any(|a| a == "-v") { + let flags = Flags::parse(&["build".to_string()]); + let mut config = Config::default(); + config.build = flags.build.clone(); + let mut build = Build::new(flags, config); + metadata::build(&mut build); + step::build_rules(&build).print_help(command); + } else { + println!(" ... elided, run `./x.py {} -h -v` to see", + command); + } + + println!(""); + } + } + +println!("\ +Subcommands: + build Compile either the compiler or libraries + test Build and run some test suites + doc Build documentation + clean Clean out build directories + dist Build and/or install distribution artifacts + +To learn more about a subcommand, run `./x.py -h` +"); + process::exit(n); }; - - let m = opts.parse(args).unwrap_or_else(|e| { - println!("failed to parse options: {}", e); - usage(1); - }); - if m.opt_present("h") { - usage(0); + if args.len() == 0 { + println!("a command must be passed"); + usage(1, &opts); } + let parse = |opts: &Options| { + let m = opts.parse(&args[1..]).unwrap_or_else(|e| { + println!("failed to parse options: {}", e); + usage(1, opts); + }); + if m.opt_present("h") { + usage(0, opts); + } + return m + }; + + let cwd = t!(env::current_dir()); + let remaining_as_path = |m: &Matches| { + m.free.iter().map(|p| cwd.join(p)).collect::>() + }; + + let m: Matches; + let cmd = match &args[0][..] { + "build" => { + m = parse(&opts); + Subcommand::Build { paths: remaining_as_path(&m) } + } + "doc" => { + m = parse(&opts); + Subcommand::Doc { paths: remaining_as_path(&m) } + } + "test" => { + opts.optmulti("", "test-args", "extra arguments", "ARGS"); + m = parse(&opts); + Subcommand::Test { + paths: remaining_as_path(&m), + test_args: m.opt_strs("test-args"), + } + } + "clean" => { + m = parse(&opts); + if m.free.len() > 0 { + println!("clean takes no arguments"); + usage(1, &opts); + } + Subcommand::Clean + } + "dist" => { + opts.optflag("", "install", "run installer as well"); + m = parse(&opts); + Subcommand::Dist { + install: m.opt_present("install"), + } + } + cmd => { + println!("unknown command: {}", cmd); + usage(1, &opts); + } + }; + let cfg_file = m.opt_str("config").map(PathBuf::from).or_else(|| { if fs::metadata("config.toml").is_ok() { @@ -78,26 +242,27 @@ impl Flags { Flags { verbose: m.opt_present("v"), - clean: m.opt_present("clean"), stage: m.opt_str("stage").map(|j| j.parse().unwrap()), - build: m.opt_str("build").unwrap(), - host: Filter { values: m.opt_strs("host") }, - target: Filter { values: m.opt_strs("target") }, - step: m.opt_strs("step"), + build: m.opt_str("build").unwrap_or_else(|| { + env::var("BUILD").unwrap() + }), + host: m.opt_strs("host"), + target: m.opt_strs("target"), config: cfg_file, src: m.opt_str("src").map(PathBuf::from), jobs: m.opt_str("jobs").map(|j| j.parse().unwrap()), - args: m.free.clone(), + cmd: cmd, } } } -impl Filter { - pub fn contains(&self, name: &str) -> bool { - self.values.len() == 0 || self.values.iter().any(|s| s == name) - } - - pub fn iter(&self) -> slice::Iter { - self.values.iter() +impl Subcommand { + pub fn test_args(&self) -> Vec<&str> { + match *self { + Subcommand::Test { ref test_args, .. } => { + test_args.iter().flat_map(|s| s.split_whitespace()).collect() + } + _ => Vec::new(), + } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7c5a0c7373f88..e4af462120606 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -57,6 +57,7 @@ mod channel; mod check; mod clean; mod compile; +mod metadata; mod config; mod dist; mod doc; @@ -76,7 +77,7 @@ mod job { } pub use config::Config; -pub use flags::Flags; +pub use flags::{Flags, Subcommand}; /// A structure representing a Rust compiler. /// @@ -130,6 +131,17 @@ pub struct Build { // Runtime state filled in later on cc: HashMap)>, cxx: HashMap, + crates: HashMap, +} + +#[derive(Debug)] +struct Crate { + name: String, + deps: Vec, + path: PathBuf, + doc_step: String, + build_step: String, + test_step: String, } /// The various "modes" of invoking Cargo. @@ -162,7 +174,9 @@ impl Build { /// By default all build output will be placed in the current directory. pub fn new(flags: Flags, config: Config) -> Build { let cwd = t!(env::current_dir()); - let src = flags.src.clone().unwrap_or(cwd.clone()); + let src = flags.src.clone().or_else(|| { + env::var_os("SRC").map(|x| x.into()) + }).unwrap_or(cwd.clone()); let out = cwd.join("build"); let stage0_root = out.join(&config.build).join("stage0/bin"); @@ -196,6 +210,7 @@ impl Build { package_vers: String::new(), cc: HashMap::new(), cxx: HashMap::new(), + crates: HashMap::new(), gdb_version: None, lldb_version: None, lldb_python_dir: None, @@ -204,13 +219,11 @@ impl Build { /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { - use step::Source::*; - unsafe { job::setup(); } - if self.flags.clean { + if let Subcommand::Clean = self.flags.cmd { return clean::clean(self); } @@ -232,247 +245,10 @@ impl Build { } self.verbose("updating submodules"); self.update_submodules(); + self.verbose("learning about cargo"); + metadata::build(self); - // The main loop of the build system. - // - // The `step::all` function returns a topographically sorted list of all - // steps that need to be executed as part of this build. Each step has a - // corresponding entry in `step.rs` and indicates some unit of work that - // needs to be done as part of the build. - // - // Almost all of these are simple one-liners that shell out to the - // corresponding functionality in the extra modules, where more - // documentation can be found. - let steps = step::all(self); - - self.verbose("bootstrap build plan:"); - for step in &steps { - self.verbose(&format!("{:?}", step)); - } - - for target in steps { - let doc_out = self.out.join(&target.target).join("doc"); - match target.src { - Llvm { _dummy } => { - native::llvm(self, target.target); - } - TestHelpers { _dummy } => { - native::test_helpers(self, target.target); - } - Libstd { compiler } => { - compile::std(self, target.target, &compiler); - } - Libtest { compiler } => { - compile::test(self, target.target, &compiler); - } - Librustc { compiler } => { - compile::rustc(self, target.target, &compiler); - } - LibstdLink { compiler, host } => { - compile::std_link(self, target.target, &compiler, host); - } - LibtestLink { compiler, host } => { - compile::test_link(self, target.target, &compiler, host); - } - LibrustcLink { compiler, host } => { - compile::rustc_link(self, target.target, &compiler, host); - } - Rustc { stage: 0 } => { - // nothing to do... - } - Rustc { stage } => { - compile::assemble_rustc(self, stage, target.target); - } - ToolLinkchecker { stage } => { - compile::tool(self, stage, target.target, "linkchecker"); - } - ToolRustbook { stage } => { - compile::tool(self, stage, target.target, "rustbook"); - } - ToolErrorIndex { stage } => { - compile::tool(self, stage, target.target, - "error_index_generator"); - } - ToolCargoTest { stage } => { - compile::tool(self, stage, target.target, "cargotest"); - } - ToolTidy { stage } => { - compile::tool(self, stage, target.target, "tidy"); - } - ToolCompiletest { stage } => { - compile::tool(self, stage, target.target, "compiletest"); - } - DocBook { stage } => { - doc::rustbook(self, stage, target.target, "book", &doc_out); - } - DocNomicon { stage } => { - doc::rustbook(self, stage, target.target, "nomicon", - &doc_out); - } - DocStandalone { stage } => { - doc::standalone(self, stage, target.target, &doc_out); - } - DocStd { stage } => { - doc::std(self, stage, target.target, &doc_out); - } - DocTest { stage } => { - doc::test(self, stage, target.target, &doc_out); - } - DocRustc { stage } => { - doc::rustc(self, stage, target.target, &doc_out); - } - DocErrorIndex { stage } => { - doc::error_index(self, stage, target.target, &doc_out); - } - - CheckLinkcheck { stage } => { - check::linkcheck(self, stage, target.target); - } - CheckCargoTest { stage } => { - check::cargotest(self, stage, target.target); - } - CheckTidy { stage } => { - check::tidy(self, stage, target.target); - } - CheckRPass { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-pass", "run-pass"); - } - CheckRPassFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-pass", "run-pass-fulldeps"); - } - CheckCFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "compile-fail", "compile-fail"); - } - CheckCFailFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "compile-fail", "compile-fail-fulldeps") - } - CheckPFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "parse-fail", "parse-fail"); - } - CheckRFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-fail", "run-fail"); - } - CheckRFailFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-fail", "run-fail-fulldeps"); - } - CheckPretty { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "pretty"); - } - CheckPrettyRPass { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-pass"); - } - CheckPrettyRPassFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-pass-fulldeps"); - } - CheckPrettyRFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-fail"); - } - CheckPrettyRFailFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-fail-fulldeps"); - } - CheckPrettyRPassValgrind { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-pass-valgrind"); - } - CheckMirOpt { compiler } => { - check::compiletest(self, &compiler, target.target, - "mir-opt", "mir-opt"); - } - CheckCodegen { compiler } => { - if self.config.codegen_tests { - check::compiletest(self, &compiler, target.target, - "codegen", "codegen"); - } - } - CheckCodegenUnits { compiler } => { - check::compiletest(self, &compiler, target.target, - "codegen-units", "codegen-units"); - } - CheckIncremental { compiler } => { - check::compiletest(self, &compiler, target.target, - "incremental", "incremental"); - } - CheckUi { compiler } => { - check::compiletest(self, &compiler, target.target, - "ui", "ui"); - } - CheckDebuginfo { compiler } => { - if target.target.contains("msvc") { - // nothing to do - } else if target.target.contains("apple") { - check::compiletest(self, &compiler, target.target, - "debuginfo-lldb", "debuginfo"); - } else { - check::compiletest(self, &compiler, target.target, - "debuginfo-gdb", "debuginfo"); - } - } - CheckRustdoc { compiler } => { - check::compiletest(self, &compiler, target.target, - "rustdoc", "rustdoc"); - } - CheckRPassValgrind { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-pass-valgrind", "run-pass-valgrind"); - } - CheckDocs { compiler } => { - check::docs(self, &compiler); - } - CheckErrorIndex { compiler } => { - check::error_index(self, &compiler); - } - CheckRMake { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-make", "run-make") - } - CheckCrateStd { compiler } => { - check::krate(self, &compiler, target.target, Mode::Libstd) - } - CheckCrateTest { compiler } => { - check::krate(self, &compiler, target.target, Mode::Libtest) - } - CheckCrateRustc { compiler } => { - check::krate(self, &compiler, target.target, Mode::Librustc) - } - - DistDocs { stage } => dist::docs(self, stage, target.target), - DistMingw { _dummy } => dist::mingw(self, target.target), - DistRustc { stage } => dist::rustc(self, stage, target.target), - DistStd { compiler } => dist::std(self, &compiler, target.target), - DistSrc { _dummy } => dist::rust_src(self), - - Install { stage } => install::install(self, stage, target.target), - - DebuggerScripts { stage } => { - let compiler = Compiler::new(stage, target.target); - dist::debugger_scripts(self, - &self.sysroot(&compiler), - target.target); - } - - AndroidCopyLibs { compiler } => { - check::android_copy_libs(self, &compiler, target.target); - } - - // pseudo-steps - Dist { .. } | - Doc { .. } | - CheckTarget { .. } | - Check { .. } => {} - } - } + step::run(self); } /// Updates all git submodules that we have. @@ -812,6 +588,11 @@ impl Build { self.out.join(target).join("llvm") } + /// Output directory for all documentation for a target + fn doc_out(&self, target: &str) -> PathBuf { + self.out.join(target).join("doc") + } + /// Returns true if no custom `llvm-config` is set for the specified target. /// /// If no custom `llvm-config` was specified then Rust's llvm will be used. diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs new file mode 100644 index 0000000000000..bf5cc6a4ad838 --- /dev/null +++ b/src/bootstrap/metadata.rs @@ -0,0 +1,95 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashMap; +use std::process::Command; +use std::path::PathBuf; + +use build_helper::output; +use rustc_serialize::json; + +use {Build, Crate}; + +#[derive(RustcDecodable)] +struct Output { + packages: Vec, + resolve: Resolve, +} + +#[derive(RustcDecodable)] +struct Package { + id: String, + name: String, + source: Option, + manifest_path: String, +} + +#[derive(RustcDecodable)] +struct Resolve { + nodes: Vec, +} + +#[derive(RustcDecodable)] +struct ResolveNode { + id: String, + dependencies: Vec, +} + +pub fn build(build: &mut Build) { + build_krate(build, "src/rustc/std_shim"); + build_krate(build, "src/rustc/test_shim"); + build_krate(build, "src/rustc"); +} + +fn build_krate(build: &mut Build, krate: &str) { + // Run `cargo metadata` to figure out what crates we're testing. + // + // Down below we're going to call `cargo test`, but to test the right set + // of packages we're going to have to know what `-p` arguments to pass it + // to know what crates to test. Here we run `cargo metadata` to learn about + // the dependency graph and what `-p` arguments there are. + let mut cargo = Command::new(&build.cargo); + cargo.arg("metadata") + .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml")); + let output = output(&mut cargo); + let output: Output = json::decode(&output).unwrap(); + let mut id2name = HashMap::new(); + for package in output.packages { + if package.source.is_none() { + id2name.insert(package.id, package.name.clone()); + let mut path = PathBuf::from(package.manifest_path); + path.pop(); + build.crates.insert(package.name.clone(), Crate { + build_step: format!("build-crate-{}", package.name), + doc_step: format!("doc-crate-{}", package.name), + test_step: format!("test-crate-{}", package.name), + name: package.name, + deps: Vec::new(), + path: path, + }); + } + } + + for node in output.resolve.nodes { + let name = match id2name.get(&node.id) { + Some(name) => name, + None => continue, + }; + + let krate = build.crates.get_mut(name).unwrap(); + for dep in node.dependencies.iter() { + let dep = match id2name.get(dep) { + Some(dep) => dep, + None => continue, + }; + krate.deps.push(dep.clone()); + } + } +} diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 0762ed98472be..d4031077639c5 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -17,47 +17,46 @@ else BOOTSTRAP_ARGS := endif -BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py $(BOOTSTRAP_ARGS) +BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py all: - $(Q)$(BOOTSTRAP) + $(Q)$(BOOTSTRAP) build $(BOOTSTRAP_ARGS) + $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS) # Don’t use $(Q) here, always show how to invoke the bootstrap script directly help: $(BOOTSTRAP) --help clean: - $(Q)$(BOOTSTRAP) --clean + $(Q)$(BOOTSTRAP) clean $(BOOTSTRAP_ARGS) rustc-stage1: - $(Q)$(BOOTSTRAP) --step libtest --stage 1 + $(Q)$(BOOTSTRAP) build --stage 1 src/libtest $(BOOTSTRAP_ARGS) rustc-stage2: - $(Q)$(BOOTSTRAP) --step libtest --stage 2 + $(Q)$(BOOTSTRAP) build --stage 2 src/libtest $(BOOTSTRAP_ARGS) docs: doc doc: - $(Q)$(BOOTSTRAP) --step doc -style: - $(Q)$(BOOTSTRAP) --step doc-style + $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS) nomicon: - $(Q)$(BOOTSTRAP) --step doc-nomicon + $(Q)$(BOOTSTRAP) doc src/doc/nomicon $(BOOTSTRAP_ARGS) book: - $(Q)$(BOOTSTRAP) --step doc-book + $(Q)$(BOOTSTRAP) doc src/doc/book $(BOOTSTRAP_ARGS) standalone-docs: - $(Q)$(BOOTSTRAP) --step doc-standalone + $(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS) check: - $(Q)$(BOOTSTRAP) --step check + $(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS) check-cargotest: - $(Q)$(BOOTSTRAP) --step check-cargotest + $(Q)$(BOOTSTRAP) test src/tools/cargotest $(BOOTSTRAP_ARGS) dist: - $(Q)$(BOOTSTRAP) --step dist + $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS) install: ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER))) $(Q)echo "'sudo make install' is not supported currently." else - $(Q)$(BOOTSTRAP) --step install + $(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS) endif tidy: - $(Q)$(BOOTSTRAP) --step check-tidy --stage 0 + $(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) .PHONY: dist diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 3bf0f21192147..4a7cfa1cc6a3e 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -8,600 +8,683 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Major workhorse of rustbuild, definition and dependencies between stages of -//! the copmile. -//! -//! The primary purpose of this module is to define the various `Step`s of -//! execution of the build. Each `Step` has a corresponding `Source` indicating -//! what it's actually doing along with a number of dependencies which must be -//! executed first. -//! -//! This module will take the CLI as input and calculate the steps required for -//! the build requested, ensuring that all intermediate pieces are in place. -//! Essentially this module is a `make`-replacement, but not as good. - -use std::collections::HashSet; - -use {Build, Compiler}; - -#[derive(Hash, Eq, PartialEq, Clone, Debug)] -pub struct Step<'a> { - pub src: Source<'a>, - pub target: &'a str, +use std::collections::{HashMap, HashSet}; +use std::mem; + +use check; +use compile; +use dist; +use doc; +use flags::Subcommand; +use install; +use native; +use {Compiler, Build, Mode}; + +#[derive(PartialEq, Eq, Hash, Clone, Debug)] +struct Step<'a> { + name: &'a str, + stage: u32, + host: &'a str, + target: &'a str, } -/// Macro used to iterate over all targets that are recognized by the build -/// system. -/// -/// Whenever a new step is added it will involve adding an entry here, updating -/// the dependencies section below, and then adding an implementation of the -/// step in `build/mod.rs`. -/// -/// This macro takes another macro as an argument and then calls that macro with -/// all steps that the build system knows about. -macro_rules! targets { - ($m:ident) => { - $m! { - // Step representing building the stageN compiler. This is just the - // compiler executable itself, not any of the support libraries - (rustc, Rustc { stage: u32 }), - - // Steps for the two main cargo builds. These are parameterized over - // the compiler which is producing the artifact. - (libstd, Libstd { compiler: Compiler<'a> }), - (libtest, Libtest { compiler: Compiler<'a> }), - (librustc, Librustc { compiler: Compiler<'a> }), - - // Links the target produced by the compiler provided into the - // host's directory also provided. - (libstd_link, LibstdLink { - compiler: Compiler<'a>, - host: &'a str - }), - (libtest_link, LibtestLink { - compiler: Compiler<'a>, - host: &'a str - }), - (librustc_link, LibrustcLink { - compiler: Compiler<'a>, - host: &'a str - }), - - // Various tools that we can build as part of the build. - (tool_linkchecker, ToolLinkchecker { stage: u32 }), - (tool_rustbook, ToolRustbook { stage: u32 }), - (tool_error_index, ToolErrorIndex { stage: u32 }), - (tool_cargotest, ToolCargoTest { stage: u32 }), - (tool_tidy, ToolTidy { stage: u32 }), - (tool_compiletest, ToolCompiletest { stage: u32 }), - - // Steps for long-running native builds. Ideally these wouldn't - // actually exist and would be part of build scripts, but for now - // these are here. - // - // There aren't really any parameters to this, but empty structs - // with braces are unstable so we just pick something that works. - (llvm, Llvm { _dummy: () }), - (test_helpers, TestHelpers { _dummy: () }), - (debugger_scripts, DebuggerScripts { stage: u32 }), - - // Steps for various pieces of documentation that we can generate, - // the 'doc' step is just a pseudo target to depend on a bunch of - // others. - (doc, Doc { stage: u32 }), - (doc_book, DocBook { stage: u32 }), - (doc_nomicon, DocNomicon { stage: u32 }), - (doc_standalone, DocStandalone { stage: u32 }), - (doc_std, DocStd { stage: u32 }), - (doc_test, DocTest { stage: u32 }), - (doc_rustc, DocRustc { stage: u32 }), - (doc_error_index, DocErrorIndex { stage: u32 }), - - // Steps for running tests. The 'check' target is just a pseudo - // target to depend on a bunch of others. - (check, Check { stage: u32, compiler: Compiler<'a> }), - (check_target, CheckTarget { stage: u32, compiler: Compiler<'a> }), - (check_linkcheck, CheckLinkcheck { stage: u32 }), - (check_cargotest, CheckCargoTest { stage: u32 }), - (check_tidy, CheckTidy { stage: u32 }), - (check_rpass, CheckRPass { compiler: Compiler<'a> }), - (check_rpass_full, CheckRPassFull { compiler: Compiler<'a> }), - (check_rpass_valgrind, CheckRPassValgrind { compiler: Compiler<'a> }), - (check_rfail, CheckRFail { compiler: Compiler<'a> }), - (check_rfail_full, CheckRFailFull { compiler: Compiler<'a> }), - (check_cfail, CheckCFail { compiler: Compiler<'a> }), - (check_cfail_full, CheckCFailFull { compiler: Compiler<'a> }), - (check_pfail, CheckPFail { compiler: Compiler<'a> }), - (check_pretty, CheckPretty { compiler: Compiler<'a> }), - (check_pretty_rpass, CheckPrettyRPass { compiler: Compiler<'a> }), - (check_pretty_rpass_full, CheckPrettyRPassFull { compiler: Compiler<'a> }), - (check_pretty_rfail, CheckPrettyRFail { compiler: Compiler<'a> }), - (check_pretty_rfail_full, CheckPrettyRFailFull { compiler: Compiler<'a> }), - (check_pretty_rpass_valgrind, CheckPrettyRPassValgrind { compiler: Compiler<'a> }), - (check_codegen, CheckCodegen { compiler: Compiler<'a> }), - (check_codegen_units, CheckCodegenUnits { compiler: Compiler<'a> }), - (check_incremental, CheckIncremental { compiler: Compiler<'a> }), - (check_ui, CheckUi { compiler: Compiler<'a> }), - (check_mir_opt, CheckMirOpt { compiler: Compiler<'a> }), - (check_debuginfo, CheckDebuginfo { compiler: Compiler<'a> }), - (check_rustdoc, CheckRustdoc { compiler: Compiler<'a> }), - (check_docs, CheckDocs { compiler: Compiler<'a> }), - (check_error_index, CheckErrorIndex { compiler: Compiler<'a> }), - (check_rmake, CheckRMake { compiler: Compiler<'a> }), - (check_crate_std, CheckCrateStd { compiler: Compiler<'a> }), - (check_crate_test, CheckCrateTest { compiler: Compiler<'a> }), - (check_crate_rustc, CheckCrateRustc { compiler: Compiler<'a> }), - - // Distribution targets, creating tarballs - (dist, Dist { stage: u32 }), - (dist_docs, DistDocs { stage: u32 }), - (dist_mingw, DistMingw { _dummy: () }), - (dist_rustc, DistRustc { stage: u32 }), - (dist_std, DistStd { compiler: Compiler<'a> }), - (dist_src, DistSrc { _dummy: () }), - - // install target - (install, Install { stage: u32 }), - - // Misc targets - (android_copy_libs, AndroidCopyLibs { compiler: Compiler<'a> }), - } +impl<'a> Step<'a> { + fn name(&self, name: &'a str) -> Step<'a> { + Step { name: name, ..*self } } -} -// Define the `Source` enum by iterating over all the steps and peeling out just -// the types that we want to define. + fn stage(&self, stage: u32) -> Step<'a> { + Step { stage: stage, ..*self } + } -macro_rules! item { ($a:item) => ($a) } + fn host(&self, host: &'a str) -> Step<'a> { + Step { host: host, ..*self } + } -macro_rules! define_source { - ($(($short:ident, $name:ident { $($args:tt)* }),)*) => { - item! { - #[derive(Hash, Eq, PartialEq, Clone, Debug)] - pub enum Source<'a> { - $($name { $($args)* }),* - } - } + fn target(&self, target: &'a str) -> Step<'a> { + Step { target: target, ..*self } } -} -targets!(define_source); - -/// Calculate a list of all steps described by `build`. -/// -/// This will inspect the flags passed in on the command line and use that to -/// build up a list of steps to execute. These steps will then be transformed -/// into a topologically sorted list which when executed left-to-right will -/// correctly sequence the entire build. -pub fn all(build: &Build) -> Vec { - build.verbose("inferred build steps:"); - - let mut ret = Vec::new(); - let mut all = HashSet::new(); - for target in top_level(build) { - fill(build, &target, &mut ret, &mut all); - } - return ret; - - fn fill<'a>(build: &'a Build, - target: &Step<'a>, - ret: &mut Vec>, - set: &mut HashSet>) { - if set.insert(target.clone()) { - for dep in target.deps(build) { - build.verbose(&format!("{:?}\n -> {:?}", target, dep)); - fill(build, &dep, ret, set); - } - ret.push(target.clone()); - } + fn compiler(&self) -> Compiler<'a> { + Compiler::new(self.stage, self.host) } } -/// Determines what top-level targets are requested as part of this build, -/// returning them as a list. -fn top_level(build: &Build) -> Vec { - let mut targets = Vec::new(); - let stage = build.flags.stage.unwrap_or(2); +pub fn run(build: &Build) { + let rules = build_rules(build); + let steps = rules.plan(); + rules.run(&steps); +} - let host = Step { - src: Source::Llvm { _dummy: () }, - target: build.flags.host.iter().next() - .unwrap_or(&build.config.build), - }; - let target = Step { - src: Source::Llvm { _dummy: () }, - target: build.flags.target.iter().next().map(|x| &x[..]) - .unwrap_or(host.target) +pub fn build_rules(build: &Build) -> Rules { + let mut rules: Rules = Rules::new(build); + // dummy rule to do nothing, useful when a dep maps to no deps + rules.build("dummy", "path/to/nowhere"); + fn dummy<'a>(s: &Step<'a>, build: &'a Build) -> Step<'a> { + s.name("dummy").stage(0) + .target(&build.config.build) + .host(&build.config.build) + } + + // Helper for loading an entire DAG of crates, rooted at `name` + let krates = |name: &str| { + let mut ret = Vec::new(); + let mut list = vec![name]; + let mut visited = HashSet::new(); + while let Some(krate) = list.pop() { + let default = krate == name; + let krate = &build.crates[krate]; + let path = krate.path.strip_prefix(&build.src).unwrap(); + ret.push((krate, path.to_str().unwrap(), default)); + for dep in krate.deps.iter() { + if visited.insert(dep) && dep != "build_helper" { + list.push(dep); + } + } + } + return ret }; - // First, try to find steps on the command line. - add_steps(build, stage, &host, &target, &mut targets); + rules.build("rustc", "path/to/nowhere") + .dep(move |s| { + if s.stage == 0 { + dummy(s, build) + } else { + s.name("librustc") + .host(&build.config.build) + .stage(s.stage - 1) + } + }) + .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); + rules.build("llvm", "src/llvm") + .host(true) + .run(move |s| native::llvm(build, s.target)); + + // ======================================================================== + // Crate compilations + // + // Tools used during the build system but not shipped + rules.build("libstd", "src/libstd") + .dep(|s| s.name("build-crate-std_shim")); + rules.build("libtest", "src/libtest") + .dep(|s| s.name("build-crate-test_shim")); + rules.build("librustc", "src/librustc") + .dep(|s| s.name("build-crate-rustc-main")); + for (krate, path, _default) in krates("std_shim") { + rules.build(&krate.build_step, path) + .dep(|s| s.name("rustc").target(s.host)) + .dep(move |s| { + if s.host == build.config.build { + dummy(s, build) + } else { + s.host(&build.config.build) + } + }) + .run(move |s| { + if s.host == build.config.build { + compile::std(build, s.target, &s.compiler()) + } else { + compile::std_link(build, s.target, s.stage, s.host) + } + }); + } + for (krate, path, default) in krates("test_shim") { + rules.build(&krate.build_step, path) + .dep(|s| s.name("libstd")) + .dep(move |s| { + if s.host == build.config.build { + dummy(s, build) + } else { + s.host(&build.config.build) + } + }) + .default(default) + .run(move |s| { + if s.host == build.config.build { + compile::test(build, s.target, &s.compiler()) + } else { + compile::test_link(build, s.target, s.stage, s.host) + } + }); + } + for (krate, path, default) in krates("rustc-main") { + rules.build(&krate.build_step, path) + .dep(|s| s.name("libtest")) + .dep(move |s| s.name("llvm").host(&build.config.build).stage(0)) + .dep(move |s| { + if s.host == build.config.build { + dummy(s, build) + } else { + s.host(&build.config.build) + } + }) + .host(true) + .default(default) + .run(move |s| { + if s.host == build.config.build { + compile::rustc(build, s.target, &s.compiler()) + } else { + compile::rustc_link(build, s.target, s.stage, s.host) + } + }); + } - // If none are specified, then build everything. - if targets.len() == 0 { - let t = Step { - src: Source::Llvm { _dummy: () }, - target: &build.config.build, + // ======================================================================== + // Test targets + // + // Various unit tests and tests suites we can run + { + let mut suite = |name, path, dir, mode| { + rules.test(name, path) + .dep(|s| s.name("libtest")) + .dep(|s| s.name("tool-compiletest").target(s.host)) + .dep(|s| s.name("test-helpers")) + .dep(move |s| { + if s.target.contains("android") { + s.name("android-copy-libs") + } else { + dummy(s, build) + } + }) + .default(true) + .run(move |s| { + check::compiletest(build, &s.compiler(), s.target, dir, mode) + }); }; - if build.config.docs { - targets.push(t.doc(stage)); - } - for host in build.config.host.iter() { - if !build.flags.host.contains(host) { - continue - } - let host = t.target(host); - if host.target == build.config.build { - targets.push(host.librustc(host.compiler(stage))); - } else { - targets.push(host.librustc_link(t.compiler(stage), host.target)); - } - for target in build.config.target.iter() { - if !build.flags.target.contains(target) { - continue - } - if host.target == build.config.build { - targets.push(host.target(target) - .libtest(host.compiler(stage))); - } else { - targets.push(host.target(target) - .libtest_link(t.compiler(stage), host.target)); - } - } + suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass"); + suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail"); + suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail"); + suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail"); + suite("check-rpass-valgrind", "src/test/run-pass-valgrind", + "run-pass-valgrind", "run-pass-valgrind"); + suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt"); + if build.config.codegen_tests { + suite("check-codegen", "src/test/codegen", "codegen", "codegen"); } + suite("check-codegen-units", "src/test/codegen-units", "codegen-units", + "codegen-units"); + suite("check-incremental", "src/test/incremental", "incremental", + "incremental"); + suite("check-ui", "src/test/ui", "ui", "ui"); + suite("check-pretty", "src/test/pretty", "pretty", "pretty"); + suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", + "run-pass"); + suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty", + "run-fail"); + suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty", + "run-pass-valgrind"); } - targets -} + if build.config.build.contains("msvc") { + // nothing to do for debuginfo tests + } else if build.config.build.contains("apple") { + rules.test("check-debuginfo", "src/test/debuginfo") + .dep(|s| s.name("libtest")) + .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("test-helpers")) + .dep(|s| s.name("debugger-scripts")) + .run(move |s| check::compiletest(build, &s.compiler(), s.target, + "debuginfo-lldb", "debuginfo")); + } else { + rules.test("check-debuginfo", "src/test/debuginfo") + .dep(|s| s.name("libtest")) + .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("test-helpers")) + .dep(|s| s.name("debugger-scripts")) + .run(move |s| check::compiletest(build, &s.compiler(), s.target, + "debuginfo-gdb", "debuginfo")); + } -fn add_steps<'a>(build: &'a Build, - stage: u32, - host: &Step<'a>, - target: &Step<'a>, - targets: &mut Vec>) { - struct Context<'a> { - stage: u32, - compiler: Compiler<'a>, - _dummy: (), - host: &'a str, - } - for step in build.flags.step.iter() { - - // The macro below insists on hygienic access to all local variables, so - // we shove them all in a struct and subvert hygiene by accessing struct - // fields instead, - let cx = Context { - stage: stage, - compiler: host.target(&build.config.build).compiler(stage), - _dummy: (), - host: host.target, + rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") + .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()), + s.target)); + + { + let mut suite = |name, path, dir, mode| { + rules.test(name, path) + .dep(|s| s.name("librustc")) + .dep(|s| s.name("tool-compiletest").target(s.host)) + .default(true) + .host(true) + .run(move |s| { + check::compiletest(build, &s.compiler(), s.target, dir, mode) + }); }; - macro_rules! add_step { - ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => ({$( - let name = stringify!($short).replace("_", "-"); - if &step[..] == &name[..] { - targets.push(target.$short($(cx.$arg),*)); - continue - } - drop(name); - )*}) + + suite("check-rpass-full", "src/test/run-pass-fulldeps", + "run-pass", "run-pass-fulldeps"); + suite("check-cfail-full", "src/test/compile-fail-fulldeps", + "compile-fail", "compile-fail-fulldeps"); + suite("check-rmake", "src/test/run-make", "run-make", "run-make"); + suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); + suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps", + "pretty", "run-pass-fulldeps"); + suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps", + "pretty", "run-fail-fulldeps"); + } + + for (krate, path, _default) in krates("std_shim") { + rules.test(&krate.test_step, path) + .dep(|s| s.name("libtest")) + .run(move |s| check::krate(build, &s.compiler(), s.target, + Mode::Libstd, Some(&krate.name))); + } + rules.test("check-std-all", "path/to/nowhere") + .dep(|s| s.name("libtest")) + .default(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libstd, + None)); + for (krate, path, _default) in krates("test_shim") { + rules.test(&krate.test_step, path) + .dep(|s| s.name("libtest")) + .run(move |s| check::krate(build, &s.compiler(), s.target, + Mode::Libtest, Some(&krate.name))); + } + rules.test("check-test-all", "path/to/nowhere") + .dep(|s| s.name("libtest")) + .default(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libtest, + None)); + for (krate, path, _default) in krates("rustc-main") { + rules.test(&krate.test_step, path) + .dep(|s| s.name("libtest")) + .host(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, + Mode::Librustc, Some(&krate.name))); + } + rules.test("check-rustc-all", "path/to/nowhere") + .dep(|s| s.name("libtest")) + .default(true) + .host(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc, + None)); + + rules.test("check-linkchecker", "src/tools/linkchecker") + .dep(|s| s.name("tool-linkchecker")) + .dep(|s| s.name("default:doc")) + .default(true) + .run(move |s| check::linkcheck(build, s.stage, s.target)); + rules.test("check-cargotest", "src/tools/cargotest") + .dep(|s| s.name("tool-cargotest")) + .dep(|s| s.name("librustc")) + .run(move |s| check::cargotest(build, s.stage, s.target)); + rules.test("check-tidy", "src/tools/tidy") + .dep(|s| s.name("tool-tidy")) + .default(true) + .run(move |s| check::tidy(build, s.stage, s.target)); + rules.test("check-error-index", "src/tools/error_index_generator") + .dep(|s| s.name("libstd")) + .dep(|s| s.name("tool-error-index").host(s.host)) + .default(true) + .run(move |s| check::error_index(build, &s.compiler())); + rules.test("check-docs", "src/doc") + .dep(|s| s.name("libtest")) + .default(true) + .run(move |s| check::docs(build, &s.compiler())); + + rules.build("test-helpers", "src/rt/rust_test_helpers.c") + .run(move |s| native::test_helpers(build, s.target)); + rules.test("android-copy-libs", "path/to/nowhere") + .dep(|s| s.name("libtest")) + .run(move |s| check::android_copy_libs(build, &s.compiler(), s.target)); + + // ======================================================================== + // Build tools + // + // Tools used during the build system but not shipped + rules.build("tool-rustbook", "src/tools/rustbook") + .dep(|s| s.name("librustc")) + .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); + rules.build("tool-error-index", "src/tools/error_index_generator") + .dep(|s| s.name("librustc")) + .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); + rules.build("tool-tidy", "src/tools/tidy") + .dep(|s| s.name("libstd")) + .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); + rules.build("tool-linkchecker", "src/tools/linkchecker") + .dep(|s| s.name("libstd")) + .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); + rules.build("tool-cargotest", "src/tools/cargotest") + .dep(|s| s.name("libstd")) + .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); + rules.build("tool-compiletest", "src/tools/compiletest") + .dep(|s| s.name("libtest")) + .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); + + // ======================================================================== + // Documentation targets + rules.doc("doc-book", "src/doc/book") + .dep(move |s| s.name("tool-rustbook").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::rustbook(build, s.stage, s.target, "book")); + rules.doc("doc-nomicon", "src/doc/nomicon") + .dep(move |s| s.name("tool-rustbook").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::rustbook(build, s.stage, s.target, "nomicon")); + rules.doc("doc-standalone", "src/doc") + .dep(move |s| s.name("rustc").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::standalone(build, s.stage, s.target)); + rules.doc("doc-error-index", "src/tools/error_index_generator") + .dep(move |s| s.name("tool-error-index").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::error_index(build, s.stage, s.target)); + for (krate, path, default) in krates("std_shim") { + rules.doc(&krate.doc_step, path) + .dep(|s| s.name("libstd")) + .default(default && build.config.docs) + .run(move |s| doc::std(build, s.stage, s.target)); + } + for (krate, path, default) in krates("test_shim") { + rules.doc(&krate.doc_step, path) + .dep(|s| s.name("libtest")) + .default(default && build.config.docs) + .run(move |s| doc::test(build, s.stage, s.target)); + } + for (krate, path, default) in krates("rustc-main") { + rules.doc(&krate.doc_step, path) + .dep(|s| s.name("librustc")) + .host(true) + .default(default && build.config.compiler_docs) + .run(move |s| doc::rustc(build, s.stage, s.target)); + } + + // ======================================================================== + // Distribution targets + rules.dist("dist-rustc", "src/librustc") + .dep(|s| s.name("rustc")) + .host(true) + .default(true) + .run(move |s| dist::rustc(build, s.stage, s.target)); + rules.dist("dist-std", "src/libstd") + .dep(move |s| { + // We want to package up as many target libraries as possible + // for the `rust-std` package, so if this is a host target we + // depend on librustc and otherwise we just depend on libtest. + if build.config.host.iter().any(|t| t == s.target) { + s.name("librustc") + } else { + s.name("libtest") + } + }) + .default(true) + .run(move |s| dist::std(build, &s.compiler(), s.target)); + rules.dist("dist-mingw", "path/to/nowhere") + .run(move |s| dist::mingw(build, s.target)); + rules.dist("dist-src", "src") + .default(true) + .host(true) + .run(move |_| dist::rust_src(build)); + rules.dist("dist-docs", "src/doc") + .dep(|s| s.name("default:doc")) + .run(move |s| dist::docs(build, s.stage, s.target)); + rules.dist("install", "src") + .dep(|s| s.name("default:dist")) + .run(move |s| install::install(build, s.stage, s.target)); + + rules.verify(); + return rules +} + +struct Rule<'a> { + name: &'a str, + path: &'a str, + kind: Kind, + deps: Vec) -> Step<'a> + 'a>>, + run: Box) + 'a>, + default: bool, + host: bool, +} + +#[derive(PartialEq)] +enum Kind { + Build, + Test, + Dist, + Doc, +} + +impl<'a> Rule<'a> { + fn new(name: &'a str, path: &'a str, kind: Kind) -> Rule<'a> { + Rule { + name: name, + deps: Vec::new(), + run: Box::new(|_| ()), + path: path, + kind: kind, + default: false, + host: false, } + } +} + +struct RuleBuilder<'a: 'b, 'b> { + rules: &'b mut Rules<'a>, + rule: Rule<'a>, +} - targets!(add_step); +impl<'a, 'b> RuleBuilder<'a, 'b> { + fn dep(&mut self, f: F) -> &mut Self + where F: Fn(&Step<'a>) -> Step<'a> + 'a, + { + self.rule.deps.push(Box::new(f)); + self + } + + fn run(&mut self, f: F) -> &mut Self + where F: Fn(&Step<'a>) + 'a, + { + self.rule.run = Box::new(f); + self + } + + fn default(&mut self, default: bool) -> &mut Self { + self.rule.default = default; + self + } - panic!("unknown step: {}", step); + fn host(&mut self, host: bool) -> &mut Self { + self.rule.host = host; + self } } -macro_rules! constructors { - ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$( - fn $short(&self, $($arg: $t),*) -> Step<'a> { - Step { - src: Source::$name { $($arg: $arg),* }, - target: self.target, - } +impl<'a, 'b> Drop for RuleBuilder<'a, 'b> { + fn drop(&mut self) { + let rule = mem::replace(&mut self.rule, Rule::new("", "", Kind::Build)); + let prev = self.rules.rules.insert(rule.name, rule); + if let Some(prev) = prev { + panic!("duplicate rule named: {}", prev.name); } - )*} + } } -impl<'a> Step<'a> { - fn compiler(&self, stage: u32) -> Compiler<'a> { - Compiler::new(stage, self.target) +pub struct Rules<'a> { + build: &'a Build, + sbuild: Step<'a>, + rules: HashMap<&'a str, Rule<'a>>, +} + +impl<'a> Rules<'a> { + fn new(build: &'a Build) -> Rules<'a> { + Rules { + build: build, + sbuild: Step { + stage: build.flags.stage.unwrap_or(2), + target: &build.config.build, + host: &build.config.build, + name: "", + }, + rules: HashMap::new(), + } } - fn target(&self, target: &'a str) -> Step<'a> { - Step { target: target, src: self.src.clone() } + fn build<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Build) } - // Define ergonomic constructors for each step defined above so they can be - // easily constructed. - targets!(constructors); + fn test<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Test) + } - /// Mapping of all dependencies for rustbuild. - /// - /// This function receives a step, the build that we're building for, and - /// then returns a list of all the dependencies of that step. - pub fn deps(&self, build: &'a Build) -> Vec> { - match self.src { - Source::Rustc { stage: 0 } => { - Vec::new() - } - Source::Rustc { stage } => { - let compiler = Compiler::new(stage - 1, &build.config.build); - vec![self.librustc(compiler)] - } - Source::Librustc { compiler } => { - vec![self.libtest(compiler), self.llvm(())] - } - Source::Libtest { compiler } => { - vec![self.libstd(compiler)] - } - Source::Libstd { compiler } => { - vec![self.rustc(compiler.stage).target(compiler.host)] - } - Source::LibrustcLink { compiler, host } => { - vec![self.librustc(compiler), - self.libtest_link(compiler, host)] - } - Source::LibtestLink { compiler, host } => { - vec![self.libtest(compiler), self.libstd_link(compiler, host)] - } - Source::LibstdLink { compiler, host } => { - vec![self.libstd(compiler), - self.target(host).rustc(compiler.stage)] - } - Source::Llvm { _dummy } => Vec::new(), - Source::TestHelpers { _dummy } => Vec::new(), - Source::DebuggerScripts { stage: _ } => Vec::new(), - - // Note that all doc targets depend on artifacts from the build - // architecture, not the target (which is where we're generating - // docs into). - Source::DocStd { stage } => { - let compiler = self.target(&build.config.build).compiler(stage); - vec![self.libstd(compiler)] - } - Source::DocTest { stage } => { - let compiler = self.target(&build.config.build).compiler(stage); - vec![self.libtest(compiler)] - } - Source::DocBook { stage } | - Source::DocNomicon { stage } => { - vec![self.target(&build.config.build).tool_rustbook(stage)] - } - Source::DocErrorIndex { stage } => { - vec![self.target(&build.config.build).tool_error_index(stage)] - } - Source::DocStandalone { stage } => { - vec![self.target(&build.config.build).rustc(stage)] - } - Source::DocRustc { stage } => { - vec![self.doc_test(stage)] - } - Source::Doc { stage } => { - let mut deps = vec![ - self.doc_book(stage), self.doc_nomicon(stage), - self.doc_standalone(stage), self.doc_std(stage), - self.doc_error_index(stage), - ]; - - if build.config.compiler_docs { - deps.push(self.doc_rustc(stage)); - } + fn doc<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Doc) + } - deps - } - Source::Check { stage, compiler } => { - // Check is just a pseudo step which means check all targets, - // so just depend on checking all targets. - build.config.target.iter().map(|t| { - self.target(t).check_target(stage, compiler) - }).collect() - } - Source::CheckTarget { stage, compiler } => { - // CheckTarget here means run all possible test suites for this - // target. Most of the time, however, we can't actually run - // anything if we're not the build triple as we could be cross - // compiling. - // - // As a result, the base set of targets here is quite stripped - // down from the standard set of targets. These suites have - // their own internal logic to run in cross-compiled situations - // if they'll run at all. For example compiletest knows that - // when testing Android targets we ship artifacts to the - // emulator. - // - // When in doubt the rule of thumb for adding to this list is - // "should this test suite run on the android bot?" - let mut base = vec![ - self.check_rpass(compiler), - self.check_rfail(compiler), - self.check_crate_std(compiler), - self.check_crate_test(compiler), - self.check_debuginfo(compiler), - ]; - - // If we're testing the build triple, then we know we can - // actually run binaries and such, so we run all possible tests - // that we know about. - if self.target == build.config.build { - base.extend(vec![ - // docs-related - self.check_docs(compiler), - self.check_error_index(compiler), - self.check_rustdoc(compiler), - - // UI-related - self.check_cfail(compiler), - self.check_pfail(compiler), - self.check_ui(compiler), - - // codegen-related - self.check_incremental(compiler), - self.check_codegen(compiler), - self.check_codegen_units(compiler), - - // misc compiletest-test suites - self.check_rpass_full(compiler), - self.check_rfail_full(compiler), - self.check_cfail_full(compiler), - self.check_pretty_rpass_full(compiler), - self.check_pretty_rfail_full(compiler), - self.check_rpass_valgrind(compiler), - self.check_rmake(compiler), - self.check_mir_opt(compiler), - - // crates - self.check_crate_rustc(compiler), - - // pretty - self.check_pretty(compiler), - self.check_pretty_rpass(compiler), - self.check_pretty_rfail(compiler), - self.check_pretty_rpass_valgrind(compiler), - - // misc - self.check_linkcheck(stage), - self.check_tidy(stage), - - // can we make the distributables? - self.dist(stage), - ]); - } - base - } - Source::CheckLinkcheck { stage } => { - vec![self.tool_linkchecker(stage), self.doc(stage)] - } - Source::CheckCargoTest { stage } => { - vec![self.tool_cargotest(stage), - self.librustc(self.compiler(stage))] - } - Source::CheckTidy { stage } => { - vec![self.tool_tidy(stage)] - } - Source::CheckMirOpt { compiler} | - Source::CheckPrettyRPass { compiler } | - Source::CheckPrettyRFail { compiler } | - Source::CheckRFail { compiler } | - Source::CheckPFail { compiler } | - Source::CheckCodegen { compiler } | - Source::CheckCodegenUnits { compiler } | - Source::CheckIncremental { compiler } | - Source::CheckUi { compiler } | - Source::CheckPretty { compiler } | - Source::CheckCFail { compiler } | - Source::CheckRPassValgrind { compiler } | - Source::CheckRPass { compiler } => { - let mut base = vec![ - self.libtest(compiler), - self.target(compiler.host).tool_compiletest(compiler.stage), - self.test_helpers(()), - ]; - if self.target.contains("android") { - base.push(self.android_copy_libs(compiler)); - } - base - } - Source::CheckDebuginfo { compiler } => { - vec![ - self.libtest(compiler), - self.target(compiler.host).tool_compiletest(compiler.stage), - self.test_helpers(()), - self.debugger_scripts(compiler.stage), - ] - } - Source::CheckRustdoc { compiler } | - Source::CheckRPassFull { compiler } | - Source::CheckRFailFull { compiler } | - Source::CheckCFailFull { compiler } | - Source::CheckPrettyRPassFull { compiler } | - Source::CheckPrettyRFailFull { compiler } | - Source::CheckPrettyRPassValgrind { compiler } | - Source::CheckRMake { compiler } => { - vec![self.librustc(compiler), - self.target(compiler.host).tool_compiletest(compiler.stage)] - } - Source::CheckDocs { compiler } => { - vec![self.libtest(compiler)] - } - Source::CheckErrorIndex { compiler } => { - vec![self.libstd(compiler), - self.target(compiler.host).tool_error_index(compiler.stage)] - } - Source::CheckCrateStd { compiler } => { - vec![self.libtest(compiler)] - } - Source::CheckCrateTest { compiler } => { - vec![self.libtest(compiler)] - } - Source::CheckCrateRustc { compiler } => { - vec![self.libtest(compiler)] - } + fn dist<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Dist) + } - Source::ToolLinkchecker { stage } | - Source::ToolTidy { stage } => { - vec![self.libstd(self.compiler(stage))] - } - Source::ToolErrorIndex { stage } | - Source::ToolRustbook { stage } => { - vec![self.librustc(self.compiler(stage))] - } - Source::ToolCargoTest { stage } => { - vec![self.libstd(self.compiler(stage))] - } - Source::ToolCompiletest { stage } => { - vec![self.libtest(self.compiler(stage))] - } + fn rule<'b>(&'b mut self, + name: &'a str, + path: &'a str, + kind: Kind) -> RuleBuilder<'a, 'b> { + RuleBuilder { + rules: self, + rule: Rule::new(name, path, kind), + } + } + + /// Verify the dependency graph defined by all our rules are correct, e.g. + /// everything points to a valid something else. + fn verify(&self) { + for rule in self.rules.values() { + for dep in rule.deps.iter() { + let dep = dep(&self.sbuild.name(rule.name)); + if self.rules.contains_key(&dep.name) || dep.name.starts_with("default:") { + continue } + panic!("\ + +invalid rule dependency graph detected, was a rule added and maybe typo'd? + + `{}` depends on `{}` which does not exist - Source::DistDocs { stage } => vec![self.doc(stage)], - Source::DistMingw { _dummy: _ } => Vec::new(), - Source::DistRustc { stage } => { - vec![self.rustc(stage)] +", rule.name, dep.name); } - Source::DistStd { compiler } => { - // We want to package up as many target libraries as possible - // for the `rust-std` package, so if this is a host target we - // depend on librustc and otherwise we just depend on libtest. - if build.config.host.iter().any(|t| t == self.target) { - vec![self.librustc(compiler)] + } + } + + pub fn print_help(&self, command: &str) { + let kind = match command { + "build" => Kind::Build, + "doc" => Kind::Doc, + "test" => Kind::Test, + "dist" => Kind::Dist, + _ => return, + }; + let rules = self.rules.values().filter(|r| r.kind == kind); + let rules = rules.filter(|r| !r.path.contains("nowhere")); + let mut rules = rules.collect::>(); + rules.sort_by_key(|r| r.path); + + println!("Available paths:\n"); + for rule in rules { + print!(" ./x.py {} {}", command, rule.path); + + println!(""); + } + } + + /// Construct the top-level build steps that we're going to be executing, + /// given the subcommand that our build is performing. + fn plan(&self) -> Vec> { + let (kind, paths) = match self.build.flags.cmd { + Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), + Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), + Subcommand::Test { ref paths, test_args: _ } => (Kind::Test, &paths[..]), + Subcommand::Dist { install } => { + if install { + return vec![self.sbuild.name("install")] } else { - vec![self.libtest(compiler)] - } - } - Source::DistSrc { _dummy: _ } => Vec::new(), - - Source::Dist { stage } => { - let mut base = Vec::new(); - - for host in build.config.host.iter() { - let host = self.target(host); - base.push(host.dist_src(())); - base.push(host.dist_rustc(stage)); - if host.target.contains("windows-gnu") { - base.push(host.dist_mingw(())); - } - - let compiler = self.compiler(stage); - for target in build.config.target.iter() { - let target = self.target(target); - if build.config.docs { - base.push(target.dist_docs(stage)); - } - base.push(target.dist_std(compiler)); - } + (Kind::Dist, &[][..]) } - base } + Subcommand::Clean => panic!(), + }; - Source::Install { stage } => { - vec![self.dist(stage)] - } + self.rules.values().filter(|rule| rule.kind == kind).filter(|rule| { + (paths.len() == 0 && rule.default) || paths.iter().any(|path| { + path.ends_with(rule.path) + }) + }).flat_map(|rule| { + let hosts = if self.build.flags.host.len() > 0 { + &self.build.flags.host + } else { + &self.build.config.host + }; + let targets = if self.build.flags.target.len() > 0 { + &self.build.flags.target + } else { + &self.build.config.target + }; + let arr = if rule.host {hosts} else {targets}; + + hosts.iter().flat_map(move |host| { + arr.iter().map(move |target| { + self.sbuild.name(rule.name).target(target).host(host) + }) + }) + }).collect() + } + + /// Execute all top-level targets indicated by `steps`. + /// + /// This will take the list returned by `plan` and then execute each step + /// along with all required dependencies as it goes up the chain. + fn run(&self, steps: &[Step<'a>]) { + self.build.verbose("bootstrap top targets:"); + for step in steps.iter() { + self.build.verbose(&format!("\t{:?}", step)); + } + + // Using `steps` as the top-level targets, make a topological ordering + // of what we need to do. + let mut order = Vec::new(); + let mut added = HashSet::new(); + for step in steps.iter().cloned() { + self.fill(step, &mut order, &mut added); + } - Source::AndroidCopyLibs { compiler } => { - vec![self.libtest(compiler)] + // Print out what we're doing for debugging + self.build.verbose("bootstrap build plan:"); + for step in order.iter() { + self.build.verbose(&format!("\t{:?}", step)); + } + + // And finally, iterate over everything and execute it. + for step in order.iter() { + (self.rules[step.name].run)(step); + } + } + + fn fill(&self, + step: Step<'a>, + order: &mut Vec>, + added: &mut HashSet>) { + if !added.insert(step.clone()) { + return + } + for dep in self.rules[step.name].deps.iter() { + let dep = dep(&step); + if dep.name.starts_with("default:") { + let kind = match &dep.name[8..] { + "doc" => Kind::Doc, + "dist" => Kind::Dist, + kind => panic!("unknown kind: `{}`", kind), + }; + let rules = self.rules.values().filter(|r| r.default); + for rule in rules.filter(|r| r.kind == kind) { + self.fill(dep.name(rule.name), order, added); + } + } else { + self.fill(dep, order, added); } } + order.push(step); } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6c0a32a54d919..d552f5928a929 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -57,8 +57,7 @@ pub fn cp_r(src: &Path, dst: &Path) { let name = path.file_name().unwrap(); let dst = dst.join(name); if t!(f.file_type()).is_dir() { - let _ = fs::remove_dir_all(&dst); - t!(fs::create_dir(&dst)); + t!(fs::create_dir_all(&dst)); cp_r(&path, &dst); } else { let _ = fs::remove_file(&dst); diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 128c270eb359c..c92e4d8f5aba5 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -11,4 +11,4 @@ crate-type = ["dylib"] [dependencies] log = { path = "../liblog" } serialize = { path = "../libserialize" } -syntax_pos = { path = "../libsyntax_pos" } \ No newline at end of file +syntax_pos = { path = "../libsyntax_pos" } diff --git a/x.py b/x.py new file mode 100755 index 0000000000000..54148b0d2b29d --- /dev/null +++ b/x.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# 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 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import sys +import os +dir = os.path.dirname(__file__) +sys.path.append(os.path.abspath(os.path.join(dir, "src", "bootstrap"))) + +import bootstrap + +bootstrap.main() From 7d06bdd4a148ccb924cd6628a94ca8bc0d3611fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Inf=C3=BChr?= Date: Thu, 3 Nov 2016 10:53:13 +0100 Subject: [PATCH 14/41] set frame pointer elimination attribute for main The rustc-generated function `main` should respect the same config for frame pointer elimination as the rest of code. --- src/librustc_trans/base.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 977ababbf5688..47b6fdc740a34 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1196,6 +1196,9 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) { } let llfn = declare::declare_cfn(ccx, "main", llfty); + // `main` should respect same config for frame pointer elimination as rest of code + attributes::set_frame_pointer_elimination(ccx, llfn); + let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, "top\0".as_ptr() as *const _) }; From dc138b3156677f81f9be2afbf80465a0be8179c8 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Thu, 3 Nov 2016 11:51:11 +0100 Subject: [PATCH 15/41] use DefId's in const eval for cross-crate const fn's --- src/librustc_const_eval/eval.rs | 13 ++++++------- src/test/run-pass/auxiliary/issue-36954.rs | 18 ++++++++++++++++++ src/test/run-pass/issue-36954.rs | 17 +++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/auxiliary/issue-36954.rs create mode 100644 src/test/run-pass/issue-36954.rs diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c02cca0da7225..41baa1080b1fb 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -27,7 +27,7 @@ use rustc::ty::util::IntTypeExt; use rustc::ty::subst::Substs; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; -use rustc::util::nodemap::NodeMap; +use rustc::util::nodemap::DefIdMap; use rustc::lint; use graphviz::IntoCow; @@ -413,7 +413,7 @@ pub fn eval_const_expr_checked<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, eval_const_expr_partial(tcx, e, ExprTypeChecked, None) } -pub type FnArgMap<'a> = Option<&'a NodeMap>; +pub type FnArgMap<'a> = Option<&'a DefIdMap>; #[derive(Clone, Debug)] pub struct ConstEvalErr { @@ -835,9 +835,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ConstVal::Struct(e.id) } Def::Local(def_id) => { - let id = tcx.map.as_local_node_id(def_id).unwrap(); - debug!("Def::Local({:?}): {:?}", id, fn_args); - if let Some(val) = fn_args.and_then(|args| args.get(&id)) { + debug!("Def::Local({:?}): {:?}", def_id, fn_args); + if let Some(val) = fn_args.and_then(|args| args.get(&def_id)) { val.clone() } else { signal!(e, NonConstPath); @@ -863,7 +862,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let result = result.as_ref().expect("const fn has no result expression"); assert_eq!(decl.inputs.len(), args.len()); - let mut call_args = NodeMap(); + let mut call_args = DefIdMap(); for (arg, arg_expr) in decl.inputs.iter().zip(args.iter()) { let arg_hint = ty_hint.erase_hint(); let arg_val = eval_const_expr_partial( @@ -873,7 +872,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_args )?; debug!("const call arg: {:?}", arg); - let old = call_args.insert(arg.pat.id, arg_val); + let old = call_args.insert(tcx.expect_def(arg.pat.id).def_id(), arg_val); assert!(old.is_none()); } debug!("const call({:?})", call_args); diff --git a/src/test/run-pass/auxiliary/issue-36954.rs b/src/test/run-pass/auxiliary/issue-36954.rs new file mode 100644 index 0000000000000..832ee1d7c1b45 --- /dev/null +++ b/src/test/run-pass/auxiliary/issue-36954.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_fn)] +#![crate_type = "lib"] + +const fn foo(i: i32) -> i32 { + i +} + +pub const FOO: i32 = foo(1); diff --git a/src/test/run-pass/issue-36954.rs b/src/test/run-pass/issue-36954.rs new file mode 100644 index 0000000000000..f8330ba99b7ae --- /dev/null +++ b/src/test/run-pass/issue-36954.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-36954.rs + +extern crate issue_36954 as lib; + +fn main() { + let _ = lib::FOO; +} From ed0230ee568ca9325a1fb5ffeca2ee9b34233ce1 Mon Sep 17 00:00:00 2001 From: Martin Glagla Date: Thu, 3 Nov 2016 22:22:27 +0100 Subject: [PATCH 16/41] Peekable::peek(): Use Option::as_ref() --- src/libcore/iter/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index df4f5e5c57643..97a232de6718e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1341,10 +1341,7 @@ impl Peekable { if self.peeked.is_none() { self.peeked = self.iter.next(); } - match self.peeked { - Some(ref value) => Some(value), - None => None, - } + self.peeked.as_ref() } } From d5f72d21afffcda4cc71945f12477136774aa604 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Thu, 3 Nov 2016 14:55:35 -0600 Subject: [PATCH 17/41] Fix ICE when querying DefId on Def::Err. --- src/librustc_typeck/collect.rs | 7 +++---- src/test/compile-fail/issue-37534.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 src/test/compile-fail/issue-37534.rs diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 202e176df0dbc..0e0f5cb1a7e15 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1724,16 +1724,15 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, match unbound { Some(ref tpb) => { // FIXME(#8559) currently requires the unbound to be built-in. - let trait_def_id = tcx.expect_def(tpb.ref_id).def_id(); - match kind_id { - Ok(kind_id) if trait_def_id != kind_id => { + if let Ok(kind_id) = kind_id { + let trait_def = tcx.expect_def(tpb.ref_id); + if trait_def != Def::Trait(kind_id) { tcx.sess.span_warn(span, "default bound relaxed for a type parameter, but \ this does nothing because the given bound is not \ a default. Only `?Sized` is supported"); tcx.try_add_builtin_trait(kind_id, bounds); } - _ => {} } } _ if kind_id.is_ok() => { diff --git a/src/test/compile-fail/issue-37534.rs b/src/test/compile-fail/issue-37534.rs new file mode 100644 index 0000000000000..eb676601e89ce --- /dev/null +++ b/src/test/compile-fail/issue-37534.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { } +//~^ ERROR trait `Hash` is not in scope [E0405] +//~^^ ERROR parameter `T` is never used [E0392] +//~^^^ WARN default bound relaxed for a type parameter, but this does nothing + +fn main() { } From 6a34feb034407cfcc82ccd951c13fb654689f130 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 3 Nov 2016 22:15:43 +0000 Subject: [PATCH 18/41] Set RUSTC_BOOTSTRAP to some value. Environment variables on windows can't be empty. --- mk/main.mk | 2 +- src/bootstrap/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index a5e3764122003..2fa8ccf3621e0 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -372,7 +372,7 @@ CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATUR # Turn on feature-staging export CFG_DISABLE_UNSTABLE_FEATURES # Subvert unstable feature lints to do the self-build -export RUSTC_BOOTSTRAP +export RUSTC_BOOTSTRAP=1 endif ifdef CFG_MUSL_ROOT export CFG_MUSL_ROOT diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7c5a0c7373f88..fdd7a1ec57df9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -873,7 +873,7 @@ impl Build { /// Adds the compiler's bootstrap key to the environment of `cmd`. fn add_bootstrap_key(&self, cmd: &mut Command) { - cmd.env("RUSTC_BOOTSTRAP", ""); + cmd.env("RUSTC_BOOTSTRAP", "1"); // FIXME: Transitionary measure to bootstrap using the old bootstrap logic. // Remove this once the bootstrap compiler uses the new login in Issue #36548. cmd.env("RUSTC_BOOTSTRAP_KEY", "62b3e239"); From 5f280a5c608c6cb92fa75829599d5759ed6305a5 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 3 Nov 2016 03:33:21 +0000 Subject: [PATCH 19/41] Clean up `parser.parse_token_tree()`. --- src/libsyntax/parse/parser.rs | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b80aa667be6a1..eb68f5a309b9c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2833,29 +2833,20 @@ impl<'a> Parser<'a> { close_span: close_span, }))) }, + token::CloseDelim(_) => { + // An unexpected closing delimiter (i.e., there is no + // matching opening delimiter). + let token_str = self.this_token_to_string(); + let err = self.diagnostic().struct_span_err(self.span, + &format!("unexpected close delimiter: `{}`", token_str)); + Err(err) + }, + /* we ought to allow different depths of unquotation */ + token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => { + self.parse_unquoted() + } _ => { - // invariants: the current token is not a left-delimiter, - // not an EOF, and not the desired right-delimiter (if - // it were, parse_seq_to_before_end would have prevented - // reaching this point). - maybe_whole!(deref self, NtTT); - match self.token { - token::CloseDelim(_) => { - // An unexpected closing delimiter (i.e., there is no - // matching opening delimiter). - let token_str = self.this_token_to_string(); - let err = self.diagnostic().struct_span_err(self.span, - &format!("unexpected close delimiter: `{}`", token_str)); - Err(err) - }, - /* we ought to allow different depths of unquotation */ - token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => { - self.parse_unquoted() - } - _ => { - Ok(TokenTree::Token(self.span, self.bump_and_get())) - } - } + Ok(TokenTree::Token(self.span, self.bump_and_get())) } } } From eb3ac29a101f9388966175bb51e340a98b849b59 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 2 Nov 2016 03:03:55 +0000 Subject: [PATCH 20/41] Reduce the size of `Token` and make it cheaper to clone by refactoring `Token::Interpolated(Nonterminal)` -> `Token::Interpolated(Rc)`. --- src/libsyntax/ext/quote.rs | 54 ++++---- src/libsyntax/ext/tt/macro_parser.rs | 13 +- src/libsyntax/ext/tt/macro_rules.rs | 22 ++-- src/libsyntax/ext/tt/transcribe.rs | 24 ++-- src/libsyntax/fold.rs | 31 +++-- src/libsyntax/parse/attr.rs | 5 +- src/libsyntax/parse/parser.rs | 187 +++++++-------------------- src/libsyntax/parse/token.rs | 35 ++--- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/tokenstream.rs | 12 +- 10 files changed, 159 insertions(+), 226 deletions(-) diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index f21360755bc26..969cfa292ce80 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -80,67 +80,71 @@ pub mod rt { impl ToTokens for ast::Path { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, - token::Interpolated(token::NtPath(Box::new(self.clone()))))] + let nt = token::NtPath(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Ty { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtTy(P(self.clone()))))] + let nt = token::NtTy(P(self.clone())); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Block { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtBlock(P(self.clone()))))] + let nt = token::NtBlock(P(self.clone())); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Generics { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtGenerics(self.clone())))] + let nt = token::NtGenerics(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::WhereClause { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, - token::Interpolated(token::NtWhereClause(self.clone())))] + let nt = token::NtWhereClause(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtItem(self.clone())))] + let nt = token::NtItem(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::ImplItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, - token::Interpolated(token::NtImplItem(P(self.clone()))))] + let nt = token::NtImplItem(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtImplItem(self.clone())))] + let nt = token::NtImplItem((**self).clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::TraitItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, - token::Interpolated(token::NtTraitItem(P(self.clone()))))] + let nt = token::NtTraitItem(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Stmt { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - let mut tts = vec![ - TokenTree::Token(self.span, token::Interpolated(token::NtStmt(P(self.clone())))) - ]; + let nt = token::NtStmt(self.clone()); + let mut tts = vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]; // Some statements require a trailing semicolon. if classify::stmt_ends_with_semi(&self.node) { @@ -153,31 +157,36 @@ pub mod rt { impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtExpr(self.clone())))] + let nt = token::NtExpr(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtPat(self.clone())))] + let nt = token::NtPat(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Arm { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))] + let nt = token::NtArm(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Arg { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArg(self.clone())))] + let nt = token::NtArg(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtBlock(self.clone())))] + let nt = token::NtBlock(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } @@ -204,7 +213,8 @@ pub mod rt { impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))] + let nt = token::NtMeta(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 7e3fe3285695c..6680119d2eaa2 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -89,7 +89,6 @@ use parse::token::{DocComment, MatchNt, SubstNt}; use parse::token::{Token, Nonterminal}; use parse::token; use print::pprust; -use ptr::P; use tokenstream::{self, TokenTree}; use util::small_vector::SmallVector; @@ -198,7 +197,7 @@ pub fn initial_matcher_pos(ms: Vec, sep: Option, lo: BytePos) pub enum NamedMatch { MatchedSeq(Vec>, syntax_pos::Span), - MatchedNonterminal(Nonterminal) + MatchedNonterminal(Rc) } pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) @@ -482,7 +481,7 @@ pub fn parse(sess: &ParseSess, mut rdr: TtReader, ms: &[TokenTree]) -> NamedPars if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) { let match_cur = ei.match_cur; (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( - parse_nt(&mut rust_parser, span, &ident.name.as_str())))); + Rc::new(parse_nt(&mut rust_parser, span, &ident.name.as_str()))))); ei.idx += 1; ei.match_cur += 1; } else { @@ -503,7 +502,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "tt" => { p.quote_depth += 1; //but in theory, non-quoted tts might be useful let res: ::parse::PResult<'a, _> = p.parse_token_tree(); - let res = token::NtTT(P(panictry!(res))); + let res = token::NtTT(panictry!(res)); p.quote_depth -= 1; return res; } @@ -521,7 +520,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { }, "block" => token::NtBlock(panictry!(p.parse_block())), "stmt" => match panictry!(p.parse_stmt()) { - Some(s) => token::NtStmt(P(s)), + Some(s) => token::NtStmt(s), None => { p.fatal("expected a statement").emit(); panic!(FatalError); @@ -534,7 +533,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "ident" => match p.token { token::Ident(sn) => { p.bump(); - token::NtIdent(Box::new(Spanned::{node: sn, span: p.span})) + token::NtIdent(Spanned::{node: sn, span: p.span}) } _ => { let token_str = pprust::token_to_string(&p.token); @@ -544,7 +543,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { } }, "path" => { - token::NtPath(Box::new(panictry!(p.parse_path(PathStyle::Type)))) + token::NtPath(panictry!(p.parse_path(PathStyle::Type))) }, "meta" => token::NtMeta(panictry!(p.parse_meta_item())), // this is not supposed to happen, since it has been checked diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 431e757368c03..552d4de961740 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -236,12 +236,14 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { // Extract the arguments: let lhses = match **argument_map.get(&lhs_nm).unwrap() { MatchedSeq(ref s, _) => { - s.iter().map(|m| match **m { - MatchedNonterminal(NtTT(ref tt)) => { - valid &= check_lhs_nt_follows(sess, tt); - (**tt).clone() + s.iter().map(|m| { + if let MatchedNonterminal(ref nt) = **m { + if let NtTT(ref tt) = **nt { + valid &= check_lhs_nt_follows(sess, tt); + return (*tt).clone(); + } } - _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") + sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") }).collect::>() } _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") @@ -249,9 +251,13 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { let rhses = match **argument_map.get(&rhs_nm).unwrap() { MatchedSeq(ref s, _) => { - s.iter().map(|m| match **m { - MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(), - _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs") + s.iter().map(|m| { + if let MatchedNonterminal(ref nt) = **m { + if let NtTT(ref tt) = **nt { + return (*tt).clone(); + } + } + sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") }).collect() } _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs") diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 8a6a8e53a3e4c..641d69900f730 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -277,39 +277,37 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { return ret_val; // this can't be 0 length, just like TokenTree::Delimited } - Some(cur_matched) => { - match *cur_matched { + Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched { + match **nt { // sidestep the interpolation tricks for ident because // (a) idents can be in lots of places, so it'd be a pain // (b) we actually can, since it's a token. - MatchedNonterminal(NtIdent(ref sn)) => { + NtIdent(ref sn) => { r.stack.last_mut().unwrap().idx += 1; r.cur_span = sn.span; r.cur_tok = token::Ident(sn.node); return ret_val; } - MatchedNonterminal(NtTT(ref tt)) => { + NtTT(_) => { r.stack.push(TtFrame { - forest: TokenTree::Token(sp, Interpolated(NtTT(tt.clone()))), + forest: TokenTree::Token(sp, Interpolated(nt.clone())), idx: 0, dotdotdoted: false, sep: None, }); } - MatchedNonterminal(ref other_whole_nt) => { + _ => { r.stack.last_mut().unwrap().idx += 1; // FIXME(pcwalton): Bad copy. r.cur_span = sp; - r.cur_tok = Interpolated((*other_whole_nt).clone()); + r.cur_tok = Interpolated(nt.clone()); return ret_val; } - MatchedSeq(..) => { - panic!(r.sp_diag.span_fatal( - sp, /* blame the macro writer */ - &format!("variable '{}' is still repeating at this depth", - ident))); - } } + } else { + panic!(r.sp_diag.span_fatal( + sp, /* blame the macro writer */ + &format!("variable '{}' is still repeating at this depth", ident))); } } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4bf6e55d6743b..71aa0437609d1 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -576,7 +576,13 @@ pub fn noop_fold_token(t: token::Token, fld: &mut T) -> token::Token match t { token::Ident(id) => token::Ident(fld.fold_ident(id)), token::Lifetime(id) => token::Lifetime(fld.fold_ident(id)), - token::Interpolated(nt) => token::Interpolated(fld.fold_interpolated(nt)), + token::Interpolated(nt) => { + let nt = match Rc::try_unwrap(nt) { + Ok(nt) => nt, + Err(nt) => (*nt).clone(), + }; + token::Interpolated(Rc::new(fld.fold_interpolated(nt))) + } token::SubstNt(ident) => token::SubstNt(fld.fold_ident(ident)), token::MatchNt(name, kind) => token::MatchNt(fld.fold_ident(name), fld.fold_ident(kind)), _ => t @@ -614,26 +620,25 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) .expect_one("expected fold to produce exactly one item")), token::NtBlock(block) => token::NtBlock(fld.fold_block(block)), token::NtStmt(stmt) => - token::NtStmt(stmt.map(|stmt| fld.fold_stmt(stmt) + token::NtStmt(fld.fold_stmt(stmt) // this is probably okay, because the only folds likely // to peek inside interpolated nodes will be renamings/markings, // which map single items to single items - .expect_one("expected fold to produce exactly one statement"))), + .expect_one("expected fold to produce exactly one statement")), token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)), token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)), token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)), - token::NtIdent(id) => - token::NtIdent(Box::new(Spanned::{node: fld.fold_ident(id.node), ..*id})), + token::NtIdent(id) => token::NtIdent(Spanned::{node: fld.fold_ident(id.node), ..id}), token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)), - token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))), - token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&tt))), + token::NtPath(path) => token::NtPath(fld.fold_path(path)), + token::NtTT(tt) => token::NtTT(fld.fold_tt(&tt)), token::NtArm(arm) => token::NtArm(fld.fold_arm(arm)), - token::NtImplItem(arm) => - token::NtImplItem(arm.map(|arm| fld.fold_impl_item(arm) - .expect_one("expected fold to produce exactly one item"))), - token::NtTraitItem(arm) => - token::NtTraitItem(arm.map(|arm| fld.fold_trait_item(arm) - .expect_one("expected fold to produce exactly one item"))), + token::NtImplItem(item) => + token::NtImplItem(fld.fold_impl_item(item) + .expect_one("expected fold to produce exactly one item")), + token::NtTraitItem(item) => + token::NtTraitItem(fld.fold_trait_item(item) + .expect_one("expected fold to produce exactly one item")), token::NtGenerics(generics) => token::NtGenerics(fld.fold_generics(generics)), token::NtWhereClause(where_clause) => token::NtWhereClause(fld.fold_where_clause(where_clause)), diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 3cb34fa3c91c5..983c882eafca3 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -215,7 +215,10 @@ impl<'a> Parser<'a> { /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; pub fn parse_meta_item(&mut self) -> PResult<'a, P> { let nt_meta = match self.token { - token::Interpolated(token::NtMeta(ref e)) => Some(e.clone()), + token::Interpolated(ref nt) => match **nt { + token::NtMeta(ref e) => Some(e.clone()), + _ => None, + }, _ => None, }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index eb68f5a309b9c..f77525ff549d9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -107,125 +107,41 @@ pub enum SemiColonMode { /// be. The important thing is to make sure that lookahead doesn't balk at /// `token::Interpolated` tokens. macro_rules! maybe_whole_expr { - ($p:expr) => ( - { - let found = match $p.token { - token::Interpolated(token::NtExpr(ref e)) => { - Some((*e).clone()) + ($p:expr) => { + if let token::Interpolated(nt) = $p.token.clone() { + match *nt { + token::NtExpr(ref e) => { + $p.bump(); + return Ok((*e).clone()); } - token::Interpolated(token::NtPath(_)) => { - // FIXME: The following avoids an issue with lexical borrowck scopes, - // but the clone is unfortunate. - let pt = match $p.token { - token::Interpolated(token::NtPath(ref pt)) => (**pt).clone(), - _ => unreachable!() - }; + token::NtPath(ref path) => { + $p.bump(); let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), ThinVec::new())) + let kind = ExprKind::Path(None, (*path).clone()); + return Ok($p.mk_expr(span.lo, span.hi, kind, ThinVec::new())); } - token::Interpolated(token::NtBlock(_)) => { - // FIXME: The following avoids an issue with lexical borrowck scopes, - // but the clone is unfortunate. - let b = match $p.token { - token::Interpolated(token::NtBlock(ref b)) => (*b).clone(), - _ => unreachable!() - }; + token::NtBlock(ref block) => { + $p.bump(); let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), ThinVec::new())) + let kind = ExprKind::Block((*block).clone()); + return Ok($p.mk_expr(span.lo, span.hi, kind, ThinVec::new())); } - _ => None + _ => {}, }; - match found { - Some(e) => { - $p.bump(); - return Ok(e); - } - None => () - } } - ) + } } /// As maybe_whole_expr, but for things other than expressions macro_rules! maybe_whole { - ($p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(x.clone()); - } - } - ); - (no_clone $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(x); - } - } - ); - (no_clone_from_p $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(x.unwrap()); - } - } - ); - (deref $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok((*x).clone()); - } - } - ); - (Some deref $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(Some((*x).clone())); - } - } - ); - (pair_empty $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok((Vec::new(), x)); + ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { + if let token::Interpolated(nt) = $p.token.clone() { + if let token::$constructor($x) = (*nt).clone() { + $p.bump(); + return Ok($e); } } - ) + }; } fn maybe_append(mut lhs: Vec, rhs: Option>) @@ -516,9 +432,6 @@ impl<'a> Parser<'a> { self.bump(); Ok(i) } - token::Interpolated(token::NtIdent(..)) => { - self.bug("ident interpolation not converted to real token"); - } _ => { Err(if self.prev_token_kind == PrevTokenKind::DocComment { self.span_fatal_help(self.prev_span, @@ -1162,7 +1075,7 @@ impl<'a> Parser<'a> { /// Parse the items in a trait declaration pub fn parse_trait_item(&mut self) -> PResult<'a, TraitItem> { - maybe_whole!(no_clone_from_p self, NtTraitItem); + maybe_whole!(self, NtTraitItem, |x| x); let mut attrs = self.parse_outer_attributes()?; let lo = self.span.lo; @@ -1331,7 +1244,7 @@ impl<'a> Parser<'a> { /// Parse a type. pub fn parse_ty(&mut self) -> PResult<'a, P> { - maybe_whole!(no_clone self, NtTy); + maybe_whole!(self, NtTy, |x| x); let lo = self.span.lo; @@ -1476,7 +1389,7 @@ impl<'a> Parser<'a> { /// This version of parse arg doesn't necessarily require /// identifier names. pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { - maybe_whole!(no_clone self, NtArg); + maybe_whole!(self, NtArg, |x| x); let pat = if require_name || self.is_named_argument() { debug!("parse_arg_general parse_pat (require_name:{})", @@ -1542,12 +1455,13 @@ impl<'a> Parser<'a> { /// Matches token_lit = LIT_INTEGER | ... pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> { let out = match self.token { - token::Interpolated(token::NtExpr(ref v)) => { - match v.node { + token::Interpolated(ref nt) => match **nt { + token::NtExpr(ref v) => match v.node { ExprKind::Lit(ref lit) => { lit.node.clone() } _ => { return self.unexpected_last(&self.token); } - } - } + }, + _ => { return self.unexpected_last(&self.token); } + }, token::Literal(lit, suf) => { let (suffix_illegal, out) = match lit { token::Byte(i) => (true, LitKind::Byte(parse::byte_lit(&i.as_str()).0)), @@ -1703,14 +1617,7 @@ impl<'a> Parser<'a> { /// bounds are permitted and whether `::` must precede type parameter /// groups. pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { - // Check for a whole path... - let found = match self.token { - token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()), - _ => None, - }; - if let Some(token::Interpolated(token::NtPath(path))) = found { - return Ok(*path); - } + maybe_whole!(self, NtPath, |x| x); let lo = self.span.lo; let is_global = self.eat(&token::ModSep); @@ -2746,7 +2653,7 @@ impl<'a> Parser<'a> { // and token::SubstNt's; it's too early to know yet // whether something will be a nonterminal or a seq // yet. - maybe_whole!(deref self, NtTT); + maybe_whole!(self, NtTT, |x| x); match self.token { token::Eof => { @@ -3327,7 +3234,7 @@ impl<'a> Parser<'a> { } pub fn parse_arm(&mut self) -> PResult<'a, Arm> { - maybe_whole!(no_clone self, NtArm); + maybe_whole!(self, NtArm, |x| x); let attrs = self.parse_outer_attributes()?; let pats = self.parse_pats()?; @@ -3583,7 +3490,7 @@ impl<'a> Parser<'a> { /// Parse a pattern. pub fn parse_pat(&mut self) -> PResult<'a, P> { - maybe_whole!(self, NtPat); + maybe_whole!(self, NtPat, |x| x); let lo = self.span.lo; let pat; @@ -3888,7 +3795,7 @@ impl<'a> Parser<'a> { fn parse_stmt_without_recovery(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option> { - maybe_whole!(Some deref self, NtStmt); + maybe_whole!(self, NtStmt, |x| Some(x)); let attrs = self.parse_outer_attributes()?; let lo = self.span.lo; @@ -4077,7 +3984,7 @@ impl<'a> Parser<'a> { /// Parse a block. No inner attrs are allowed. pub fn parse_block(&mut self) -> PResult<'a, P> { - maybe_whole!(no_clone self, NtBlock); + maybe_whole!(self, NtBlock, |x| x); let lo = self.span.lo; @@ -4115,7 +4022,7 @@ impl<'a> Parser<'a> { /// Parse a block. Inner attrs are allowed. fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec, P)> { - maybe_whole!(pair_empty self, NtBlock); + maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.span.lo; self.expect(&token::OpenDelim(token::Brace))?; @@ -4290,7 +4197,7 @@ impl<'a> Parser<'a> { /// | ( < lifetimes , typaramseq ( , )? > ) /// where typaramseq = ( typaram ) | ( typaram , typaramseq ) pub fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { - maybe_whole!(self, NtGenerics); + maybe_whole!(self, NtGenerics, |x| x); let span_lo = self.span.lo; if self.eat(&token::Lt) { @@ -4431,7 +4338,7 @@ impl<'a> Parser<'a> { /// where T : Trait + 'b, 'a : 'b /// ``` pub fn parse_where_clause(&mut self) -> PResult<'a, ast::WhereClause> { - maybe_whole!(self, NtWhereClause); + maybe_whole!(self, NtWhereClause, |x| x); let mut where_clause = WhereClause { id: ast::DUMMY_NODE_ID, @@ -4839,7 +4746,7 @@ impl<'a> Parser<'a> { /// Parse an impl item. pub fn parse_impl_item(&mut self) -> PResult<'a, ImplItem> { - maybe_whole!(no_clone_from_p self, NtImplItem); + maybe_whole!(self, NtImplItem, |x| x); let mut attrs = self.parse_outer_attributes()?; let lo = self.span.lo; @@ -5707,19 +5614,13 @@ impl<'a> Parser<'a> { /// extern crate. fn parse_item_(&mut self, attrs: Vec, macros_allowed: bool, attributes_allowed: bool) -> PResult<'a, Option>> { - let nt_item = match self.token { - token::Interpolated(token::NtItem(ref item)) => { - Some((**item).clone()) - } - _ => None - }; - if let Some(mut item) = nt_item { - self.bump(); + maybe_whole!(self, NtItem, |item| { + let mut item = item.unwrap(); let mut attrs = attrs; mem::swap(&mut item.attrs, &mut attrs); item.attrs.extend(attrs); - return Ok(Some(P(item))); - } + Some(P(item)) + }); let lo = self.span.lo; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 4d0da660302ae..0198ee073d239 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -123,7 +123,7 @@ pub enum Token { Lifetime(ast::Ident), /* For interpolation */ - Interpolated(Nonterminal), + Interpolated(Rc), // Can be expanded into several tokens. /// Doc comment DocComment(ast::Name), @@ -172,12 +172,15 @@ impl Token { DotDot | DotDotDot => true, // range notation Lt | BinOp(Shl) => true, // associated path ModSep => true, - Interpolated(NtExpr(..)) => true, - Interpolated(NtIdent(..)) => true, - Interpolated(NtBlock(..)) => true, - Interpolated(NtPath(..)) => true, Pound => true, // for expression attributes - _ => false, + Interpolated(ref nt) => match **nt { + NtExpr(..) => true, + NtIdent(..) => true, + NtBlock(..) => true, + NtPath(..) => true, + _ => false, + }, + _ => false, } } @@ -215,10 +218,12 @@ impl Token { /// Returns `true` if the token is an interpolated path. pub fn is_path(&self) -> bool { - match *self { - Interpolated(NtPath(..)) => true, - _ => false, + if let Interpolated(ref nt) = *self { + if let NtPath(..) = **nt { + return true; + } } + false } /// Returns `true` if the token is a lifetime. @@ -290,19 +295,19 @@ impl Token { pub enum Nonterminal { NtItem(P), NtBlock(P), - NtStmt(P), + NtStmt(ast::Stmt), NtPat(P), NtExpr(P), NtTy(P), - NtIdent(Box), + NtIdent(ast::SpannedIdent), /// Stuff inside brackets for attributes NtMeta(P), - NtPath(Box), - NtTT(P), // needs P'ed to break a circularity + NtPath(ast::Path), + NtTT(tokenstream::TokenTree), // These are not exposed to macros, but are used by quasiquote. NtArm(ast::Arm), - NtImplItem(P), - NtTraitItem(P), + NtImplItem(ast::ImplItem), + NtTraitItem(ast::TraitItem), NtGenerics(ast::Generics), NtWhereClause(ast::WhereClause), NtArg(ast::Arg), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b0bd644674300..7352792a8a252 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -285,7 +285,7 @@ pub fn token_to_string(tok: &Token) -> String { token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s), - token::Interpolated(ref nt) => match *nt { + token::Interpolated(ref nt) => match **nt { token::NtExpr(ref e) => expr_to_string(&e), token::NtMeta(ref e) => meta_item_to_string(&e), token::NtTy(ref e) => ty_to_string(&e), diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 9e644e59e86a7..a0dd7b4c5212c 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -134,8 +134,10 @@ impl TokenTree { AttrStyle::Inner => 3, } } + TokenTree::Token(_, token::Interpolated(ref nt)) => { + if let Nonterminal::NtTT(..) = **nt { 1 } else { 0 } + }, TokenTree::Token(_, token::MatchNt(..)) => 3, - TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(..))) => 1, TokenTree::Delimited(_, ref delimed) => delimed.tts.len() + 2, TokenTree::Sequence(_, ref seq) => seq.tts.len(), TokenTree::Token(..) => 0, @@ -193,8 +195,12 @@ impl TokenTree { TokenTree::Token(sp, token::Ident(kind))]; v[index].clone() } - (&TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(ref tt))), _) => { - tt.clone().unwrap() + (&TokenTree::Token(_, token::Interpolated(ref nt)), _) => { + if let Nonterminal::NtTT(ref tt) = **nt { + tt.clone() + } else { + panic!("Cannot expand a token tree"); + } } (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(), _ => panic!("Cannot expand a token tree"), From 3b71646a600b44868ed6cd7e69d66617a24e41e2 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Wed, 2 Nov 2016 22:59:08 +0000 Subject: [PATCH 21/41] Revert "macros: Improve `tt` fragments" This reverts commit 41745f30f751364bdce14428b7d3ffa5dd028903. --- src/libsyntax/ext/tt/transcribe.rs | 16 +++------------- src/libsyntax/tokenstream.rs | 7 ------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 641d69900f730..9ca3b16b74ecc 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -13,7 +13,7 @@ use ast::Ident; use errors::{Handler, DiagnosticBuilder}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; use parse::token::{DocComment, MatchNt, SubstNt}; -use parse::token::{Token, Interpolated, NtIdent, NtTT}; +use parse::token::{Token, NtIdent}; use parse::token; use parse::lexer::TokenAndSpan; use syntax_pos::{Span, DUMMY_SP}; @@ -269,9 +269,9 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } // FIXME #2887: think about span stuff here TokenTree::Token(sp, SubstNt(ident)) => { + r.stack.last_mut().unwrap().idx += 1; match lookup_cur_matched(r, ident) { None => { - r.stack.last_mut().unwrap().idx += 1; r.cur_span = sp; r.cur_tok = SubstNt(ident); return ret_val; @@ -283,24 +283,14 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { // (a) idents can be in lots of places, so it'd be a pain // (b) we actually can, since it's a token. NtIdent(ref sn) => { - r.stack.last_mut().unwrap().idx += 1; r.cur_span = sn.span; r.cur_tok = token::Ident(sn.node); return ret_val; } - NtTT(_) => { - r.stack.push(TtFrame { - forest: TokenTree::Token(sp, Interpolated(nt.clone())), - idx: 0, - dotdotdoted: false, - sep: None, - }); - } _ => { - r.stack.last_mut().unwrap().idx += 1; // FIXME(pcwalton): Bad copy. r.cur_span = sp; - r.cur_tok = Interpolated(nt.clone()); + r.cur_tok = token::Interpolated(nt.clone()); return ret_val; } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index a0dd7b4c5212c..204c885e36130 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -195,13 +195,6 @@ impl TokenTree { TokenTree::Token(sp, token::Ident(kind))]; v[index].clone() } - (&TokenTree::Token(_, token::Interpolated(ref nt)), _) => { - if let Nonterminal::NtTT(ref tt) = **nt { - tt.clone() - } else { - panic!("Cannot expand a token tree"); - } - } (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(), _ => panic!("Cannot expand a token tree"), } From 6e9bf12c6f22661f48e160a8bc23be0e72eff538 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 3 Nov 2016 07:43:29 +0000 Subject: [PATCH 22/41] Reimplement "macros: Improve `tt` fragments" with better performance. --- src/libsyntax/parse/parser.rs | 79 +++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f77525ff549d9..93ab09c89ab96 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -210,6 +210,7 @@ pub struct Parser<'a> { /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option, pub expected_tokens: Vec, + pub tts: Vec<(TokenTree, usize)>, } #[derive(PartialEq, Eq, Clone)] @@ -273,21 +274,13 @@ impl From> for LhsExpr { } impl<'a> Parser<'a> { - pub fn new(sess: &'a ParseSess, mut rdr: Box) -> Self { - let tok0 = rdr.real_token(); - let span = tok0.sp; - let mut directory = match span { - syntax_pos::DUMMY_SP => PathBuf::new(), - _ => PathBuf::from(sess.codemap().span_to_filename(span)), - }; - directory.pop(); - - Parser { + pub fn new(sess: &'a ParseSess, rdr: Box) -> Self { + let mut parser = Parser { reader: rdr, sess: sess, - token: tok0.tok, - span: span, - prev_span: span, + token: token::Underscore, + span: syntax_pos::DUMMY_SP, + prev_span: syntax_pos::DUMMY_SP, prev_token_kind: PrevTokenKind::Other, lookahead_buffer: Default::default(), tokens_consumed: 0, @@ -295,11 +288,57 @@ impl<'a> Parser<'a> { quote_depth: 0, parsing_token_tree: false, obsolete_set: HashSet::new(), - directory: directory, + directory: PathBuf::new(), open_braces: Vec::new(), owns_directory: true, root_module_name: None, expected_tokens: Vec::new(), + tts: Vec::new(), + }; + + let tok = parser.next_tok(); + parser.token = tok.tok; + parser.span = tok.sp; + if parser.span != syntax_pos::DUMMY_SP { + parser.directory = PathBuf::from(sess.codemap().span_to_filename(parser.span)); + parser.directory.pop(); + } + parser + } + + fn next_tok(&mut self) -> TokenAndSpan { + 'outer: loop { + let mut tok = if let Some((tts, i)) = self.tts.pop() { + let tt = tts.get_tt(i); + if i + 1 < tts.len() { + self.tts.push((tts, i + 1)); + } + if let TokenTree::Token(sp, tok) = tt { + TokenAndSpan { tok: tok, sp: sp } + } else { + self.tts.push((tt, 0)); + continue + } + } else { + self.reader.real_token() + }; + + loop { + let nt = match tok.tok { + token::Interpolated(ref nt) => nt.clone(), + _ => return tok, + }; + match *nt { + token::NtTT(TokenTree::Token(sp, ref t)) => { + tok = TokenAndSpan { tok: t.clone(), sp: sp }; + } + token::NtTT(ref tt) => { + self.tts.push((tt.clone(), 0)); + continue 'outer + } + _ => return tok, + } + } } } @@ -848,7 +887,7 @@ impl<'a> Parser<'a> { }; let next = if self.lookahead_buffer.start == self.lookahead_buffer.end { - self.reader.real_token() + self.next_tok() } else { // Avoid token copies with `replace`. let old_start = self.lookahead_buffer.start; @@ -893,7 +932,7 @@ impl<'a> Parser<'a> { f(&self.token) } else if dist < LOOKAHEAD_BUFFER_CAPACITY { while self.lookahead_buffer.len() < dist { - self.lookahead_buffer.buffer[self.lookahead_buffer.end] = self.reader.real_token(); + self.lookahead_buffer.buffer[self.lookahead_buffer.end] = self.next_tok(); self.lookahead_buffer.end = (self.lookahead_buffer.end + 1) % LOOKAHEAD_BUFFER_CAPACITY; } @@ -2653,8 +2692,6 @@ impl<'a> Parser<'a> { // and token::SubstNt's; it's too early to know yet // whether something will be a nonterminal or a seq // yet. - maybe_whole!(self, NtTT, |x| x); - match self.token { token::Eof => { let mut err: DiagnosticBuilder<'a> = @@ -2667,6 +2704,12 @@ impl<'a> Parser<'a> { Err(err) }, token::OpenDelim(delim) => { + if self.tts.last().map(|&(_, i)| i == 1).unwrap_or(false) { + let tt = self.tts.pop().unwrap().0; + self.bump(); + return Ok(tt); + } + let parsing_token_tree = ::std::mem::replace(&mut self.parsing_token_tree, true); // The span for beginning of the delimited section let pre_span = self.span; From b60bcba9e4229cb6efbb31538aa0fd74a98c32f0 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 3 Nov 2016 08:38:17 +0000 Subject: [PATCH 23/41] Make `ast::ExprKind` smaller. --- src/librustc/hir/lowering.rs | 54 ++++++++++++++++-------------------- src/libsyntax/ast.rs | 2 +- src/libsyntax/fold.rs | 46 +++++++++++------------------- src/libsyntax_ext/asm.rs | 4 +-- 4 files changed, 43 insertions(+), 63 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 620ee30c95628..105a9e099b1a4 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1208,36 +1208,30 @@ impl<'a> LoweringContext<'a> { ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)), ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)), ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))), - ExprKind::InlineAsm(InlineAsm { - ref inputs, - ref outputs, - ref asm, - asm_str_style, - ref clobbers, - volatile, - alignstack, - dialect, - expn_id, - }) => hir::ExprInlineAsm(P(hir::InlineAsm { - inputs: inputs.iter().map(|&(ref c, _)| c.clone()).collect(), - outputs: outputs.iter() - .map(|out| { - hir::InlineAsmOutput { - constraint: out.constraint.clone(), - is_rw: out.is_rw, - is_indirect: out.is_indirect, - } - }) - .collect(), - asm: asm.clone(), - asm_str_style: asm_str_style, - clobbers: clobbers.clone().into(), - volatile: volatile, - alignstack: alignstack, - dialect: dialect, - expn_id: expn_id, - }), outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(), - inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect()), + ExprKind::InlineAsm(ref asm) => { + let hir_asm = hir::InlineAsm { + inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(), + outputs: asm.outputs.iter().map(|out| { + hir::InlineAsmOutput { + constraint: out.constraint.clone(), + is_rw: out.is_rw, + is_indirect: out.is_indirect, + } + }).collect(), + asm: asm.asm.clone(), + asm_str_style: asm.asm_str_style, + clobbers: asm.clobbers.clone().into(), + volatile: asm.volatile, + alignstack: asm.alignstack, + dialect: asm.dialect, + expn_id: asm.expn_id, + }; + let outputs = + asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(); + let inputs = + asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect(); + hir::ExprInlineAsm(P(hir_asm), outputs, inputs) + } ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { hir::ExprStruct(self.lower_path(path), fields.iter().map(|x| self.lower_field(x)).collect(), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f077ead1f8e07..f7581924eb19f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1050,7 +1050,7 @@ pub enum ExprKind { Ret(Option>), /// Output of the `asm!()` macro - InlineAsm(InlineAsm), + InlineAsm(P), /// A macro invocation; pre-expansion Mac(Mac), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 71aa0437609d1..1deeaf422316c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1249,36 +1249,22 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu folder.fold_ident(label.node))) ), ExprKind::Ret(e) => ExprKind::Ret(e.map(|x| folder.fold_expr(x))), - ExprKind::InlineAsm(InlineAsm { - inputs, - outputs, - asm, - asm_str_style, - clobbers, - volatile, - alignstack, - dialect, - expn_id, - }) => ExprKind::InlineAsm(InlineAsm { - inputs: inputs.move_map(|(c, input)| { - (c, folder.fold_expr(input)) - }), - outputs: outputs.move_map(|out| { - InlineAsmOutput { - constraint: out.constraint, - expr: folder.fold_expr(out.expr), - is_rw: out.is_rw, - is_indirect: out.is_indirect, - } - }), - asm: asm, - asm_str_style: asm_str_style, - clobbers: clobbers, - volatile: volatile, - alignstack: alignstack, - dialect: dialect, - expn_id: expn_id, - }), + ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(asm.map(|asm| { + InlineAsm { + inputs: asm.inputs.move_map(|(c, input)| { + (c, folder.fold_expr(input)) + }), + outputs: asm.outputs.move_map(|out| { + InlineAsmOutput { + constraint: out.constraint, + expr: folder.fold_expr(out.expr), + is_rw: out.is_rw, + is_indirect: out.is_indirect, + } + }), + ..asm + } + })), ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)), ExprKind::Struct(path, fields, maybe_expr) => { ExprKind::Struct(folder.fold_path(path), diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 24c515e502808..e4d0cb7404603 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -250,7 +250,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::InlineAsm(ast::InlineAsm { + node: ast::ExprKind::InlineAsm(P(ast::InlineAsm { asm: token::intern_and_get_ident(&asm), asm_str_style: asm_str_style.unwrap(), outputs: outputs, @@ -260,7 +260,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, alignstack: alignstack, dialect: dialect, expn_id: expn_id, - }), + })), span: sp, attrs: ast::ThinVec::new(), })) From e2b3fec778453d06be6a07494eeaa66da57e4f82 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 3 Nov 2016 08:23:59 +0000 Subject: [PATCH 24/41] Avoid recontructing the `Parser` in `macro_parser.rs`. --- src/libsyntax/ext/tt/macro_parser.rs | 37 ++++++++++++---------------- src/libsyntax/parse/lexer/mod.rs | 21 ---------------- 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 6680119d2eaa2..2ea01599006e7 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -278,17 +278,16 @@ pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { } } -pub fn parse(sess: &ParseSess, mut rdr: TtReader, ms: &[TokenTree]) -> NamedParseResult { - let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), - None, - rdr.peek().sp.lo)); +pub fn parse(sess: &ParseSess, rdr: TtReader, ms: &[TokenTree]) -> NamedParseResult { + let mut parser = Parser::new(sess, Box::new(rdr)); + let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), None, parser.span.lo)); loop { let mut bb_eis = Vec::new(); // black-box parsed by parser.rs let mut next_eis = Vec::new(); // or proceed normally let mut eof_eis = Vec::new(); - let TokenAndSpan { tok, sp } = rdr.peek(); + let (sp, tok) = (parser.span, parser.token.clone()); /* we append new items to this while we go */ loop { @@ -473,23 +472,19 @@ pub fn parse(sess: &ParseSess, mut rdr: TtReader, ms: &[TokenTree]) -> NamedPars while !next_eis.is_empty() { cur_eis.push(next_eis.pop().unwrap()); } - rdr.next_token(); + parser.bump(); } else /* bb_eis.len() == 1 */ { - rdr.next_tok = { - let mut rust_parser = Parser::new(sess, Box::new(&mut rdr)); - let mut ei = bb_eis.pop().unwrap(); - if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) { - let match_cur = ei.match_cur; - (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( - Rc::new(parse_nt(&mut rust_parser, span, &ident.name.as_str()))))); - ei.idx += 1; - ei.match_cur += 1; - } else { - unreachable!() - } - cur_eis.push(ei); - Some(TokenAndSpan { tok: rust_parser.token, sp: rust_parser.span }) - }; + let mut ei = bb_eis.pop().unwrap(); + if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) { + let match_cur = ei.match_cur; + (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( + Rc::new(parse_nt(&mut parser, span, &ident.name.as_str()))))); + ei.idx += 1; + ei.match_cur += 1; + } else { + unreachable!() + } + cur_eis.push(ei); } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 5e20f6e419276..3d5dec31d2a37 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -178,27 +178,6 @@ impl<'a> Reader for TtReader<'a> { } } -impl<'a, 'b> Reader for &'b mut TtReader<'a> { - fn is_eof(&self) -> bool { - (**self).is_eof() - } - fn try_next_token(&mut self) -> Result { - (**self).try_next_token() - } - fn fatal(&self, m: &str) -> FatalError { - (**self).fatal(m) - } - fn err(&self, m: &str) { - (**self).err(m) - } - fn emit_fatal_errors(&mut self) { - (**self).emit_fatal_errors() - } - fn peek(&self) -> TokenAndSpan { - (**self).peek() - } -} - impl<'a> StringReader<'a> { /// For comments.rs, which hackily pokes into next_pos and ch pub fn new_raw<'b>(span_diagnostic: &'b Handler, From 7ae083383d1a88f1d76e51297a88c2a423aaa3d1 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 3 Nov 2016 10:44:25 +0000 Subject: [PATCH 25/41] Move doc comment desugaring into the parser. --- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/ext/tt/transcribe.rs | 28 +--------------------------- src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 11 +++++++++++ src/libsyntax/tokenstream.rs | 6 ++---- 5 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 2ea01599006e7..fdec7a4c7321e 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -279,7 +279,7 @@ pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { } pub fn parse(sess: &ParseSess, rdr: TtReader, ms: &[TokenTree]) -> NamedParseResult { - let mut parser = Parser::new(sess, Box::new(rdr)); + let mut parser = Parser::new_with_doc_flag(sess, Box::new(rdr), true); let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), None, parser.span.lo)); loop { diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 9ca3b16b74ecc..96972f4dc884b 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -12,9 +12,7 @@ use self::LockstepIterSize::*; use ast::Ident; use errors::{Handler, DiagnosticBuilder}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; -use parse::token::{DocComment, MatchNt, SubstNt}; -use parse::token::{Token, NtIdent}; -use parse::token; +use parse::token::{self, MatchNt, SubstNt, Token, NtIdent}; use parse::lexer::TokenAndSpan; use syntax_pos::{Span, DUMMY_SP}; use tokenstream::{self, TokenTree}; @@ -48,7 +46,6 @@ pub struct TtReader<'a> { pub cur_span: Span, pub next_tok: Option, /// Transform doc comments. Only useful in macro invocations - pub desugar_doc_comments: bool, pub fatal_errs: Vec>, } @@ -59,20 +56,6 @@ pub fn new_tt_reader(sp_diag: &Handler, interp: Option>>, src: Vec) -> TtReader { - new_tt_reader_with_doc_flag(sp_diag, interp, src, false) -} - -/// The extra `desugar_doc_comments` flag enables reading doc comments -/// like any other attribute which consists of `meta` and surrounding #[ ] tokens. -/// -/// This can do Macro-By-Example transcription. On the other hand, if -/// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can -/// (and should) be None. -pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, - interp: Option>>, - src: Vec, - desugar_doc_comments: bool) - -> TtReader { let mut r = TtReader { sp_diag: sp_diag, stack: SmallVector::one(TtFrame { @@ -91,7 +74,6 @@ pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, }, repeat_idx: Vec::new(), repeat_len: Vec::new(), - desugar_doc_comments: desugar_doc_comments, /* dummy values, never read: */ cur_tok: token::Eof, cur_span: DUMMY_SP, @@ -312,14 +294,6 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { }); // if this could be 0-length, we'd need to potentially recur here } - TokenTree::Token(sp, DocComment(name)) if r.desugar_doc_comments => { - r.stack.push(TtFrame { - forest: TokenTree::Token(sp, DocComment(name)), - idx: 0, - dotdotdoted: false, - sep: None - }); - } TokenTree::Token(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 3d5dec31d2a37..200fb0de2d242 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -22,7 +22,7 @@ use std::char; use std::mem::replace; use std::rc::Rc; -pub use ext::tt::transcribe::{TtReader, new_tt_reader, new_tt_reader_with_doc_flag}; +pub use ext::tt::transcribe::{TtReader, new_tt_reader}; pub mod comments; mod unicode_chars; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 93ab09c89ab96..e5bbeb3c648ef 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -211,6 +211,7 @@ pub struct Parser<'a> { pub root_module_name: Option, pub expected_tokens: Vec, pub tts: Vec<(TokenTree, usize)>, + pub desugar_doc_comments: bool, } #[derive(PartialEq, Eq, Clone)] @@ -275,6 +276,11 @@ impl From> for LhsExpr { impl<'a> Parser<'a> { pub fn new(sess: &'a ParseSess, rdr: Box) -> Self { + Parser::new_with_doc_flag(sess, rdr, false) + } + + pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box, desugar_doc_comments: bool) + -> Self { let mut parser = Parser { reader: rdr, sess: sess, @@ -294,6 +300,7 @@ impl<'a> Parser<'a> { root_module_name: None, expected_tokens: Vec::new(), tts: Vec::new(), + desugar_doc_comments: desugar_doc_comments, }; let tok = parser.next_tok(); @@ -326,6 +333,10 @@ impl<'a> Parser<'a> { loop { let nt = match tok.tok { token::Interpolated(ref nt) => nt.clone(), + token::DocComment(name) if self.desugar_doc_comments => { + self.tts.push((TokenTree::Token(tok.sp, token::DocComment(name)), 0)); + continue 'outer + } _ => return tok, }; match *nt { diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 204c885e36130..9ef6c07e489dc 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -214,11 +214,9 @@ impl TokenTree { mtch: &[TokenTree], tts: &[TokenTree]) -> macro_parser::NamedParseResult { + let diag = &cx.parse_sess().span_diagnostic; // `None` is because we're not interpolating - let arg_rdr = lexer::new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic, - None, - tts.iter().cloned().collect(), - true); + let arg_rdr = lexer::new_tt_reader(diag, None, tts.iter().cloned().collect()); macro_parser::parse(cx.parse_sess(), arg_rdr, mtch) } From 1e40c80cf527c3b18baaf443f0fc553f35424499 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Fri, 4 Nov 2016 01:07:00 +0000 Subject: [PATCH 26/41] Fix issues with the Add/AddAssign impls for Cow * Correct the stability attributes. * Make Add and AddAssign actually behave the same. * Use String::with_capacity when allocating a new string. * Fix the tests. --- src/libcollections/borrow.rs | 61 ++++++++------ src/libcollectionstest/cow_str.rs | 134 +++++++++++++++++++++++------- src/libcollectionstest/lib.rs | 1 + 3 files changed, 143 insertions(+), 53 deletions(-) diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 8f9c357833791..3bc2a3f8f68b7 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -17,6 +17,7 @@ use core::hash::{Hash, Hasher}; use core::ops::{Add, AddAssign, Deref}; use fmt; +use string::String; use self::Cow::*; @@ -284,48 +285,60 @@ impl<'a, T: ?Sized + ToOwned> AsRef for Cow<'a, T> { } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> Add<&'a str> for Cow<'a, str> { type Output = Cow<'a, str>; - fn add(self, rhs: &'a str) -> Self { - if self == "" { - Cow::Borrowed(rhs) - } else if rhs == "" { - self - } else { - Cow::Owned(self.into_owned() + rhs) - } + #[inline] + fn add(mut self, rhs: &'a str) -> Self::Output { + self += rhs; + self } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> Add> for Cow<'a, str> { type Output = Cow<'a, str>; - fn add(self, rhs: Cow<'a, str>) -> Self { - if self == "" { - rhs - } else if rhs == "" { - self - } else { - Cow::Owned(self.into_owned() + rhs.borrow()) - } + #[inline] + fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { + self += rhs; + self } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> AddAssign<&'a str> for Cow<'a, str> { fn add_assign(&mut self, rhs: &'a str) { - if rhs == "" { return; } - self.to_mut().push_str(rhs); + if self.is_empty() { + *self = Cow::Borrowed(rhs) + } else if rhs.is_empty() { + return; + } else { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(rhs); + } } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> AddAssign> for Cow<'a, str> { fn add_assign(&mut self, rhs: Cow<'a, str>) { - if rhs == "" { return; } - self.to_mut().push_str(rhs.borrow()); + if self.is_empty() { + *self = rhs + } else if rhs.is_empty() { + return; + } else { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(&rhs); + } } } diff --git a/src/libcollectionstest/cow_str.rs b/src/libcollectionstest/cow_str.rs index 82533ba077541..b29245121daad 100644 --- a/src/libcollectionstest/cow_str.rs +++ b/src/libcollectionstest/cow_str.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013-2014 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -12,54 +12,130 @@ use std::borrow::Cow; // check that Cow<'a, str> implements addition #[test] -fn check_cow_add() { - borrowed1 = Cow::Borrowed("Hello, "); - borrowed2 = Cow::Borrowed("World!"); - borrow_empty = Cow::Borrowed(""); +fn check_cow_add_cow() { + let borrowed1 = Cow::Borrowed("Hello, "); + let borrowed2 = Cow::Borrowed("World!"); + let borrow_empty = Cow::Borrowed(""); - owned1 = Cow::Owned("Hi, ".into()); - owned2 = Cow::Owned("Rustaceans!".into()); - owned_empty = Cow::Owned("".into()); + let owned1: Cow = Cow::Owned(String::from("Hi, ")); + let owned2: Cow = Cow::Owned(String::from("Rustaceans!")); + let owned_empty: Cow = Cow::Owned(String::new()); - assert_eq!("Hello, World!", borrowed1 + borrowed2); - assert_eq!("Hello, Rustaceans!", borrowed1 + owned2); + assert_eq!("Hello, World!", borrowed1.clone() + borrowed2.clone()); + assert_eq!("Hello, Rustaceans!", borrowed1.clone() + owned2.clone()); - assert_eq!("Hello, World!", owned1 + borrowed2); - assert_eq!("Hello, Rustaceans!", owned1 + owned2); + assert_eq!("Hi, World!", owned1.clone() + borrowed2.clone()); + assert_eq!("Hi, Rustaceans!", owned1.clone() + owned2.clone()); - if let Cow::Owned(_) = borrowed1 + borrow_empty { + if let Cow::Owned(_) = borrowed1.clone() + borrow_empty.clone() { panic!("Adding empty strings to a borrow should note allocate"); } - if let Cow::Owned(_) = borrow_empty + borrowed1 { + if let Cow::Owned(_) = borrow_empty.clone() + borrowed1.clone() { panic!("Adding empty strings to a borrow should note allocate"); } - if let Cow::Owned(_) = borrowed1 + owned_empty { + if let Cow::Owned(_) = borrowed1.clone() + owned_empty.clone() { panic!("Adding empty strings to a borrow should note allocate"); } - if let Cow::Owned(_) = owned_empty + borrowed1 { + if let Cow::Owned(_) = owned_empty.clone() + borrowed1.clone() { panic!("Adding empty strings to a borrow should note allocate"); } } -fn check_cow_add_assign() { - borrowed1 = Cow::Borrowed("Hello, "); - borrowed2 = Cow::Borrowed("World!"); - borrow_empty = Cow::Borrowed(""); +#[test] +fn check_cow_add_str() { + let borrowed = Cow::Borrowed("Hello, "); + let borrow_empty = Cow::Borrowed(""); + + let owned: Cow = Cow::Owned(String::from("Hi, ")); + let owned_empty: Cow = Cow::Owned(String::new()); - owned1 = Cow::Owned("Hi, ".into()); - owned2 = Cow::Owned("Rustaceans!".into()); - owned_empty = Cow::Owned("".into()); + assert_eq!("Hello, World!", borrowed.clone() + "World!"); - let borrowed1clone = borrowed1.clone(); - borrowed1clone += borrow_empty; - assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr()); + assert_eq!("Hi, World!", owned.clone() + "World!"); - borrowed1clone += owned_empty; - assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr()); + if let Cow::Owned(_) = borrowed.clone() + "" { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = borrow_empty.clone() + "Hello, " { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = owned_empty.clone() + "Hello, " { + panic!("Adding empty strings to a borrow should note allocate"); + } +} + +#[test] +fn check_cow_add_assign_cow() { + let mut borrowed1 = Cow::Borrowed("Hello, "); + let borrowed2 = Cow::Borrowed("World!"); + let borrow_empty = Cow::Borrowed(""); + + let mut owned1: Cow = Cow::Owned(String::from("Hi, ")); + let owned2: Cow = Cow::Owned(String::from("Rustaceans!")); + let owned_empty: Cow = Cow::Owned(String::new()); + + let mut s = borrowed1.clone(); + s += borrow_empty.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrow_empty.clone(); + s += borrowed1.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrowed1.clone(); + s += owned_empty.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = owned_empty.clone(); + s += borrowed1.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } owned1 += borrowed2; borrowed1 += owned2; - assert_eq!("Hello, World!", owned1); + assert_eq!("Hi, World!", owned1); assert_eq!("Hello, Rustaceans!", borrowed1); } + +#[test] +fn check_cow_add_assign_str() { + let mut borrowed = Cow::Borrowed("Hello, "); + let borrow_empty = Cow::Borrowed(""); + + let mut owned: Cow = Cow::Owned(String::from("Hi, ")); + let owned_empty: Cow = Cow::Owned(String::new()); + + let mut s = borrowed.clone(); + s += ""; + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrow_empty.clone(); + s += "World!"; + assert_eq!("World!", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = owned_empty.clone(); + s += "World!"; + assert_eq!("World!", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + + owned += "World!"; + borrowed += "World!"; + + assert_eq!("Hi, World!", owned); + assert_eq!("Hello, World!", borrowed); +} diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 5d3e03c2dee36..14ec8d58bef61 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -42,6 +42,7 @@ mod bench; mod binary_heap; mod btree; +mod cow_str; mod enum_set; mod fmt; mod linked_list; From 23ad6fdb66a2159b173e3e781c51d648fa663882 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 3 Nov 2016 11:59:43 +0000 Subject: [PATCH 27/41] Improve `tt`-heavy expansion performance. --- src/libsyntax/ext/base.rs | 4 +++- src/libsyntax/ext/tt/macro_parser.rs | 15 ++++++++++++--- src/libsyntax/parse/parser.rs | 9 ++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cc097ab0efadc..1f47a91fcc13e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -615,7 +615,9 @@ impl<'a> ExtCtxt<'a> { pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> { - parse::tts_to_parser(self.parse_sess, tts.to_vec()) + let mut parser = parse::tts_to_parser(self.parse_sess, tts.to_vec()); + parser.allow_interpolated_tts = false; // FIXME(jseyfried) `quote!` can't handle these yet + parser } pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() } pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index fdec7a4c7321e..1066646aa8e8a 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -496,10 +496,19 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { match name { "tt" => { p.quote_depth += 1; //but in theory, non-quoted tts might be useful - let res: ::parse::PResult<'a, _> = p.parse_token_tree(); - let res = token::NtTT(panictry!(res)); + let mut tt = panictry!(p.parse_token_tree()); p.quote_depth -= 1; - return res; + loop { + let nt = match tt { + TokenTree::Token(_, token::Interpolated(ref nt)) => nt.clone(), + _ => break, + }; + match *nt { + token::NtTT(ref sub_tt) => tt = sub_tt.clone(), + _ => break, + } + } + return token::NtTT(tt); } _ => {} } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e5bbeb3c648ef..b670a7384739b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -212,6 +212,7 @@ pub struct Parser<'a> { pub expected_tokens: Vec, pub tts: Vec<(TokenTree, usize)>, pub desugar_doc_comments: bool, + pub allow_interpolated_tts: bool, } #[derive(PartialEq, Eq, Clone)] @@ -301,6 +302,7 @@ impl<'a> Parser<'a> { expected_tokens: Vec::new(), tts: Vec::new(), desugar_doc_comments: desugar_doc_comments, + allow_interpolated_tts: true, }; let tok = parser.next_tok(); @@ -2718,7 +2720,12 @@ impl<'a> Parser<'a> { if self.tts.last().map(|&(_, i)| i == 1).unwrap_or(false) { let tt = self.tts.pop().unwrap().0; self.bump(); - return Ok(tt); + return Ok(if self.allow_interpolated_tts { + // avoid needlessly reparsing token trees in recursive macro expansions + TokenTree::Token(tt.span(), token::Interpolated(Rc::new(token::NtTT(tt)))) + } else { + tt + }); } let parsing_token_tree = ::std::mem::replace(&mut self.parsing_token_tree, true); From b7eed53b55d43c8d63ede9e8e45c532e9cc83cc2 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 3 Nov 2016 21:58:28 +0000 Subject: [PATCH 28/41] Remove field `TtReader::next_tok`. --- src/libsyntax/ext/tt/transcribe.rs | 5 ----- src/libsyntax/parse/lexer/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 96972f4dc884b..37e329e5d3b29 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -44,7 +44,6 @@ pub struct TtReader<'a> { /* cached: */ pub cur_tok: Token, pub cur_span: Span, - pub next_tok: Option, /// Transform doc comments. Only useful in macro invocations pub fatal_errs: Vec>, } @@ -77,7 +76,6 @@ pub fn new_tt_reader(sp_diag: &Handler, /* dummy values, never read: */ cur_tok: token::Eof, cur_span: DUMMY_SP, - next_tok: None, fatal_errs: Vec::new(), }; tt_next_token(&mut r); /* get cur_tok and cur_span set up */ @@ -156,9 +154,6 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize { /// Return the next token from the TtReader. /// EFFECT: advances the reader's token field pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { - if let Some(tok) = r.next_tok.take() { - return tok; - } // FIXME(pcwalton): Bad copy? let ret_val = TokenAndSpan { tok: r.cur_tok.clone(), diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 200fb0de2d242..cf48c445c80eb 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -171,10 +171,10 @@ impl<'a> Reader for TtReader<'a> { self.fatal_errs.clear(); } fn peek(&self) -> TokenAndSpan { - self.next_tok.clone().unwrap_or(TokenAndSpan { + TokenAndSpan { tok: self.cur_tok.clone(), sp: self.cur_span, - }) + } } } From 9366ba31668af3575ecadb3b35d2b67e138c3605 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2016 14:58:32 +1100 Subject: [PATCH 29/41] Reorder `hir::Expr` fields. On 64-bit platforms this reduces the size of `Expr` from 96 bytes to 88 bytes. --- src/librustc/hir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index c451a789193aa..5ff69a789ed59 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -840,8 +840,8 @@ pub enum UnsafeSource { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Expr { pub id: NodeId, - pub node: Expr_, pub span: Span, + pub node: Expr_, pub attrs: ThinVec, } From 43452a36efae22492ffef157ce44f05346bde1b0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Nov 2016 15:04:16 +1100 Subject: [PATCH 30/41] Shrink `Expr_::ExprStruct`. On 64-bit platforms this reduces the size of `Expr_` from 64 bytes to 56 bytes, and reduces the size of `Expr` from 88 bytes to 80 bytes. --- src/librustc/hir/lowering.rs | 4 ++-- src/librustc/hir/mod.rs | 2 +- src/librustc_const_eval/eval.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 620ee30c95628..7567c405bcaec 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1239,7 +1239,7 @@ impl<'a> LoweringContext<'a> { }), outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(), inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect()), ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - hir::ExprStruct(self.lower_path(path), + hir::ExprStruct(P(self.lower_path(path)), fields.iter().map(|x| self.lower_field(x)).collect(), maybe_expr.as_ref().map(|x| self.lower_expr(x))) } @@ -1743,7 +1743,7 @@ impl<'a> LoweringContext<'a> { e: Option>, attrs: ThinVec) -> P { let def = self.resolver.resolve_generated_global_path(&path, false); - let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs); + let expr = self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs); self.resolver.record_resolution(expr.id, def); expr } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 5ff69a789ed59..5f57ceac353cc 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -946,7 +946,7 @@ pub enum Expr_ { /// /// For example, `Foo {x: 1, y: 2}`, or /// `Foo {x: 1, .. base}`, where `base` is the `Option`. - ExprStruct(Path, HirVec, Option>), + ExprStruct(P, HirVec, Option>), /// An array literal constructed from one repeated element. /// diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c02cca0da7225..ad9e718617a52 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -314,7 +314,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }, })) .collect::>()?; - PatKind::Struct(path.clone(), field_pats, false) + PatKind::Struct((**path).clone(), field_pats, false) } hir::ExprArray(ref exprs) => { From 51104e5ca60177b9f646f0c906eac358050664b7 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 4 Nov 2016 09:07:00 +0000 Subject: [PATCH 31/41] Fix fallout in tests. --- .../auxiliary/procedural_mbe_matching.rs | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index 5229d42f1fdd4..6ac0d5ad1a3bc 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -18,10 +18,10 @@ extern crate syntax_pos; extern crate rustc; extern crate rustc_plugin; -use syntax::parse::token::{self, str_to_ident, NtExpr, NtPat}; +use syntax::parse::token::{str_to_ident, NtExpr, NtPat}; use syntax::ast::{Pat}; use syntax::tokenstream::{TokenTree}; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; +use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; use syntax::ext::build::AstBuilder; use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use syntax::ext::tt::macro_parser::{Success, Failure, Error}; @@ -30,35 +30,12 @@ use syntax::ptr::P; use syntax_pos::Span; use rustc_plugin::Registry; -fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) +fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) -> Box { let mbe_matcher = quote_matcher!(cx, $matched:expr, $($pat:pat)|+); - - let mac_expr = match TokenTree::parse(cx, &mbe_matcher[..], args) { - Success(map) => { - match (&*map[&str_to_ident("matched")], &*map[&str_to_ident("pat")]) { - (&MatchedNonterminal(NtExpr(ref matched_expr)), - &MatchedSeq(ref pats, seq_sp)) => { - let pats: Vec> = pats.iter().map(|pat_nt| - if let &MatchedNonterminal(NtPat(ref pat)) = &**pat_nt { - pat.clone() - } else { - unreachable!() - } - ).collect(); - let arm = cx.arm(seq_sp, pats, cx.expr_bool(seq_sp, true)); - - quote_expr!(cx, - match $matched_expr { - $arm - _ => false - } - ) - } - _ => unreachable!() - } - } + let map = match TokenTree::parse(cx, &mbe_matcher, args) { + Success(map) => map, Failure(_, tok) => { panic!("expected Success, but got Failure: {}", parse_failure_msg(tok)); } @@ -67,6 +44,34 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } }; + let matched_nt = match *map[&str_to_ident("matched")] { + MatchedNonterminal(ref nt) => nt.clone(), + _ => unreachable!(), + }; + + let mac_expr = match (&*matched_nt, &*map[&str_to_ident("pat")]) { + (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => { + let pats: Vec> = pats.iter().map(|pat_nt| { + match **pat_nt { + MatchedNonterminal(ref nt) => match **nt { + NtPat(ref pat) => pat.clone(), + _ => unreachable!(), + }, + _ => unreachable!(), + } + }).collect(); + let arm = cx.arm(seq_sp, pats, cx.expr_bool(seq_sp, true)); + + quote_expr!(cx, + match $matched_expr { + $arm + _ => false + } + ) + } + _ => unreachable!() + }; + MacEager::expr(mac_expr) } From a5f6aa1c14a4af1637170565dd0646cc7642a7c0 Mon Sep 17 00:00:00 2001 From: Liigo Zhuang Date: Fri, 4 Nov 2016 15:43:42 +0800 Subject: [PATCH 32/41] reference full path `DefaultHasher` --- src/libcore/hash/sip.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 6b3ab64dfd88c..5f5d07b668237 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -24,7 +24,8 @@ use mem; /// /// See: https://131002.net/siphash/ #[unstable(feature = "sip_hash_13", issue = "34767")] -#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] +#[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher13 { hasher: Hasher, @@ -34,7 +35,8 @@ pub struct SipHasher13 { /// /// See: https://131002.net/siphash/ #[unstable(feature = "sip_hash_13", issue = "34767")] -#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] +#[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher24 { hasher: Hasher, @@ -53,7 +55,8 @@ pub struct SipHasher24 { /// it is not intended for cryptographic purposes. As such, all /// cryptographic uses of this implementation are _strongly discouraged_. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] +#[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher(SipHasher24); @@ -140,7 +143,8 @@ impl SipHasher { /// Creates a new `SipHasher` with the two initial keys set to 0. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -148,7 +152,8 @@ impl SipHasher { /// Creates a `SipHasher` that is keyed off the provided keys. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24::new_with_keys(key0, key1)) } @@ -158,7 +163,8 @@ impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -166,7 +172,8 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) @@ -178,7 +185,8 @@ impl SipHasher24 { /// Creates a new `SipHasher24` with the two initial keys set to 0. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new() -> SipHasher24 { SipHasher24::new_with_keys(0, 0) } @@ -186,7 +194,8 @@ impl SipHasher24 { /// Creates a `SipHasher24` that is keyed off the provided keys. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 { SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) From 94e655eca6909fdca6f346e04abdcec8b8cc6e25 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 4 Nov 2016 11:37:39 -0400 Subject: [PATCH 33/41] Add -Zhir-stats for collecting statistics on HIR and AST --- src/librustc/session/config.rs | 2 + src/librustc/util/common.rs | 34 +++ src/librustc_driver/driver.rs | 19 +- src/librustc_passes/hir_stats.rs | 374 +++++++++++++++++++++++++++++++ src/librustc_passes/lib.rs | 1 + 5 files changed, 428 insertions(+), 2 deletions(-) create mode 100644 src/librustc_passes/hir_stats.rs diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 87a5c6410a841..63eabd5212fd0 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -918,6 +918,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "the directory the MIR is dumped into"), perf_stats: bool = (false, parse_bool, [UNTRACKED], "print some performance-related statistics"), + hir_stats: bool = (false, parse_bool, [UNTRACKED], + "print some statistics about AST and HIR"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 78f20b77f3185..7cd5fd78df528 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -75,6 +75,26 @@ pub fn duration_to_secs_str(dur: Duration) -> String { format!("{:.3}", secs) } +pub fn to_readable_str(mut val: usize) -> String { + let mut groups = vec![]; + loop { + let group = val % 1000; + + val /= 1000; + + if val == 0 { + groups.push(format!("{}", group)); + break + } else { + groups.push(format!("{:03}", group)); + } + } + + groups.reverse(); + + groups.join("_") +} + pub fn record_time(accu: &Cell, f: F) -> T where F: FnOnce() -> T, { @@ -264,3 +284,17 @@ pub fn path2cstr(p: &Path) -> CString { pub fn path2cstr(p: &Path) -> CString { CString::new(p.to_str().unwrap()).unwrap() } + + +#[test] +fn test_to_readable_str() { + assert_eq!("0", to_readable_str(0)); + assert_eq!("1", to_readable_str(1)); + assert_eq!("99", to_readable_str(99)); + assert_eq!("999", to_readable_str(999)); + assert_eq!("1_000", to_readable_str(1_000)); + assert_eq!("1_001", to_readable_str(1_001)); + assert_eq!("999_999", to_readable_str(999_999)); + assert_eq!("1_000_000", to_readable_str(1_000_000)); + assert_eq!("1_234_567", to_readable_str(1_234_567)); +} diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index da1d5ad2c4a9b..77d2eb0cbce3a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -37,7 +37,8 @@ use rustc_typeck as typeck; use rustc_privacy; use rustc_plugin::registry::Registry; use rustc_plugin as plugin; -use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues, static_recursion}; +use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues, + static_recursion, hir_stats}; use rustc_const_eval::check_match; use super::Compilation; @@ -513,6 +514,10 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session, input: &Input) -> PResult<'a, syntax::show_span::run(sess.diagnostic(), s, &krate); } + if sess.opts.debugging_opts.hir_stats { + hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS"); + } + Ok(krate) } @@ -718,6 +723,10 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, println!("Post-expansion node count: {}", count_nodes(&krate)); } + if sess.opts.debugging_opts.hir_stats { + hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS"); + } + if sess.opts.debugging_opts.ast_json { println!("{}", json::as_json(&krate)); } @@ -758,7 +767,13 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, // Lower ast -> hir. let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - hir_map::Forest::new(lower_crate(sess, &krate, &mut resolver), &sess.dep_graph) + let hir_crate = lower_crate(sess, &krate, &mut resolver); + + if sess.opts.debugging_opts.hir_stats { + hir_stats::print_hir_stats(&hir_crate); + } + + hir_map::Forest::new(hir_crate, &sess.dep_graph) }); // Discard hygiene data, which isn't required past lowering to HIR. diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs new file mode 100644 index 0000000000000..18586715894f5 --- /dev/null +++ b/src/librustc_passes/hir_stats.rs @@ -0,0 +1,374 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The visitors in this module collect sizes and counts of the most important +// pieces of AST and HIR. The resulting numbers are good approximations but not +// completely accurate (some things might be counted twice, others missed). + +use rustc::hir; +use rustc::hir::intravisit as hir_visit; +use rustc::util::common::to_readable_str; +use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; +use syntax::ast::{self, NodeId, AttrId}; +use syntax::visit as ast_visit; +use syntax_pos::Span; + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +enum Id { + Node(NodeId), + Attr(AttrId), + None, +} + +struct NodeData { + count: usize, + size: usize, +} + +struct StatCollector<'k> { + krate: Option<&'k hir::Crate>, + data: FnvHashMap<&'static str, NodeData>, + seen: FnvHashSet, +} + +pub fn print_hir_stats(krate: &hir::Crate) { + let mut collector = StatCollector { + krate: Some(krate), + data: FnvHashMap(), + seen: FnvHashSet(), + }; + hir_visit::walk_crate(&mut collector, krate); + collector.print("HIR STATS"); +} + +pub fn print_ast_stats(krate: &ast::Crate, title: &str) { + let mut collector = StatCollector { + krate: None, + data: FnvHashMap(), + seen: FnvHashSet(), + }; + ast_visit::walk_crate(&mut collector, krate); + collector.print(title); +} + +impl<'k> StatCollector<'k> { + + fn record(&mut self, label: &'static str, id: Id, node: &T) { + if id != Id::None { + if !self.seen.insert(id) { + return + } + } + + let entry = self.data.entry(label).or_insert(NodeData { + count: 0, + size: 0, + }); + + entry.count += 1; + entry.size = ::std::mem::size_of_val(node); + } + + fn print(&self, title: &str) { + let mut stats: Vec<_> = self.data.iter().collect(); + + stats.sort_by_key(|&(_, ref d)| d.count * d.size); + + let mut total_size = 0; + + println!("\n{}\n", title); + + println!("{:<18}{:>18}{:>14}{:>14}", + "Name", "Accumulated Size", "Count", "Item Size"); + println!("----------------------------------------------------------------"); + + for (label, data) in stats { + println!("{:<18}{:>18}{:>14}{:>14}", + label, + to_readable_str(data.count * data.size), + to_readable_str(data.count), + to_readable_str(data.size)); + + total_size += data.count * data.size; + } + println!("----------------------------------------------------------------"); + println!("{:<18}{:>18}\n", + "Total", + to_readable_str(total_size)); + } +} + +impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { + + fn visit_nested_item(&mut self, id: hir::ItemId) { + let nested_item = self.krate.unwrap().item(id.id); + self.visit_item(nested_item) + } + + fn visit_item(&mut self, i: &'v hir::Item) { + self.record("Item", Id::Node(i.id), i); + hir_visit::walk_item(self, i) + } + + /////////////////////////////////////////////////////////////////////////// + + fn visit_mod(&mut self, m: &'v hir::Mod, _s: Span, n: NodeId) { + self.record("Mod", Id::None, m); + hir_visit::walk_mod(self, m, n) + } + fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem) { + self.record("ForeignItem", Id::Node(i.id), i); + hir_visit::walk_foreign_item(self, i) + } + fn visit_local(&mut self, l: &'v hir::Local) { + self.record("Local", Id::Node(l.id), l); + hir_visit::walk_local(self, l) + } + fn visit_block(&mut self, b: &'v hir::Block) { + self.record("Block", Id::Node(b.id), b); + hir_visit::walk_block(self, b) + } + fn visit_stmt(&mut self, s: &'v hir::Stmt) { + self.record("Stmt", Id::Node(s.node.id()), s); + hir_visit::walk_stmt(self, s) + } + fn visit_arm(&mut self, a: &'v hir::Arm) { + self.record("Arm", Id::None, a); + hir_visit::walk_arm(self, a) + } + fn visit_pat(&mut self, p: &'v hir::Pat) { + self.record("Pat", Id::Node(p.id), p); + hir_visit::walk_pat(self, p) + } + fn visit_decl(&mut self, d: &'v hir::Decl) { + self.record("Decl", Id::None, d); + hir_visit::walk_decl(self, d) + } + fn visit_expr(&mut self, ex: &'v hir::Expr) { + self.record("Expr", Id::Node(ex.id), ex); + hir_visit::walk_expr(self, ex) + } + + fn visit_ty(&mut self, t: &'v hir::Ty) { + self.record("Ty", Id::Node(t.id), t); + hir_visit::walk_ty(self, t) + } + + fn visit_fn(&mut self, + fk: hir_visit::FnKind<'v>, + fd: &'v hir::FnDecl, + b: &'v hir::Block, + s: Span, + id: NodeId) { + self.record("FnDecl", Id::None, fd); + hir_visit::walk_fn(self, fk, fd, b, s, id) + } + + fn visit_where_predicate(&mut self, predicate: &'v hir::WherePredicate) { + self.record("WherePredicate", Id::None, predicate); + hir_visit::walk_where_predicate(self, predicate) + } + + fn visit_trait_item(&mut self, ti: &'v hir::TraitItem) { + self.record("TraitItem", Id::Node(ti.id), ti); + hir_visit::walk_trait_item(self, ti) + } + fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) { + self.record("ImplItem", Id::Node(ii.id), ii); + hir_visit::walk_impl_item(self, ii) + } + + fn visit_ty_param_bound(&mut self, bounds: &'v hir::TyParamBound) { + self.record("TyParamBound", Id::None, bounds); + hir_visit::walk_ty_param_bound(self, bounds) + } + + fn visit_struct_field(&mut self, s: &'v hir::StructField) { + self.record("StructField", Id::Node(s.id), s); + hir_visit::walk_struct_field(self, s) + } + + fn visit_variant(&mut self, + v: &'v hir::Variant, + g: &'v hir::Generics, + item_id: NodeId) { + self.record("Variant", Id::None, v); + hir_visit::walk_variant(self, v, g, item_id) + } + fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { + self.record("Lifetime", Id::Node(lifetime.id), lifetime); + hir_visit::walk_lifetime(self, lifetime) + } + fn visit_lifetime_def(&mut self, lifetime: &'v hir::LifetimeDef) { + self.record("LifetimeDef", Id::None, lifetime); + hir_visit::walk_lifetime_def(self, lifetime) + } + fn visit_path(&mut self, path: &'v hir::Path, _id: NodeId) { + self.record("Path", Id::None, path); + hir_visit::walk_path(self, path) + } + fn visit_path_list_item(&mut self, + prefix: &'v hir::Path, + item: &'v hir::PathListItem) { + self.record("PathListItem", Id::Node(item.node.id), item); + hir_visit::walk_path_list_item(self, prefix, item) + } + fn visit_path_segment(&mut self, + path_span: Span, + path_segment: &'v hir::PathSegment) { + self.record("PathSegment", Id::None, path_segment); + hir_visit::walk_path_segment(self, path_span, path_segment) + } + + fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) { + self.record("TypeBinding", Id::Node(type_binding.id), type_binding); + hir_visit::walk_assoc_type_binding(self, type_binding) + } + fn visit_attribute(&mut self, attr: &'v ast::Attribute) { + self.record("Attribute", Id::Attr(attr.node.id), attr); + } + fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) { + self.record("MacroDef", Id::Node(macro_def.id), macro_def); + hir_visit::walk_macro_def(self, macro_def) + } +} + +impl<'v> ast_visit::Visitor for StatCollector<'v> { + + fn visit_mod(&mut self, m: &ast::Mod, _s: Span, _n: NodeId) { + self.record("Mod", Id::None, m); + ast_visit::walk_mod(self, m) + } + + fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { + self.record("ForeignItem", Id::None, i); + ast_visit::walk_foreign_item(self, i) + } + + fn visit_item(&mut self, i: &ast::Item) { + self.record("Item", Id::None, i); + ast_visit::walk_item(self, i) + } + + fn visit_local(&mut self, l: &ast::Local) { + self.record("Local", Id::None, l); + ast_visit::walk_local(self, l) + } + + fn visit_block(&mut self, b: &ast::Block) { + self.record("Block", Id::None, b); + ast_visit::walk_block(self, b) + } + + fn visit_stmt(&mut self, s: &ast::Stmt) { + self.record("Stmt", Id::None, s); + ast_visit::walk_stmt(self, s) + } + + fn visit_arm(&mut self, a: &ast::Arm) { + self.record("Arm", Id::None, a); + ast_visit::walk_arm(self, a) + } + + fn visit_pat(&mut self, p: &ast::Pat) { + self.record("Pat", Id::None, p); + ast_visit::walk_pat(self, p) + } + + fn visit_expr(&mut self, ex: &ast::Expr) { + self.record("Expr", Id::None, ex); + ast_visit::walk_expr(self, ex) + } + + fn visit_ty(&mut self, t: &ast::Ty) { + self.record("Ty", Id::None, t); + ast_visit::walk_ty(self, t) + } + + fn visit_fn(&mut self, + fk: ast_visit::FnKind, + fd: &ast::FnDecl, + b: &ast::Block, + s: Span, + _: NodeId) { + self.record("FnDecl", Id::None, fd); + ast_visit::walk_fn(self, fk, fd, b, s) + } + + fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + self.record("TraitItem", Id::None, ti); + ast_visit::walk_trait_item(self, ti) + } + + fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + self.record("ImplItem", Id::None, ii); + ast_visit::walk_impl_item(self, ii) + } + + fn visit_ty_param_bound(&mut self, bounds: &ast::TyParamBound) { + self.record("TyParamBound", Id::None, bounds); + ast_visit::walk_ty_param_bound(self, bounds) + } + + fn visit_struct_field(&mut self, s: &ast::StructField) { + self.record("StructField", Id::None, s); + ast_visit::walk_struct_field(self, s) + } + + fn visit_variant(&mut self, + v: &ast::Variant, + g: &ast::Generics, + item_id: NodeId) { + self.record("Variant", Id::None, v); + ast_visit::walk_variant(self, v, g, item_id) + } + + fn visit_lifetime(&mut self, lifetime: &ast::Lifetime) { + self.record("Lifetime", Id::None, lifetime); + ast_visit::walk_lifetime(self, lifetime) + } + + fn visit_lifetime_def(&mut self, lifetime: &ast::LifetimeDef) { + self.record("LifetimeDef", Id::None, lifetime); + ast_visit::walk_lifetime_def(self, lifetime) + } + + fn visit_mac(&mut self, mac: &ast::Mac) { + self.record("Mac", Id::None, mac); + } + + fn visit_path_list_item(&mut self, + prefix: &ast::Path, + item: &ast::PathListItem) { + self.record("PathListItem", Id::None, item); + ast_visit::walk_path_list_item(self, prefix, item) + } + + fn visit_path_segment(&mut self, + path_span: Span, + path_segment: &ast::PathSegment) { + self.record("PathSegment", Id::None, path_segment); + ast_visit::walk_path_segment(self, path_span, path_segment) + } + + fn visit_assoc_type_binding(&mut self, type_binding: &ast::TypeBinding) { + self.record("TypeBinding", Id::None, type_binding); + ast_visit::walk_assoc_type_binding(self, type_binding) + } + + fn visit_attribute(&mut self, attr: &ast::Attribute) { + self.record("Attribute", Id::None, attr); + } + + fn visit_macro_def(&mut self, macro_def: &ast::MacroDef) { + self.record("MacroDef", Id::None, macro_def); + ast_visit::walk_macro_def(self, macro_def) + } +} diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index a4657251c9ce2..94816594878cc 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -45,6 +45,7 @@ pub mod diagnostics; pub mod ast_validation; pub mod consts; +pub mod hir_stats; pub mod loops; pub mod no_asm; pub mod rvalues; From 3e4bd8843829284a62af22687ee415a66c8207cc Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Fri, 4 Nov 2016 15:54:08 -0200 Subject: [PATCH 34/41] Change Into> for String and Into for PathBuf to From impls --- src/libcollections/string.rs | 8 ++++---- src/libstd/path.rs | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 286f06b6fe32a..348eb6fb5ffa4 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1904,10 +1904,10 @@ impl<'a> FromIterator for Cow<'a, str> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Into> for String { - fn into(self) -> Vec { - self.into_bytes() +#[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] +impl From for Vec { + fn from(string : String) -> Vec { + string.into_bytes() } } diff --git a/src/libstd/path.rs b/src/libstd/path.rs index d6a5dfe551800..e8a7951d557b2 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1172,6 +1172,13 @@ impl From for PathBuf { } } +#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")] +impl From for OsString { + fn from(path_buf : PathBuf) -> OsString { + path_buf.inner + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { fn from(s: String) -> PathBuf { @@ -1282,13 +1289,6 @@ impl AsRef for PathBuf { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Into for PathBuf { - fn into(self) -> OsString { - self.inner - } -} - /// A slice of a path (akin to [`str`]). /// /// This type supports a number of operations for inspecting a path, including From a6cf77704f407f26a181af9cfd7c838ea6270312 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Fri, 4 Nov 2016 19:08:09 +0100 Subject: [PATCH 35/41] fix #37559: update compiler-rt --- src/compiler-rt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler-rt b/src/compiler-rt index f03ba5a4e8bf1..ecd2b1f6d689d 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit f03ba5a4e8bf16dcf42dd742a4ce255c36321356 +Subproject commit ecd2b1f6d689d5afbf5debe8afb3739337323852 From 775d399da84776bfd8ae09af5f402874372e299c Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Fri, 4 Nov 2016 18:47:32 +0000 Subject: [PATCH 36/41] Remove recursive call from Cow::to_mut It seems to prevent it from being inlined. --- src/libcollections/borrow.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 8f9c357833791..30286fb243c1d 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -159,7 +159,10 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { match *self { Borrowed(borrowed) => { *self = Owned(borrowed.to_owned()); - self.to_mut() + match *self { + Borrowed(..) => unreachable!(), + Owned(ref mut owned) => owned, + } } Owned(ref mut owned) => owned, } From fe953dc16ee205ec27a946398f2d3350666962e3 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Fri, 4 Nov 2016 13:01:15 -0700 Subject: [PATCH 37/41] std: Track change to cprng syscall signature (Fuchsia) The mx_cprng_draw syscall has changed signature to separate the status and size return values, rather than multiplexing them into a single value with errors interpreted as a negative value. This patch tracks that change. --- src/libstd/sys/unix/rand.rs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 3aebb8c18ec86..9b1cf6ffd0e22 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -350,11 +350,19 @@ mod imp { #[link(name = "magenta")] extern { - fn mx_cprng_draw(buffer: *mut u8, len: usize) -> isize; + fn mx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32; } - fn getrandom(buf: &mut [u8]) -> isize { - unsafe { mx_cprng_draw(buf.as_mut_ptr(), buf.len()) } + fn getrandom(buf: &mut [u8]) -> Result { + unsafe { + let mut actual = 0; + let status = mx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual); + if status == 0 { + Ok(actual) + } else { + Err(status) + } + } } pub struct OsRng { @@ -381,12 +389,16 @@ mod imp { let mut buf = v; while !buf.is_empty() { let ret = getrandom(buf); - if ret < 0 { - panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})", - ret, buf.len()); + match ret { + Err(err) => { + panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})", + err, buf.len()) + } + Ok(actual) => { + let move_buf = buf; + buf = &mut move_buf[(actual as usize)..]; + } } - let move_buf = buf; - buf = &mut move_buf[(ret as usize)..]; } } } From ecd79a125b333e2e38fa1e0f6156438659c283db Mon Sep 17 00:00:00 2001 From: est31 Date: Fri, 4 Nov 2016 22:37:51 +0100 Subject: [PATCH 38/41] Add error when proc_macro_derive is used not on functions Fixes #37590 --- src/libsyntax_ext/proc_macro_registrar.rs | 11 +++++++++++ ...crate-type.rs => illegal-proc-macro-derive-use.rs} | 6 ++++++ 2 files changed, 17 insertions(+) rename src/test/compile-fail-fulldeps/proc-macro/{require-rustc-macro-crate-type.rs => illegal-proc-macro-derive-use.rs} (82%) diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index f49a5f0e0706e..a8accd63dcf0a 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -105,6 +105,17 @@ impl<'a> Visitor for CollectCustomDerives<'a> { match item.node { ast::ItemKind::Fn(..) => {} _ => { + // Check for invalid use of proc_macro_derive + let attr = item.attrs.iter() + .filter(|a| a.check_name("proc_macro_derive")) + .next(); + if let Some(attr) = attr { + self.handler.span_err(attr.span(), + "the `#[proc_macro_derive]` \ + attribute may only be used \ + on bare functions"); + return; + } self.check_not_pub_in_root(&item.vis, item.span); return visit::walk_item(self, item) } diff --git a/src/test/compile-fail-fulldeps/proc-macro/require-rustc-macro-crate-type.rs b/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs similarity index 82% rename from src/test/compile-fail-fulldeps/proc-macro/require-rustc-macro-crate-type.rs rename to src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs index 44397cdde0c0a..405994b36e25e 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/require-rustc-macro-crate-type.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs @@ -18,4 +18,10 @@ pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream { a } +// Issue #37590 +#[proc_macro_derive(Foo)] +//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions +pub struct Foo { +} + fn main() {} From d2cb515ab045eefa1fb7ec36078fa0440e4affec Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 5 Nov 2016 10:23:55 +0100 Subject: [PATCH 39/41] ignore gdb check for android --- src/tools/compiletest/src/runtest.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 3c6903ac21d51..c409991a55915 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -43,11 +43,12 @@ pub fn run(config: Config, testpaths: &TestPaths) { } } - _=> { } - } - - if config.mode == DebugInfoGdb && config.gdb.is_none() { - panic!("gdb not available but debuginfo gdb debuginfo test requested"); + _ => { + // android has it's own gdb handling + if config.mode == DebugInfoGdb && config.gdb.is_none() { + panic!("gdb not available but debuginfo gdb debuginfo test requested"); + } + } } if config.verbose { From 11251e59b9133f2d226c7bbc8a59a80b53edb0a7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 4 Nov 2016 17:44:53 -0700 Subject: [PATCH 40/41] Fix tests from the rollup --- src/bootstrap/clean.rs | 42 +++++++++++++++++-- src/bootstrap/config.rs | 24 +++++++++++ src/bootstrap/step.rs | 4 +- src/libsyntax/feature_gate.rs | 2 +- .../compile-fail/windows-subsystem-invalid.rs | 3 +- 5 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 3d338cf4f94d8..d8b840297b810 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -16,6 +16,7 @@ //! directory as we want that cached between builds. use std::fs; +use std::io::{self, ErrorKind}; use std::path::Path; use Build; @@ -35,14 +36,47 @@ pub fn clean(build: &Build) { if entry.file_name().to_str() == Some("llvm") { continue } - t!(fs::remove_dir_all(&entry.path())); + rm_rf(build, &entry.path()); } } } fn rm_rf(build: &Build, path: &Path) { - if path.exists() { - build.verbose(&format!("removing `{}`", path.display())); - t!(fs::remove_dir_all(path)); + if !path.exists() { + return + } + + for file in t!(fs::read_dir(path)) { + let file = t!(file).path(); + + if file.is_dir() { + rm_rf(build, &file); + } else { + // On windows we can't remove a readonly file, and git will + // often clone files as readonly. As a result, we have some + // special logic to remove readonly files on windows. + do_op(&file, "remove file", |p| fs::remove_file(p)); + } + } + do_op(path, "remove dir", |p| fs::remove_dir(p)); +} + +fn do_op(path: &Path, desc: &str, mut f: F) + where F: FnMut(&Path) -> io::Result<()> +{ + match f(path) { + Ok(()) => {} + Err(ref e) if cfg!(windows) && + e.kind() == ErrorKind::PermissionDenied => { + let mut p = t!(path.metadata()).permissions(); + p.set_readonly(false); + t!(fs::set_permissions(path, p)); + f(path).unwrap_or_else(|e| { + panic!("failed to {} {}: {}", desc, path.display(), e); + }) + } + Err(e) => { + panic!("failed to {} {}: {}", desc, path.display(), e); + } } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index abaa9389d809a..1cadb634dfcec 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -454,6 +454,30 @@ impl Config { } } +#[cfg(not(windows))] +fn parse_configure_path(path: &str) -> PathBuf { + path.into() +} + +#[cfg(windows)] +fn parse_configure_path(path: &str) -> PathBuf { + // on windows, configure produces unix style paths e.g. /c/some/path but we + // only want real windows paths + + use std::process::Command; + use build_helper; + + // '/' is invalid in windows paths, so we can detect unix paths by the presence of it + if !path.contains('/') { + return path.into(); + } + + let win_path = build_helper::output(Command::new("cygpath").arg("-w").arg(path)); + let win_path = win_path.trim(); + + win_path.into() +} + fn set(field: &mut T, val: Option) { if let Some(v) = val { *field = v; diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 4a7cfa1cc6a3e..ef6f9c526390c 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -288,13 +288,13 @@ pub fn build_rules(build: &Build) -> Rules { None)); for (krate, path, _default) in krates("rustc-main") { rules.test(&krate.test_step, path) - .dep(|s| s.name("libtest")) + .dep(|s| s.name("librustc")) .host(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc, Some(&krate.name))); } rules.test("check-rustc-all", "path/to/nowhere") - .dep(|s| s.name("libtest")) + .dep(|s| s.name("librustc")) .default(true) .host(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f29f9ec4e4f25..ba16208715109 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -722,7 +722,7 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat ("windows_subsystem", Whitelisted, Gated(Stability::Unstable, "windows_subsystem", "the windows subsystem attribute \ - id currently unstable", + is currently unstable", cfg_fn!(windows_subsystem))), // Crate level attributes diff --git a/src/test/compile-fail/windows-subsystem-invalid.rs b/src/test/compile-fail/windows-subsystem-invalid.rs index 28c3950e76f20..e0003440719e6 100644 --- a/src/test/compile-fail/windows-subsystem-invalid.rs +++ b/src/test/compile-fail/windows-subsystem-invalid.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// error-pattern: invalid windows subsystem `wrong`, only `windows` and `console` are allowed + #![feature(windows_subsystem)] #![windows_subsystem = "wrong"] -//~^ ERROR: invalid subsystem `wrong`, only `windows` and `console` are allowed fn main() {} From bdacb63f5a93b7359e2d2b6d877f2841032d2ed2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 5 Nov 2016 14:22:19 -0700 Subject: [PATCH 41/41] Only test docs and such for the host --- src/bootstrap/clean.rs | 3 ++- src/bootstrap/step.rs | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index d8b840297b810..75bcbfee6ee0b 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -36,7 +36,8 @@ pub fn clean(build: &Build) { if entry.file_name().to_str() == Some("llvm") { continue } - rm_rf(build, &entry.path()); + let path = t!(entry.path().canonicalize()); + rm_rf(build, &path); } } } diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index ef6f9c526390c..6f616434b10c3 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -112,7 +112,7 @@ pub fn build_rules(build: &Build) -> Rules { .dep(|s| s.name("build-crate-rustc-main")); for (krate, path, _default) in krates("std_shim") { rules.build(&krate.build_step, path) - .dep(|s| s.name("rustc").target(s.host)) + .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host)) .dep(move |s| { if s.host == build.config.build { dummy(s, build) @@ -296,7 +296,7 @@ pub fn build_rules(build: &Build) -> Rules { rules.test("check-rustc-all", "path/to/nowhere") .dep(|s| s.name("librustc")) .default(true) - .host(true) + .host(true) .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc, None)); @@ -304,23 +304,28 @@ pub fn build_rules(build: &Build) -> Rules { .dep(|s| s.name("tool-linkchecker")) .dep(|s| s.name("default:doc")) .default(true) + .host(true) .run(move |s| check::linkcheck(build, s.stage, s.target)); rules.test("check-cargotest", "src/tools/cargotest") .dep(|s| s.name("tool-cargotest")) .dep(|s| s.name("librustc")) + .host(true) .run(move |s| check::cargotest(build, s.stage, s.target)); rules.test("check-tidy", "src/tools/tidy") .dep(|s| s.name("tool-tidy")) .default(true) + .host(true) .run(move |s| check::tidy(build, s.stage, s.target)); rules.test("check-error-index", "src/tools/error_index_generator") .dep(|s| s.name("libstd")) .dep(|s| s.name("tool-error-index").host(s.host)) .default(true) + .host(true) .run(move |s| check::error_index(build, &s.compiler())); rules.test("check-docs", "src/doc") .dep(|s| s.name("libtest")) .default(true) + .host(true) .run(move |s| check::docs(build, &s.compiler())); rules.build("test-helpers", "src/rt/rust_test_helpers.c") @@ -363,12 +368,14 @@ pub fn build_rules(build: &Build) -> Rules { .default(build.config.docs) .run(move |s| doc::rustbook(build, s.stage, s.target, "nomicon")); rules.doc("doc-standalone", "src/doc") - .dep(move |s| s.name("rustc").target(&build.config.build)) + .dep(move |s| s.name("rustc").host(&build.config.build).target(&build.config.build)) .default(build.config.docs) .run(move |s| doc::standalone(build, s.stage, s.target)); rules.doc("doc-error-index", "src/tools/error_index_generator") .dep(move |s| s.name("tool-error-index").target(&build.config.build)) + .dep(move |s| s.name("librustc")) .default(build.config.docs) + .host(true) .run(move |s| doc::error_index(build, s.stage, s.target)); for (krate, path, default) in krates("std_shim") { rules.doc(&krate.doc_step, path) @@ -393,7 +400,7 @@ pub fn build_rules(build: &Build) -> Rules { // ======================================================================== // Distribution targets rules.dist("dist-rustc", "src/librustc") - .dep(|s| s.name("rustc")) + .dep(move |s| s.name("rustc").host(&build.config.build)) .host(true) .default(true) .run(move |s| dist::rustc(build, s.stage, s.target)); @@ -658,6 +665,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? // And finally, iterate over everything and execute it. for step in order.iter() { + self.build.verbose(&format!("executing step {:?}", step)); (self.rules[step.name].run)(step); } }