]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #60851 - Pulkit07:issue60849, r=Centril
authorMazdak Farrokhzad <twingoow@gmail.com>
Thu, 16 May 2019 08:43:35 +0000 (10:43 +0200)
committerGitHub <noreply@github.com>
Thu, 16 May 2019 08:43:35 +0000 (10:43 +0200)
Move `box` from the stable keyword to unstable keywords list

Fixes #60849

22 files changed:
README.md
src/bootstrap/native.rs
src/doc/rustc/src/command-line-arguments.md
src/liballoc/string.rs
src/libcore/convert.rs
src/librustc/session/config.rs
src/librustc/ty/layout.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/declare.rs
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_ssa/mir/mod.rs
src/librustc_codegen_ssa/traits/abi.rs
src/librustc_codegen_ssa/traits/builder.rs
src/librustc_codegen_ssa/traits/mod.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/lexer/tokentrees.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/test/ui/feature-gate/await-macro.stderr

index f6f796911b8fa57a5f702e71cc9d2dd27ed96349..75d7823490a201564a55c708960c231c7a9b869d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -128,9 +128,15 @@ build.
 #### MSVC
 [windows-msvc]: #windows-msvc
 
-MSVC builds of Rust additionally require an installation of Visual Studio 2013
-(or later) so `rustc` can use its linker. Make sure to check the “C++ tools”
-option.
+MSVC builds of Rust additionally require an installation of Visual Studio 2017
+(or later) so `rustc` can use its linker.  The simplest way is to get the
+[Visual Studio Build Tools] and check the “C++ build tools” workload.
+
+[Visual Studio Build Tools]: https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019
+
+At last check (cmake 3.14.3 and msvc 16.0.3) using the 2019 tools fails to
+build the in-tree LLVM build with a CMake error, so use 2017 instead by
+including the “MSVC v141 – VS 2017 C++ x64/x86 build tools (v14.16)” component.
 
 With these dependencies installed, you can build the compiler in a `cmd.exe`
 shell with:
index 5777331b9bfd5b9ae67b0544ee4cba6136168fe0..da2e03a1a08482e6e6f912ee249a69056c884e51 100644 (file)
@@ -317,6 +317,10 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
 fn configure_cmake(builder: &Builder<'_>,
                    target: Interned<String>,
                    cfg: &mut cmake::Config) {
+    // Do not print installation messages for up-to-date files.
+    // LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
+    cfg.define("CMAKE_INSTALL_MESSAGE", "LAZY");
+
     if builder.config.ninja {
         cfg.generator("Ninja");
     }
index dfb40284ef6cfd00bceb4ec1e8d9e5a93e47d019..bd7f6630ea2adf988db267c5692b88266b40f6c1 100644 (file)
@@ -17,28 +17,147 @@ to `#[cfg(verbose)]` and `#[cfg(feature = "serde")]` respectively.
 
 ## `-L`: add a directory to the library search path
 
-When looking for external crates, a directory passed to this flag will be searched.
+When looking for external crates or libraries, a directory passed to this flag
+will be searched.
+
+The kind of search path can optionally be specified with the form `-L
+KIND=PATH` where `KIND` may be one of:
+
+- `dependency` — Only search for transitive dependencies in this directory.
+- `crate` — Only search for this crate's direct dependencies in this
+  directory.
+- `native` — Only search for native libraries in this directory.
+- `framework` — Only search for macOS frameworks in this directory.
+- `all` — Search for all library kinds in this directory. This is the default
+  if `KIND` is not specified.
 
 ## `-l`: link the generated crate to a native library
 
 This flag allows you to specify linking to a specific native library when building
 a crate.
 
+The kind of library can optionally be specified with the form `-l KIND=lib`
+where `KIND` may be one of:
+
+- `dylib` — A native dynamic library.
+- `static` — A native static library (such as a `.a` archive).
+- `framework` — A macOS framework.
+
+The kind of library can be specified in a [`#[link]`
+attribute][link-attribute]. If the kind is not specified in the `link`
+attribute or on the command-line, it will link a dynamic library if available,
+otherwise it will use a static library. If the kind is specified on the
+command-line, it will override the kind specified in a `link` attribute.
+
+The name used in a `link` attribute may be overridden using the form `-l
+ATTR_NAME:LINK_NAME` where `ATTR_NAME` is the name in the `link` attribute,
+and `LINK_NAME` is the name of the actual library that will be linked.
+
+[link-attribute]: ../reference/items/external-blocks.html#the-link-attribute
+
 ## `--crate-type`: a list of types of crates for the compiler to emit
 
-This instructs `rustc` on which crate type to build.
+This instructs `rustc` on which crate type to build. This flag accepts a
+comma-separated list of values, and may be specified multiple times. The valid
+crate types are:
+
+- `lib` — Generates a library kind preferred by the compiler, currently
+  defaults to `rlib`.
+- `rlib` — A Rust static library.
+- `staticlib` — A native static library.
+- `dylib` — A Rust dynamic library.
+- `cdylib` — A native dynamic library.
+- `bin` — A runnable executable program.
+- `proc-macro` — Generates a format suitable for a procedural macro library
+  that may be loaded by the compiler.
+
+The crate type may be specified with the [`crate_type` attribute][crate_type].
+The `--crate-type` command-line value will override the `crate_type`
+attribute.
+
+More details may be found in the [linkage chapter] of the reference.
+
+[linkage chapter]: ../reference/linkage.html
+[crate_type]: ../reference/linkage.html
 
 ## `--crate-name`: specify the name of the crate being built
 
 This informs `rustc` of the name of your crate.
 
-## `--emit`: emit output other than a crate
-
-Instead of producing a crate, this flag can print out things like the assembly or LLVM-IR.
+## `--edition`: specify the edition to use
+
+This flag takes a value of `2015` or `2018`. The default is `2015`. More
+information about editions may be found in the [edition guide].
+
+[edition guide]: ../edition-guide/introduction.html
+
+## `--emit`: specifies the types of output files to generate
+
+This flag controls the types of output files generated by the compiler. It
+accepts a comma-separated list of values, and may be specified multiple times.
+The valid emit kinds are:
+
+- `asm` — Generates a file with the crate's assembly code. The default output
+  filename is `CRATE_NAME.s`.
+- `dep-info` — Generates a file with Makefile syntax that indicates all the
+  source files that were loaded to generate the crate. The default output
+  filename is `CRATE_NAME.d`.
+- `link` — Generates the crates specified by `--crate-type`. The default
+  output filenames depend on the crate type and platform. This is the default
+  if `--emit` is not specified.
+- `llvm-bc` — Generates a binary file containing the [LLVM bitcode]. The
+  default output filename is `CRATE_NAME.bc`.
+- `llvm-ir` — Generates a file containing [LLVM IR]. The default output
+  filename is `CRATE_NAME.ll`.
+- `metadata` — Generates a file containing metadata about the crate. The
+  default output filename is `CRATE_NAME.rmeta`.
+- `mir` — Generates a file containing rustc's mid-level intermediate
+  representation. The default output filename is `CRATE_NAME.mir`.
+- `obj` — Generates a native object file. The default output filename is
+  `CRATE_NAME.o`.
+
+The output filename can be set with the `-o` flag. A suffix may be added to
+the filename with the `-C extra-filename` flag. The files are written to the
+current directory unless the `--out-dir` flag is used. Each emission type may
+also specify the output filename with the form `KIND=PATH`, which takes
+precedence over the `-o` flag.
+
+[LLVM bitcode]: https://llvm.org/docs/BitCodeFormat.html
+[LLVM IR]: https://llvm.org/docs/LangRef.html
 
 ## `--print`: print compiler information
 
-This flag prints out various information about the compiler.
+This flag prints out various information about the compiler. This flag may be
+specified multiple times, and the information is printed in the order the
+flags are specified. Specifying a `--print` flag will usually disable the
+`--emit` step and will only print the requested information. The valid types
+of print values are:
+
+- `crate-name` — The name of the crate.
+- `file-names` — The names of the files created by the `link` emit kind.
+- `sysroot` — Path to the sysroot.
+- `cfg` — List of cfg values. See [conditional compilation] for more
+  information about cfg values.
+- `target-list` — List of known targets. The target may be selected with the
+  `--target` flag.
+- `target-cpus` — List of available CPU values for the current target. The
+  target CPU may be selected with the `-C target-cpu=val` flag.
+- `target-features` — List of available target features for the current
+  target. Target features may be enabled with the `-C target-feature=val`
+  flag.
+- `relocation-models` — List of relocation models. Relocation models may be
+  selected with the `-C relocation-model=val` flag.
+- `code-models` — List of code models. Code models may be selected with the
+  `-C code-model=val` flag.
+- `tls-models` — List of Thread Local Storage models supported. The model may
+  be selected with the `-Z tls-model=val` flag.
+- `native-static-libs` — This may be used when creating a `staticlib` crate
+  type. If this is the only flag, it will perform a full compilation and
+  include a diagnostic note that indicates the linker flags to use when
+  linking the resulting static library. The note starts with the text
+  `native-static-libs:` to make it easier to fetch the output.
+
+[conditional compilation]: ../reference/conditional-compilation.html
 
 ## `-g`: include debug information
 
@@ -54,7 +173,8 @@ This flag controls the output filename.
 
 ## `--out-dir`: directory to write the output in
 
-The outputted crate will be written to this directory.
+The outputted crate will be written to this directory. This flag is ignored if
+the `-o` flag is used.
 
 ## `--explain`: provide a detailed explanation of an error message
 
@@ -111,8 +231,9 @@ This flag, when combined with other flags, makes them produce extra output.
 
 ## `--extern`: specify where an external library is located
 
-This flag allows you to pass the name and location of an external crate that will
-be linked into the crate you're buildling.
+This flag allows you to pass the name and location of an external crate that
+will be linked into the crate you are building. This flag may be specified
+multiple times. The format of the value should be `CRATENAME=PATH`.
 
 ## `--sysroot`: Override the system root
 
@@ -121,8 +242,32 @@ distribution; this flag allows that to be overridden.
 
 ## `--error-format`: control how errors are produced
 
-This flag lets you control the format of errors.
+This flag lets you control the format of messages. Messages are printed to
+stderr. The valid options are:
+
+- `human` — Human-readable output. This is the default.
+- `json` — Structured JSON output.
+- `short` — Short, one-line messages.
 
 ## `--color`: configure coloring of output
 
-This flag lets you control color settings of the output.
+This flag lets you control color settings of the output. The valid options
+are:
+
+- `auto` — Use colors if output goes to a tty. This is the default.
+- `always` — Always use colors.
+- `never` — Never colorize output.
+
+## `--remap-path-prefix`: remap source names in output
+
+Remap source path prefixes in all output, including compiler diagnostics,
+debug information, macro expansions, etc. It takes a value of the form
+`FROM=TO` where a path prefix equal to `FROM` is rewritten to the value `TO`.
+The `FROM` may itself contain an `=` symbol, but the `TO` value may not. This
+flag may be specified multiple times.
+
+This is useful for normalizing build products, for example by removing the
+current directory out of pathnames emitted into the object files. The
+replacement is purely textual, with no consideration of the current system's
+pathname syntax. For example `--remap-path-prefix foo=bar` will match
+`foo/lib.rs` but not `./foo/lib.rs`.
index 63f7769fee56a794583404c020b421c6354373e7..e74d37c1c2bae1b676b4c14a1dc08f4cb107efa1 100644 (file)
@@ -2189,6 +2189,14 @@ fn from(s: &str) -> String {
     }
 }
 
+#[stable(feature = "from_ref_string", since = "1.35.0")]
+impl From<&String> for String {
+    #[inline]
+    fn from(s: &String) -> String {
+        s.clone()
+    }
+}
+
 // note: test pulls in libstd, which causes errors here
 #[cfg(not(test))]
 #[stable(feature = "string_from_box", since = "1.18.0")]
index cf92babcb400c6acc4418142cf0306354a839cc2..b3ff447be5ee4802f110e4c601b38007b9a30bef 100644 (file)
@@ -104,7 +104,6 @@ pub const fn identity<T>(x: T) -> T { x }
 /// If you need to do a costly conversion it is better to implement [`From`] with type
 /// `&T` or write a custom function.
 ///
-///
 /// `AsRef` has the same signature as [`Borrow`], but `Borrow` is different in few aspects:
 ///
 /// - Unlike `AsRef`, `Borrow` has a blanket impl for any `T`, and can be used to accept either
@@ -133,7 +132,7 @@ pub const fn identity<T>(x: T) -> T { x }
 /// converted a the specified type `T`.
 ///
 /// For example: By creating a generic function that takes an `AsRef<str>` we express that we
-/// want to accept all references that can be converted to &str as an argument.
+/// want to accept all references that can be converted to `&str` as an argument.
 /// Since both [`String`] and `&str` implement `AsRef<str>` we can accept both as input argument.
 ///
 /// [`String`]: ../../std/string/struct.String.html
@@ -149,7 +148,6 @@ pub const fn identity<T>(x: T) -> T { x }
 /// let s = "hello".to_string();
 /// is_hello(s);
 /// ```
-///
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsRef<T: ?Sized> {
     /// Performs the conversion.
@@ -182,6 +180,7 @@ pub trait AsRef<T: ?Sized> {
 /// write a function `add_one`that takes all arguments that can be converted to `&mut u64`.
 /// Because [`Box<T>`] implements `AsMut<T>` `add_one` accepts arguments of type
 /// `&mut Box<u64>` as well:
+///
 /// ```
 /// fn add_one<T: AsMut<u64>>(num: &mut T) {
 ///     *num.as_mut() += 1;
@@ -191,8 +190,8 @@ pub trait AsRef<T: ?Sized> {
 /// add_one(&mut boxed_num);
 /// assert_eq!(*boxed_num, 1);
 /// ```
-/// [`Box<T>`]: ../../std/boxed/struct.Box.html
 ///
+/// [`Box<T>`]: ../../std/boxed/struct.Box.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsMut<T: ?Sized> {
     /// Performs the conversion.
@@ -203,9 +202,9 @@ pub trait AsMut<T: ?Sized> {
 /// A value-to-value conversion that consumes the input value. The
 /// opposite of [`From`].
 ///
-/// One should only implement [`Into`] if a conversion to a type outside the current crate is
-/// required. Otherwise one should always prefer implementing [`From`] over [`Into`] because
-/// implementing [`From`] automatically provides one with a implementation of [`Into`] thanks to
+/// One should only implement `Into` if a conversion to a type outside the current crate is
+/// required. Otherwise one should always prefer implementing [`From`] over `Into` because
+/// implementing [`From`] automatically provides one with a implementation of `Into` thanks to
 /// the blanket implementation in the standard library. [`From`] cannot do these type of
 /// conversions because of Rust's orphaning rules.
 ///
@@ -213,8 +212,8 @@ pub trait AsMut<T: ?Sized> {
 ///
 /// # Generic Implementations
 ///
-/// - [`From<T>`]` for U` implies `Into<U> for T`
-/// - [`Into`]` is reflexive, which means that `Into<T> for T` is implemented
+/// - [`From`]`<T> for U` implies `Into<U> for T`
+/// - `Into` is reflexive, which means that `Into<T> for T` is implemented
 ///
 /// # Implementing `Into` for conversions to external types
 ///
@@ -273,7 +272,7 @@ pub trait AsMut<T: ?Sized> {
 /// [`Option<T>`]: ../../std/option/enum.Option.html
 /// [`Result<T, E>`]: ../../std/result/enum.Result.html
 /// [`String`]: ../../std/string/struct.String.html
-/// [From]: trait.From.html
+/// [`From`]: trait.From.html
 /// [`into`]: trait.Into.html#tymethod.into
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Into<T>: Sized {
@@ -285,18 +284,18 @@ pub trait Into<T>: Sized {
 /// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of
 /// [`Into`].
 ///
-/// One should always prefer implementing [`From`] over [`Into`]
-/// because implementing [`From`] automatically provides one with a implementation of [`Into`]
+/// One should always prefer implementing `From` over [`Into`]
+/// because implementing `From` automatically provides one with a implementation of [`Into`]
 /// thanks to the blanket implementation in the standard library.
 ///
 /// Only implement [`Into`] if a conversion to a type outside the current crate is required.
-/// [`From`] cannot do these type of conversions because of Rust's orphaning rules.
+/// `From` cannot do these type of conversions because of Rust's orphaning rules.
 /// See [`Into`] for more details.
 ///
-/// Prefer using [`Into`] over using [`From`] when specifying trait bounds on a generic function.
+/// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function.
 /// This way, types that directly implement [`Into`] can be used as arguments as well.
 ///
-/// The [`From`] is also very useful when performing error handling. When constructing a function
+/// The `From` is also very useful when performing error handling. When constructing a function
 /// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
 /// The `From` trait simplifies error handling by allowing a function to return a single error type
 /// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
@@ -306,14 +305,15 @@ pub trait Into<T>: Sized {
 ///
 /// # Generic Implementations
 ///
-/// - [`From<T>`]` for U` implies [`Into<U>`]` for T`
-/// - [`From`] is reflexive, which means that `From<T> for T` is implemented
+/// - `From<T> for U` implies [`Into`]`<U> for T`
+/// - `From` is reflexive, which means that `From<T> for T` is implemented
 ///
 /// # Examples
 ///
 /// [`String`] implements `From<&str>`:
 ///
-/// An explicit conversion from a &str to a String is done as follows:
+/// An explicit conversion from a `&str` to a String is done as follows:
+///
 /// ```
 /// let string = "hello".to_string();
 /// let other_string = String::from("hello");
@@ -361,7 +361,7 @@ pub trait Into<T>: Sized {
 /// [`Option<T>`]: ../../std/option/enum.Option.html
 /// [`Result<T, E>`]: ../../std/result/enum.Result.html
 /// [`String`]: ../../std/string/struct.String.html
-/// [`Into<U>`]: trait.Into.html
+/// [`Into`]: trait.Into.html
 /// [`from`]: trait.From.html#tymethod.from
 /// [book]: ../../book/ch09-00-error-handling.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -422,7 +422,7 @@ pub trait TryInto<T>: Sized {
 ///
 /// # Generic Implementations
 ///
-/// - `TryFrom<T> for U` implies [`TryInto<U>`]` for T`
+/// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
 /// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
 /// is implemented and cannot fail -- the associated `Error` type for
 /// calling `T::try_from()` on a value of type `T` is `Infallible`.
index f61ffac15d5f92acfa78a13f4c98bf69c054f26a..b5e3c4cda0a66f20d13297585046b7b35e5e1944 100644 (file)
@@ -1744,8 +1744,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         opt::multi_s(
             "",
             "print",
-            "Comma separated list of compiler information to \
-             print on stdout",
+            "Compiler information to print on stdout",
             "[crate-name|file-names|sysroot|cfg|target-list|\
              target-cpus|target-features|relocation-models|\
              code-models|tls-models|target-spec-json|native-static-libs]",
index d1a8a9a34e1559fd57d3a72b80ed29ab2f717446..6d7b0926c7ae26527fbb131fbec4f251104bbc04 100644 (file)
                                            StableHasherResult};
 
 pub use rustc_target::abi::*;
+use rustc_target::spec::{HasTargetSpec, abi::Abi as SpecAbi};
+use rustc_target::abi::call::{
+    ArgAttribute, ArgAttributes, ArgType, Conv, FnType, IgnoreMode, PassMode, Reg, RegKind
+};
+
+
 
 pub trait IntegerExt {
     fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx>;
@@ -2259,3 +2265,380 @@ fn hash_stable<W: StableHasherResult>(&self,
         }
     }
 }
+
+pub trait FnTypeExt<'tcx, C>
+where
+    C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
+        + HasDataLayout
+        + HasTargetSpec
+        + HasTyCtxt<'tcx>
+        + HasParamEnv<'tcx>,
+{
+    fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self;
+    fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
+    fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
+    fn new_internal(
+        cx: &C,
+        sig: ty::FnSig<'tcx>,
+        extra_args: &[Ty<'tcx>],
+        mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
+    ) -> Self;
+    fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
+}
+
+impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>>
+where
+    C: LayoutOf<Ty = Ty<'tcx>, TyLayout = TyLayout<'tcx>>
+        + HasDataLayout
+        + HasTargetSpec
+        + HasTyCtxt<'tcx>
+        + HasParamEnv<'tcx>,
+{
+    fn of_instance(cx: &C, instance: &ty::Instance<'tcx>) -> Self {
+        let sig = instance.fn_sig(cx.tcx());
+        let sig = cx
+            .tcx()
+            .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
+        call::FnType::new(cx, sig, &[])
+    }
+
+    fn new(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
+        call::FnType::new_internal(cx, sig, extra_args, |ty, _| ArgType::new(cx.layout_of(ty)))
+    }
+
+    fn new_vtable(cx: &C, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
+        FnTypeExt::new_internal(cx, sig, extra_args, |ty, arg_idx| {
+            let mut layout = cx.layout_of(ty);
+            // Don't pass the vtable, it's not an argument of the virtual fn.
+            // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
+            // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
+            if arg_idx == Some(0) {
+                let fat_pointer_ty = if layout.is_unsized() {
+                    // unsized `self` is passed as a pointer to `self`
+                    // FIXME (mikeyhew) change this to use &own if it is ever added to the language
+                    cx.tcx().mk_mut_ptr(layout.ty)
+                } else {
+                    match layout.abi {
+                        Abi::ScalarPair(..) => (),
+                        _ => bug!("receiver type has unsupported layout: {:?}", layout),
+                    }
+
+                    // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
+                    // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
+                    // elsewhere in the compiler as a method on a `dyn Trait`.
+                    // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
+                    // get a built-in pointer type
+                    let mut fat_pointer_layout = layout;
+                    'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
+                        && !fat_pointer_layout.ty.is_region_ptr()
+                    {
+                        'iter_fields: for i in 0..fat_pointer_layout.fields.count() {
+                            let field_layout = fat_pointer_layout.field(cx, i);
+
+                            if !field_layout.is_zst() {
+                                fat_pointer_layout = field_layout;
+                                continue 'descend_newtypes;
+                            }
+                        }
+
+                        bug!(
+                            "receiver has no non-zero-sized fields {:?}",
+                            fat_pointer_layout
+                        );
+                    }
+
+                    fat_pointer_layout.ty
+                };
+
+                // we now have a type like `*mut RcBox<dyn Trait>`
+                // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
+                // this is understood as a special case elsewhere in the compiler
+                let unit_pointer_ty = cx.tcx().mk_mut_ptr(cx.tcx().mk_unit());
+                layout = cx.layout_of(unit_pointer_ty);
+                layout.ty = fat_pointer_ty;
+            }
+            ArgType::new(layout)
+        })
+    }
+
+    fn new_internal(
+        cx: &C,
+        sig: ty::FnSig<'tcx>,
+        extra_args: &[Ty<'tcx>],
+        mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
+    ) -> Self {
+        debug!("FnType::new_internal({:?}, {:?})", sig, extra_args);
+
+        use rustc_target::spec::abi::Abi::*;
+        let conv = match cx.tcx().sess.target.target.adjust_abi(sig.abi) {
+            RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::C,
+
+            // It's the ABI's job to select this, not ours.
+            System => bug!("system abi should be selected elsewhere"),
+
+            Stdcall => Conv::X86Stdcall,
+            Fastcall => Conv::X86Fastcall,
+            Vectorcall => Conv::X86VectorCall,
+            Thiscall => Conv::X86ThisCall,
+            C => Conv::C,
+            Unadjusted => Conv::C,
+            Win64 => Conv::X86_64Win64,
+            SysV64 => Conv::X86_64SysV,
+            Aapcs => Conv::ArmAapcs,
+            PtxKernel => Conv::PtxKernel,
+            Msp430Interrupt => Conv::Msp430Intr,
+            X86Interrupt => Conv::X86Intr,
+            AmdGpuKernel => Conv::AmdGpuKernel,
+
+            // These API constants ought to be more specific...
+            Cdecl => Conv::C,
+        };
+
+        let mut inputs = sig.inputs();
+        let extra_args = if sig.abi == RustCall {
+            assert!(!sig.c_variadic && extra_args.is_empty());
+
+            match sig.inputs().last().unwrap().sty {
+                ty::Tuple(tupled_arguments) => {
+                    inputs = &sig.inputs()[0..sig.inputs().len() - 1];
+                    tupled_arguments.iter().map(|k| k.expect_ty()).collect()
+                }
+                _ => {
+                    bug!(
+                        "argument to function with \"rust-call\" ABI \
+                         is not a tuple"
+                    );
+                }
+            }
+        } else {
+            assert!(sig.c_variadic || extra_args.is_empty());
+            extra_args.to_vec()
+        };
+
+        let target = &cx.tcx().sess.target.target;
+        let win_x64_gnu =
+            target.target_os == "windows" && target.arch == "x86_64" && target.target_env == "gnu";
+        let linux_s390x =
+            target.target_os == "linux" && target.arch == "s390x" && target.target_env == "gnu";
+        let linux_sparc64 =
+            target.target_os == "linux" && target.arch == "sparc64" && target.target_env == "gnu";
+        let rust_abi = match sig.abi {
+            RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true,
+            _ => false,
+        };
+
+        // Handle safe Rust thin and fat pointers.
+        let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
+                                      scalar: &Scalar,
+                                      layout: TyLayout<'tcx>,
+                                      offset: Size,
+                                      is_return: bool| {
+            // Booleans are always an i1 that needs to be zero-extended.
+            if scalar.is_bool() {
+                attrs.set(ArgAttribute::ZExt);
+                return;
+            }
+
+            // Only pointer types handled below.
+            if scalar.value != Pointer {
+                return;
+            }
+
+            if scalar.valid_range.start() < scalar.valid_range.end() {
+                if *scalar.valid_range.start() > 0 {
+                    attrs.set(ArgAttribute::NonNull);
+                }
+            }
+
+            if let Some(pointee) = layout.pointee_info_at(cx, offset) {
+                if let Some(kind) = pointee.safe {
+                    attrs.pointee_size = pointee.size;
+                    attrs.pointee_align = Some(pointee.align);
+
+                    // `Box` pointer parameters never alias because ownership is transferred
+                    // `&mut` pointer parameters never alias other parameters,
+                    // or mutable global data
+                    //
+                    // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
+                    // and can be marked as both `readonly` and `noalias`, as
+                    // LLVM's definition of `noalias` is based solely on memory
+                    // dependencies rather than pointer equality
+                    let no_alias = match kind {
+                        PointerKind::Shared => false,
+                        PointerKind::UniqueOwned => true,
+                        PointerKind::Frozen | PointerKind::UniqueBorrowed => !is_return,
+                    };
+                    if no_alias {
+                        attrs.set(ArgAttribute::NoAlias);
+                    }
+
+                    if kind == PointerKind::Frozen && !is_return {
+                        attrs.set(ArgAttribute::ReadOnly);
+                    }
+                }
+            }
+        };
+
+        // Store the index of the last argument. This is useful for working with
+        // C-compatible variadic arguments.
+        let last_arg_idx = if sig.inputs().is_empty() {
+            None
+        } else {
+            Some(sig.inputs().len() - 1)
+        };
+
+        let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
+            let is_return = arg_idx.is_none();
+            let mut arg = mk_arg_type(ty, arg_idx);
+            if arg.layout.is_zst() {
+                // For some forsaken reason, x86_64-pc-windows-gnu
+                // doesn't ignore zero-sized struct arguments.
+                // The same is true for s390x-unknown-linux-gnu
+                // and sparc64-unknown-linux-gnu.
+                if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) {
+                    arg.mode = PassMode::Ignore(IgnoreMode::Zst);
+                }
+            }
+
+            // If this is a C-variadic function, this is not the return value,
+            // and there is one or more fixed arguments; ensure that the `VaList`
+            // is ignored as an argument.
+            if sig.c_variadic {
+                match (last_arg_idx, arg_idx) {
+                    (Some(last_idx), Some(cur_idx)) if last_idx == cur_idx => {
+                        let va_list_did = match cx.tcx().lang_items().va_list() {
+                            Some(did) => did,
+                            None => bug!("`va_list` lang item required for C-variadic functions"),
+                        };
+                        match ty.sty {
+                            ty::Adt(def, _) if def.did == va_list_did => {
+                                // This is the "spoofed" `VaList`. Set the arguments mode
+                                // so that it will be ignored.
+                                arg.mode = PassMode::Ignore(IgnoreMode::CVarArgs);
+                            }
+                            _ => (),
+                        }
+                    }
+                    _ => {}
+                }
+            }
+
+            // FIXME(eddyb) other ABIs don't have logic for scalar pairs.
+            if !is_return && rust_abi {
+                if let Abi::ScalarPair(ref a, ref b) = arg.layout.abi {
+                    let mut a_attrs = ArgAttributes::new();
+                    let mut b_attrs = ArgAttributes::new();
+                    adjust_for_rust_scalar(&mut a_attrs, a, arg.layout, Size::ZERO, false);
+                    adjust_for_rust_scalar(
+                        &mut b_attrs,
+                        b,
+                        arg.layout,
+                        a.value.size(cx).align_to(b.value.align(cx).abi),
+                        false,
+                    );
+                    arg.mode = PassMode::Pair(a_attrs, b_attrs);
+                    return arg;
+                }
+            }
+
+            if let Abi::Scalar(ref scalar) = arg.layout.abi {
+                if let PassMode::Direct(ref mut attrs) = arg.mode {
+                    adjust_for_rust_scalar(attrs, scalar, arg.layout, Size::ZERO, is_return);
+                }
+            }
+
+            arg
+        };
+
+        let mut fn_ty = FnType {
+            ret: arg_of(sig.output(), None),
+            args: inputs
+                .iter()
+                .cloned()
+                .chain(extra_args)
+                .enumerate()
+                .map(|(i, ty)| arg_of(ty, Some(i)))
+                .collect(),
+            c_variadic: sig.c_variadic,
+            conv,
+        };
+        fn_ty.adjust_for_abi(cx, sig.abi);
+        fn_ty
+    }
+
+    fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
+        if abi == SpecAbi::Unadjusted {
+            return;
+        }
+
+        if abi == SpecAbi::Rust
+            || abi == SpecAbi::RustCall
+            || abi == SpecAbi::RustIntrinsic
+            || abi == SpecAbi::PlatformIntrinsic
+        {
+            let fixup = |arg: &mut ArgType<'tcx, Ty<'tcx>>| {
+                if arg.is_ignore() {
+                    return;
+                }
+
+                match arg.layout.abi {
+                    Abi::Aggregate { .. } => {}
+
+                    // This is a fun case! The gist of what this is doing is
+                    // that we want callers and callees to always agree on the
+                    // ABI of how they pass SIMD arguments. If we were to *not*
+                    // make these arguments indirect then they'd be immediates
+                    // in LLVM, which means that they'd used whatever the
+                    // appropriate ABI is for the callee and the caller. That
+                    // means, for example, if the caller doesn't have AVX
+                    // enabled but the callee does, then passing an AVX argument
+                    // across this boundary would cause corrupt data to show up.
+                    //
+                    // This problem is fixed by unconditionally passing SIMD
+                    // arguments through memory between callers and callees
+                    // which should get them all to agree on ABI regardless of
+                    // target feature sets. Some more information about this
+                    // issue can be found in #44367.
+                    //
+                    // Note that the platform intrinsic ABI is exempt here as
+                    // that's how we connect up to LLVM and it's unstable
+                    // anyway, we control all calls to it in libstd.
+                    Abi::Vector { .. }
+                        if abi != SpecAbi::PlatformIntrinsic
+                            && cx.tcx().sess.target.target.options.simd_types_indirect =>
+                    {
+                        arg.make_indirect();
+                        return;
+                    }
+
+                    _ => return,
+                }
+
+                let size = arg.layout.size;
+                if arg.layout.is_unsized() || size > Pointer.size(cx) {
+                    arg.make_indirect();
+                } else {
+                    // We want to pass small aggregates as immediates, but using
+                    // a LLVM aggregate type for this leads to bad optimizations,
+                    // so we pick an appropriately sized integer type instead.
+                    arg.cast_to(Reg {
+                        kind: RegKind::Integer,
+                        size,
+                    });
+                }
+            };
+            fixup(&mut self.ret);
+            for arg in &mut self.args {
+                fixup(arg);
+            }
+            if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
+                attrs.set(ArgAttribute::StructRet);
+            }
+            return;
+        }
+
+        if let Err(msg) = self.adjust_for_cabi(cx, abi) {
+            cx.tcx().sess.fatal(&msg);
+        }
+    }
+}
index 70d184240fccd1a6bd85d94813809eaa7ab14860..38d4b7e3f9d85504db9548447f19f8e294fec49f 100644 (file)
@@ -11,9 +11,9 @@
 
 use rustc_codegen_ssa::traits::*;
 
-use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
-use rustc::ty::{self, Ty, Instance};
-use rustc::ty::layout::{self, PointerKind};
+use rustc_target::abi::{HasDataLayout, LayoutOf};
+use rustc::ty::{Ty};
+use rustc::ty::layout::{self};
 
 use libc::c_uint;
 
@@ -294,23 +294,7 @@ fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> &'ll Type {
     }
 }
 
-pub trait FnTypeExt<'tcx> {
-    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self;
-    fn new(cx: &CodegenCx<'ll, 'tcx>,
-           sig: ty::FnSig<'tcx>,
-           extra_args: &[Ty<'tcx>]) -> Self;
-    fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
-                  sig: ty::FnSig<'tcx>,
-                  extra_args: &[Ty<'tcx>]) -> Self;
-    fn new_internal(
-        cx: &CodegenCx<'ll, 'tcx>,
-        sig: ty::FnSig<'tcx>,
-        extra_args: &[Ty<'tcx>],
-        mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
-    ) -> Self;
-    fn adjust_for_abi(&mut self,
-                      cx: &CodegenCx<'ll, 'tcx>,
-                      abi: Abi);
+pub trait FnTypeLlvmExt<'tcx> {
     fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
@@ -318,356 +302,7 @@ fn adjust_for_abi(&mut self,
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
 }
 
-impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
-    fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self {
-        let sig = instance.fn_sig(cx.tcx);
-        let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
-        FnType::new(cx, sig, &[])
-    }
-
-    fn new(cx: &CodegenCx<'ll, 'tcx>,
-           sig: ty::FnSig<'tcx>,
-           extra_args: &[Ty<'tcx>]) -> Self {
-        FnType::new_internal(cx, sig, extra_args, |ty, _| {
-            ArgType::new(cx.layout_of(ty))
-        })
-    }
-
-    fn new_vtable(cx: &CodegenCx<'ll, 'tcx>,
-                  sig: ty::FnSig<'tcx>,
-                  extra_args: &[Ty<'tcx>]) -> Self {
-        FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| {
-            let mut layout = cx.layout_of(ty);
-            // Don't pass the vtable, it's not an argument of the virtual fn.
-            // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
-            // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
-            if arg_idx == Some(0) {
-                let fat_pointer_ty = if layout.is_unsized() {
-                    // unsized `self` is passed as a pointer to `self`
-                    // FIXME (mikeyhew) change this to use &own if it is ever added to the language
-                    cx.tcx.mk_mut_ptr(layout.ty)
-                } else {
-                    match layout.abi {
-                        LayoutAbi::ScalarPair(..) => (),
-                        _ => bug!("receiver type has unsupported layout: {:?}", layout)
-                    }
-
-                    // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
-                    // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
-                    // elsewhere in the compiler as a method on a `dyn Trait`.
-                    // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
-                    // get a built-in pointer type
-                    let mut fat_pointer_layout = layout;
-                    'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
-                        && !fat_pointer_layout.ty.is_region_ptr()
-                    {
-                        'iter_fields: for i in 0..fat_pointer_layout.fields.count() {
-                            let field_layout = fat_pointer_layout.field(cx, i);
-
-                            if !field_layout.is_zst() {
-                                fat_pointer_layout = field_layout;
-                                continue 'descend_newtypes
-                            }
-                        }
-
-                        bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
-                    }
-
-                    fat_pointer_layout.ty
-                };
-
-                // we now have a type like `*mut RcBox<dyn Trait>`
-                // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
-                // this is understood as a special case elsewhere in the compiler
-                let unit_pointer_ty = cx.tcx.mk_mut_ptr(cx.tcx.mk_unit());
-                layout = cx.layout_of(unit_pointer_ty);
-                layout.ty = fat_pointer_ty;
-            }
-            ArgType::new(layout)
-        })
-    }
-
-    fn new_internal(
-        cx: &CodegenCx<'ll, 'tcx>,
-        sig: ty::FnSig<'tcx>,
-        extra_args: &[Ty<'tcx>],
-        mk_arg_type: impl Fn(Ty<'tcx>, Option<usize>) -> ArgType<'tcx, Ty<'tcx>>,
-    ) -> Self {
-        debug!("FnType::new_internal({:?}, {:?})", sig, extra_args);
-
-        use self::Abi::*;
-        let conv = match cx.sess().target.target.adjust_abi(sig.abi) {
-            RustIntrinsic | PlatformIntrinsic |
-            Rust | RustCall => Conv::C,
-
-            // It's the ABI's job to select this, not ours.
-            System => bug!("system abi should be selected elsewhere"),
-
-            Stdcall => Conv::X86Stdcall,
-            Fastcall => Conv::X86Fastcall,
-            Vectorcall => Conv::X86VectorCall,
-            Thiscall => Conv::X86ThisCall,
-            C => Conv::C,
-            Unadjusted => Conv::C,
-            Win64 => Conv::X86_64Win64,
-            SysV64 => Conv::X86_64SysV,
-            Aapcs => Conv::ArmAapcs,
-            PtxKernel => Conv::PtxKernel,
-            Msp430Interrupt => Conv::Msp430Intr,
-            X86Interrupt => Conv::X86Intr,
-            AmdGpuKernel => Conv::AmdGpuKernel,
-
-            // These API constants ought to be more specific...
-            Cdecl => Conv::C,
-        };
-
-        let mut inputs = sig.inputs();
-        let extra_args = if sig.abi == RustCall {
-            assert!(!sig.c_variadic && extra_args.is_empty());
-
-            match sig.inputs().last().unwrap().sty {
-                ty::Tuple(tupled_arguments) => {
-                    inputs = &sig.inputs()[0..sig.inputs().len() - 1];
-                    tupled_arguments.iter().map(|k| k.expect_ty()).collect()
-                }
-                _ => {
-                    bug!("argument to function with \"rust-call\" ABI \
-                          is not a tuple");
-                }
-            }
-        } else {
-            assert!(sig.c_variadic || extra_args.is_empty());
-            extra_args.to_vec()
-        };
-
-        let target = &cx.sess().target.target;
-        let win_x64_gnu = target.target_os == "windows"
-                       && target.arch == "x86_64"
-                       && target.target_env == "gnu";
-        let linux_s390x = target.target_os == "linux"
-                       && target.arch == "s390x"
-                       && target.target_env == "gnu";
-        let linux_sparc64 = target.target_os == "linux"
-                       && target.arch == "sparc64"
-                       && target.target_env == "gnu";
-        let rust_abi = match sig.abi {
-            RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true,
-            _ => false
-        };
-
-        // Handle safe Rust thin and fat pointers.
-        let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
-                                      scalar: &layout::Scalar,
-                                      layout: TyLayout<'tcx, Ty<'tcx>>,
-                                      offset: Size,
-                                      is_return: bool| {
-            // Booleans are always an i1 that needs to be zero-extended.
-            if scalar.is_bool() {
-                attrs.set(ArgAttribute::ZExt);
-                return;
-            }
-
-            // Only pointer types handled below.
-            if scalar.value != layout::Pointer {
-                return;
-            }
-
-            if scalar.valid_range.start() < scalar.valid_range.end() {
-                if *scalar.valid_range.start() > 0 {
-                    attrs.set(ArgAttribute::NonNull);
-                }
-            }
-
-            if let Some(pointee) = layout.pointee_info_at(cx, offset) {
-                if let Some(kind) = pointee.safe {
-                    attrs.pointee_size = pointee.size;
-                    attrs.pointee_align = Some(pointee.align);
-
-                    // `Box` pointer parameters never alias because ownership is transferred
-                    // `&mut` pointer parameters never alias other parameters,
-                    // or mutable global data
-                    //
-                    // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
-                    // and can be marked as both `readonly` and `noalias`, as
-                    // LLVM's definition of `noalias` is based solely on memory
-                    // dependencies rather than pointer equality
-                    let no_alias = match kind {
-                        PointerKind::Shared => false,
-                        PointerKind::UniqueOwned => true,
-                        PointerKind::Frozen |
-                        PointerKind::UniqueBorrowed => !is_return
-                    };
-                    if no_alias {
-                        attrs.set(ArgAttribute::NoAlias);
-                    }
-
-                    if kind == PointerKind::Frozen && !is_return {
-                        attrs.set(ArgAttribute::ReadOnly);
-                    }
-                }
-            }
-        };
-
-        // Store the index of the last argument. This is useful for working with
-        // C-compatible variadic arguments.
-        let last_arg_idx = if sig.inputs().is_empty() {
-            None
-        } else {
-            Some(sig.inputs().len() - 1)
-        };
-
-        let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
-            let is_return = arg_idx.is_none();
-            let mut arg = mk_arg_type(ty, arg_idx);
-            if arg.layout.is_zst() {
-                // For some forsaken reason, x86_64-pc-windows-gnu
-                // doesn't ignore zero-sized struct arguments.
-                // The same is true for s390x-unknown-linux-gnu
-                // and sparc64-unknown-linux-gnu.
-                if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) {
-                    arg.mode = PassMode::Ignore(IgnoreMode::Zst);
-                }
-            }
-
-            // If this is a C-variadic function, this is not the return value,
-            // and there is one or more fixed arguments; ensure that the `VaList`
-            // is ignored as an argument.
-            if sig.c_variadic {
-                match (last_arg_idx, arg_idx) {
-                    (Some(last_idx), Some(cur_idx)) if last_idx == cur_idx => {
-                        let va_list_did = match cx.tcx.lang_items().va_list() {
-                            Some(did) => did,
-                            None => bug!("`va_list` lang item required for C-variadic functions"),
-                        };
-                        match ty.sty {
-                            ty::Adt(def, _) if def.did == va_list_did => {
-                                // This is the "spoofed" `VaList`. Set the arguments mode
-                                // so that it will be ignored.
-                                arg.mode = PassMode::Ignore(IgnoreMode::CVarArgs);
-                            },
-                            _ => (),
-                        }
-                    }
-                    _ => {}
-                }
-            }
-
-            // FIXME(eddyb) other ABIs don't have logic for scalar pairs.
-            if !is_return && rust_abi {
-                if let layout::Abi::ScalarPair(ref a, ref b) = arg.layout.abi {
-                    let mut a_attrs = ArgAttributes::new();
-                    let mut b_attrs = ArgAttributes::new();
-                    adjust_for_rust_scalar(&mut a_attrs,
-                                           a,
-                                           arg.layout,
-                                           Size::ZERO,
-                                           false);
-                    adjust_for_rust_scalar(&mut b_attrs,
-                                           b,
-                                           arg.layout,
-                                           a.value.size(cx).align_to(b.value.align(cx).abi),
-                                           false);
-                    arg.mode = PassMode::Pair(a_attrs, b_attrs);
-                    return arg;
-                }
-            }
-
-            if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
-                if let PassMode::Direct(ref mut attrs) = arg.mode {
-                    adjust_for_rust_scalar(attrs,
-                                           scalar,
-                                           arg.layout,
-                                           Size::ZERO,
-                                           is_return);
-                }
-            }
-
-            arg
-        };
-
-        let mut fn_ty = FnType {
-            ret: arg_of(sig.output(), None),
-            args: inputs.iter().cloned().chain(extra_args).enumerate().map(|(i, ty)| {
-                arg_of(ty, Some(i))
-            }).collect(),
-            c_variadic: sig.c_variadic,
-            conv,
-        };
-        fn_ty.adjust_for_abi(cx, sig.abi);
-        fn_ty
-    }
-
-    fn adjust_for_abi(&mut self,
-                      cx: &CodegenCx<'ll, 'tcx>,
-                      abi: Abi) {
-        if abi == Abi::Unadjusted { return }
-
-        if abi == Abi::Rust || abi == Abi::RustCall ||
-           abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
-            let fixup = |arg: &mut ArgType<'tcx, Ty<'tcx>>| {
-                if arg.is_ignore() { return; }
-
-                match arg.layout.abi {
-                    layout::Abi::Aggregate { .. } => {}
-
-                    // This is a fun case! The gist of what this is doing is
-                    // that we want callers and callees to always agree on the
-                    // ABI of how they pass SIMD arguments. If we were to *not*
-                    // make these arguments indirect then they'd be immediates
-                    // in LLVM, which means that they'd used whatever the
-                    // appropriate ABI is for the callee and the caller. That
-                    // means, for example, if the caller doesn't have AVX
-                    // enabled but the callee does, then passing an AVX argument
-                    // across this boundary would cause corrupt data to show up.
-                    //
-                    // This problem is fixed by unconditionally passing SIMD
-                    // arguments through memory between callers and callees
-                    // which should get them all to agree on ABI regardless of
-                    // target feature sets. Some more information about this
-                    // issue can be found in #44367.
-                    //
-                    // Note that the platform intrinsic ABI is exempt here as
-                    // that's how we connect up to LLVM and it's unstable
-                    // anyway, we control all calls to it in libstd.
-                    layout::Abi::Vector { .. }
-                        if abi != Abi::PlatformIntrinsic &&
-                            cx.sess().target.target.options.simd_types_indirect =>
-                    {
-                        arg.make_indirect();
-                        return
-                    }
-
-                    _ => return
-                }
-
-                let size = arg.layout.size;
-                if arg.layout.is_unsized() || size > layout::Pointer.size(cx) {
-                    arg.make_indirect();
-                } else {
-                    // We want to pass small aggregates as immediates, but using
-                    // a LLVM aggregate type for this leads to bad optimizations,
-                    // so we pick an appropriately sized integer type instead.
-                    arg.cast_to(Reg {
-                        kind: RegKind::Integer,
-                        size
-                    });
-                }
-            };
-            fixup(&mut self.ret);
-            for arg in &mut self.args {
-                fixup(arg);
-            }
-            if let PassMode::Indirect(ref mut attrs, _) = self.ret.mode {
-                attrs.set(ArgAttribute::StructRet);
-            }
-            return;
-        }
-
-        if let Err(msg) = self.adjust_for_cabi(cx, abi) {
-            cx.sess().fatal(&msg);
-        }
-    }
-
+impl<'tcx> FnTypeLlvmExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
     fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         let args_capacity: usize = self.args.iter().map(|arg|
             if arg.pad.is_some() { 1 } else { 0 } +
@@ -836,22 +471,6 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
     }
 }
 
-impl AbiMethods<'tcx> for CodegenCx<'ll, 'tcx> {
-    fn new_fn_type(&self, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType<'tcx, Ty<'tcx>> {
-        FnType::new(&self, sig, extra_args)
-    }
-    fn new_vtable(
-        &self,
-        sig: ty::FnSig<'tcx>,
-        extra_args: &[Ty<'tcx>]
-    ) -> FnType<'tcx, Ty<'tcx>> {
-        FnType::new_vtable(&self, sig, extra_args)
-    }
-    fn fn_type_of_instance(&self, instance: &Instance<'tcx>) -> FnType<'tcx, Ty<'tcx>> {
-        FnType::of_instance(&self, instance)
-    }
-}
-
 impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn apply_attrs_callsite(
         &mut self,
index bc2bb97a19e5471f5a8e6e5739eca5d200f8fe8f..48808eea3045ea892382cf08046db9297eb4c466 100644 (file)
@@ -18,6 +18,7 @@
 use rustc_codegen_ssa::base::to_immediate;
 use rustc_codegen_ssa::mir::operand::{OperandValue, OperandRef};
 use rustc_codegen_ssa::mir::place::PlaceRef;
+use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
 use std::ops::{Deref, Range};
 use std::ptr;
@@ -72,6 +73,12 @@ fn param_env(&self) -> ty::ParamEnv<'tcx> {
     }
 }
 
+impl HasTargetSpec for Builder<'_, '_, 'tcx> {
+    fn target_spec(&self) -> &Target {
+        &self.cx.target_spec()
+    }
+}
+
 impl ty::layout::LayoutOf for Builder<'_, '_, 'tcx> {
     type Ty = Ty<'tcx>;
     type TyLayout = TyLayout<'tcx>;
index 3febcb019ce29ff32677661acd312c0220e93037..bcb14b8899ec245bb728af3535bc91e0557bf1f8 100644 (file)
 
 use crate::llvm;
 use crate::llvm::AttributePlace::Function;
-use crate::abi::{FnType, FnTypeExt};
+use crate::abi::{FnType, FnTypeLlvmExt};
 use crate::attributes;
 use crate::context::CodegenCx;
 use crate::type_::Type;
 use crate::value::Value;
 use rustc::ty::{self, PolyFnSig};
-use rustc::ty::layout::LayoutOf;
+use rustc::ty::layout::{FnTypeExt, LayoutOf};
 use rustc::session::config::Sanitizer;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_codegen_ssa::traits::*;
index a5ed64a66a39da1ebdf3fce19c258a8559516b04..a3d3f0756a5f3997405faf73485934f3bd9987de 100644 (file)
@@ -10,7 +10,7 @@
 
 use crate::common;
 use crate::type_of::LayoutLlvmExt;
-use crate::abi::{LlvmType, FnTypeExt};
+use crate::abi::{LlvmType, FnTypeLlvmExt};
 use syntax::ast;
 use rustc::ty::Ty;
 use rustc::ty::layout::{self, Align, Size, TyLayout};
index ff25ed9256613c867cae9a3b9315a5549b34b67d..800bf505125d677842d88e8023848b91edb342fa 100644 (file)
@@ -1,8 +1,8 @@
-use crate::abi::{FnType, FnTypeExt};
+use crate::abi::{FnType};
 use crate::common::*;
 use crate::type_::Type;
 use rustc::ty::{self, Ty, TypeFoldable};
-use rustc::ty::layout::{self, Align, LayoutOf, PointeeInfo, Size, TyLayout};
+use rustc::ty::layout::{self, Align, LayoutOf, FnTypeExt, PointeeInfo, Size, TyLayout};
 use rustc_target::abi::{FloatTy, TyLayoutMethods};
 use rustc_mir::monomorphize::item::DefPathBasedNames;
 use rustc_codegen_ssa::traits::*;
index e64c847db651bbaebdd0da0a7e981f3e45225c05..96b8558c1d2c447f2b8149f6d71cf647f5696260 100644 (file)
@@ -1,6 +1,6 @@
 use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable};
-use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
+use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
 use rustc::mir::interpret::InterpError;
 use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
@@ -334,14 +334,14 @@ fn codegen_drop_terminator<'b>(
                     ty::ParamEnv::reveal_all(),
                     &sig,
                 );
-                let fn_ty = bx.new_vtable(sig, &[]);
+                let fn_ty = FnType::new_vtable(&bx, sig, &[]);
                 let vtable = args[1];
                 args = &args[..1];
                 (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty)
             }
             _ => {
                 (bx.get_fn(drop_fn),
-                 bx.fn_type_of_instance(&drop_fn))
+                 FnType::of_instance(&bx, &drop_fn))
             }
         };
         helper.do_call(self, &mut bx, fn_ty, drop_fn, args,
@@ -439,7 +439,7 @@ fn codegen_assert_terminator<'b>(
         // Obtain the panic entry point.
         let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
         let instance = ty::Instance::mono(bx.tcx(), def_id);
-        let fn_ty = bx.fn_type_of_instance(&instance);
+        let fn_ty = FnType::of_instance(&bx, &instance);
         let llfn = bx.get_fn(instance);
 
         // Codegen the actual panic invoke/call.
@@ -518,7 +518,7 @@ fn codegen_call_terminator<'b>(
 
         let fn_ty = match def {
             Some(ty::InstanceDef::Virtual(..)) => {
-                bx.new_vtable(sig, &extra_args)
+                FnType::new_vtable(&bx, sig, &extra_args)
             }
             Some(ty::InstanceDef::DropGlue(_, None)) => {
                 // Empty drop glue; a no-op.
@@ -526,7 +526,7 @@ fn codegen_call_terminator<'b>(
                 helper.funclet_br(self, &mut bx, target);
                 return;
             }
-            _ => bx.new_fn_type(sig, &extra_args)
+            _ => FnType::new(&bx, sig, &extra_args)
         };
 
         // Emit a panic or a no-op for `panic_if_uninhabited`.
@@ -556,7 +556,7 @@ fn codegen_call_terminator<'b>(
                 let def_id =
                     common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
                 let instance = ty::Instance::mono(bx.tcx(), def_id);
-                let fn_ty = bx.fn_type_of_instance(&instance);
+                let fn_ty = FnType::of_instance(&bx, &instance);
                 let llfn = bx.get_fn(instance);
 
                 // Codegen the actual panic invoke/call.
index fcf099235aa14f2ac4c00316de6fe018b7ca0533..060d7d18625fcd358323405f1570db82a632d9cc 100644 (file)
@@ -1,5 +1,5 @@
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
-use rustc::ty::layout::{TyLayout, HasTyCtxt};
+use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Mir};
 use rustc::session::config::DebugInfo;
 use rustc_mir::monomorphize::Instance;
@@ -202,7 +202,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
 ) {
     assert!(!instance.substs.needs_infer());
 
-    let fn_ty = cx.new_fn_type(sig, &[]);
+    let fn_ty = FnType::new(cx, sig, &[]);
     debug!("fn_ty: {:?}", fn_ty);
     let mut debug_context =
         cx.create_function_debug_context(instance, sig, llfn, mir);
index a8fd4e1d2c7c756853466f47edb41708ece38c67..509255c37be701853dd2f00e15406fa77c0d189e 100644 (file)
@@ -1,13 +1,7 @@
 use super::BackendTypes;
-use rustc::ty::{FnSig, Instance, Ty};
+use rustc::ty::{Ty};
 use rustc_target::abi::call::FnType;
 
-pub trait AbiMethods<'tcx> {
-    fn new_fn_type(&self, sig: FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType<'tcx, Ty<'tcx>>;
-    fn new_vtable(&self, sig: FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> FnType<'tcx, Ty<'tcx>>;
-    fn fn_type_of_instance(&self, instance: &Instance<'tcx>) -> FnType<'tcx, Ty<'tcx>>;
-}
-
 pub trait AbiBuilderMethods<'tcx>: BackendTypes {
     fn apply_attrs_callsite(&mut self, ty: &FnType<'tcx, Ty<'tcx>>, callsite: Self::Value);
     fn get_param(&self, index: usize) -> Self::Value;
index a3f99cd869e28f5851aebc854d63d57dc9c175da..0c4c4547a7955a1f0ad3ffdd391ea11d678509b4 100644 (file)
@@ -11,6 +11,7 @@
 use crate::MemFlags;
 use rustc::ty::Ty;
 use rustc::ty::layout::{Align, Size, HasParamEnv};
+use rustc_target::spec::{HasTargetSpec};
 use std::ops::Range;
 use std::iter::TrustedLen;
 
@@ -30,6 +31,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     + AsmBuilderMethods<'tcx>
     + StaticBuilderMethods<'tcx>
     + HasParamEnv<'tcx>
+    + HasTargetSpec
 
 {
     fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self;
index c237cd8bd2645b009b33536175a1dada09b4dd90..2bb619e79f5e06ee0b0781c46463e0433d94ca41 100644 (file)
@@ -27,7 +27,7 @@
 mod type_;
 mod write;
 
-pub use self::abi::{AbiBuilderMethods, AbiMethods};
+pub use self::abi::{AbiBuilderMethods};
 pub use self::asm::{AsmBuilderMethods, AsmMethods};
 pub use self::backend::{Backend, BackendTypes, ExtraBackendMethods};
 pub use self::builder::{BuilderMethods, OverflowOp};
@@ -41,7 +41,8 @@
     ArgTypeMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods,
 };
 pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
-use rustc::ty::layout::{HasParamEnv};
+use rustc::ty::layout::{HasParamEnv, HasTyCtxt};
+use rustc_target::spec::{HasTargetSpec};
 
 
 use std::fmt;
@@ -56,11 +57,12 @@ pub trait CodegenMethods<'tcx>:
     + ConstMethods<'tcx>
     + StaticMethods
     + DebugInfoMethods<'tcx>
-    + AbiMethods<'tcx>
     + DeclareMethods<'tcx>
     + AsmMethods<'tcx>
     + PreDefineMethods<'tcx>
     + HasParamEnv<'tcx>
+    + HasTyCtxt<'tcx>
+    + HasTargetSpec
 {
 }
 
@@ -71,11 +73,12 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
         + ConstMethods<'tcx>
         + StaticMethods
         + DebugInfoMethods<'tcx>
-        + AbiMethods<'tcx>
         + DeclareMethods<'tcx>
         + AsmMethods<'tcx>
         + PreDefineMethods<'tcx>
         + HasParamEnv<'tcx>
+        + HasTyCtxt<'tcx>
+        + HasTargetSpec
 {
 }
 
index e76605cde32ab4376e5f4e5f50b127d07d8b877c..47da3ee6a6c7817c1b770f9d2fd00cc884737db9 100644 (file)
@@ -62,19 +62,7 @@ pub struct StringReader<'a> {
     // cache a direct reference to the source text, so that we don't have to
     // retrieve it via `self.source_file.src.as_ref().unwrap()` all the time.
     src: Lrc<String>,
-    token: token::Token,
-    span: Span,
-    /// The raw source span which *does not* take `override_span` into account
-    span_src_raw: Span,
-    /// Stack of open delimiters and their spans. Used for error message.
-    open_braces: Vec<(token::DelimToken, Span)>,
-    crate unmatched_braces: Vec<UnmatchedBrace>,
-    /// The type and spans for all braces
-    ///
-    /// Used only for error recovery when arriving to EOF with mismatched braces.
-    matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
-    crate override_span: Option<Span>,
-    last_unclosed_found_span: Option<Span>,
+    override_span: Option<Span>,
 }
 
 impl<'a> StringReader<'a> {
@@ -121,8 +109,6 @@ pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
             sp: self.peek_span,
         };
         self.advance_token()?;
-        self.span_src_raw = self.peek_span_src_raw;
-
         Ok(ret_val)
     }
 
@@ -159,9 +145,6 @@ fn try_real_token(&mut self) -> Result<TokenAndSpan, ()> {
             }
         }
 
-        self.token = t.tok.clone();
-        self.span = t.sp;
-
         Ok(t)
     }
 
@@ -251,14 +234,7 @@ fn new_raw_internal(sess: &'a ParseSess, source_file: Lrc<syntax_pos::SourceFile
             peek_span_src_raw: syntax_pos::DUMMY_SP,
             src,
             fatal_errs: Vec::new(),
-            token: token::Eof,
-            span: syntax_pos::DUMMY_SP,
-            span_src_raw: syntax_pos::DUMMY_SP,
-            open_braces: Vec::new(),
-            unmatched_braces: Vec::new(),
-            matching_delim_spans: Vec::new(),
             override_span,
-            last_unclosed_found_span: None,
         }
     }
 
index 0db36c84cdfeb532bfe7b3f7d0c033a4300d1c59..4bfc5bb16c0bb236d50d140960b4648cbfbbaeb2 100644 (file)
@@ -1,13 +1,46 @@
+use syntax_pos::Span;
+
 use crate::print::pprust::token_to_string;
 use crate::parse::lexer::{StringReader, UnmatchedBrace};
 use crate::parse::{token, PResult};
 use crate::tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree, TreeAndJoint};
 
 impl<'a> StringReader<'a> {
+    crate fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+        let mut tt_reader = TokenTreesReader {
+            string_reader: self,
+            token: token::Eof,
+            span: syntax_pos::DUMMY_SP,
+            open_braces: Vec::new(),
+            unmatched_braces: Vec::new(),
+            matching_delim_spans: Vec::new(),
+            last_unclosed_found_span: None,
+        };
+        let res = tt_reader.parse_all_token_trees();
+        (res, tt_reader.unmatched_braces)
+    }
+}
+
+struct TokenTreesReader<'a> {
+    string_reader: StringReader<'a>,
+    token: token::Token,
+    span: Span,
+    /// Stack of open delimiters and their spans. Used for error message.
+    open_braces: Vec<(token::DelimToken, Span)>,
+    unmatched_braces: Vec<UnmatchedBrace>,
+    /// The type and spans for all braces
+    ///
+    /// Used only for error recovery when arriving to EOF with mismatched braces.
+    matching_delim_spans: Vec<(token::DelimToken, Span, Span)>,
+    last_unclosed_found_span: Option<Span>,
+}
+
+impl<'a> TokenTreesReader<'a> {
     // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
-    crate fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
+    fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
         let mut tts = Vec::new();
 
+        self.real_token();
         while self.token != token::Eof {
             tts.push(self.parse_token_tree()?);
         }
@@ -34,11 +67,12 @@ fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
     }
 
     fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
-        let sm = self.sess.source_map();
+        let sm = self.string_reader.sess.source_map();
         match self.token {
             token::Eof => {
                 let msg = "this file contains an un-closed delimiter";
-                let mut err = self.sess.span_diagnostic.struct_span_err(self.span, msg);
+                let mut err = self.string_reader.sess.span_diagnostic
+                    .struct_span_err(self.span, msg);
                 for &(_, sp) in &self.open_braces {
                     err.span_label(sp, "un-closed delimiter");
                 }
@@ -46,13 +80,12 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
                 if let Some((delim, _)) = self.open_braces.last() {
                     if let Some((_, open_sp, close_sp)) = self.matching_delim_spans.iter()
                         .filter(|(d, open_sp, close_sp)| {
-
-                        if let Some(close_padding) = sm.span_to_margin(*close_sp) {
-                            if let Some(open_padding) = sm.span_to_margin(*open_sp) {
-                                return delim == d && close_padding != open_padding;
+                            if let Some(close_padding) = sm.span_to_margin(*close_sp) {
+                                if let Some(open_padding) = sm.span_to_margin(*open_sp) {
+                                    return delim == d && close_padding != open_padding;
+                                }
                             }
-                        }
-                        false
+                            false
                         }).next()  // these are in reverse order as they get inserted on close, but
                     {              // we want the last open/first close
                         err.span_label(
@@ -164,7 +197,8 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
                 // matching opening delimiter).
                 let token_str = token_to_string(&self.token);
                 let msg = format!("unexpected close delimiter: `{}`", token_str);
-                let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
+                let mut err = self.string_reader.sess.span_diagnostic
+                    .struct_span_err(self.span, &msg);
                 err.span_label(self.span, "unexpected close delimiter");
                 Err(err)
             },
@@ -173,11 +207,20 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> {
                 // Note that testing for joint-ness here is done via the raw
                 // source span as the joint-ness is a property of the raw source
                 // rather than wanting to take `override_span` into account.
-                let raw = self.span_src_raw;
+                // Additionally, we actually check if the *next* pair of tokens
+                // is joint, but this is equivalent to checking the current pair.
+                let raw = self.string_reader.peek_span_src_raw;
                 self.real_token();
-                let is_joint = raw.hi() == self.span_src_raw.lo() && token::is_op(&self.token);
+                let is_joint = raw.hi() == self.string_reader.peek_span_src_raw.lo()
+                    && token::is_op(&self.token);
                 Ok((tt, if is_joint { Joint } else { NonJoint }))
             }
         }
     }
+
+    fn real_token(&mut self) {
+        let t = self.string_reader.real_token();
+        self.token = t.tok;
+        self.span = t.sp;
+    }
 }
index 655baafcd2d5da34fb68303152b337efd8cfa064..0611c1d9b42a5a6dd88791c5809e6848d5b97556 100644 (file)
@@ -290,22 +290,22 @@ pub fn source_file_to_stream(
 }
 
 /// Given a source file, produces a sequence of token trees. Returns any buffered errors from
-/// parsing the token tream.
+/// parsing the token stream.
 pub fn maybe_file_to_stream(
     sess: &ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
 ) -> Result<(TokenStream, Vec<lexer::UnmatchedBrace>), Vec<Diagnostic>> {
-    let mut srdr = lexer::StringReader::new_or_buffered_errs(sess, source_file, override_span)?;
-    srdr.real_token();
+    let srdr = lexer::StringReader::new_or_buffered_errs(sess, source_file, override_span)?;
+    let (token_trees, unmatched_braces) = srdr.into_token_trees();
 
-    match srdr.parse_all_token_trees() {
-        Ok(stream) => Ok((stream, srdr.unmatched_braces)),
+    match token_trees {
+        Ok(stream) => Ok((stream, unmatched_braces)),
         Err(err) => {
             let mut buffer = Vec::with_capacity(1);
             err.buffer(&mut buffer);
             // Not using `emit_unclosed_delims` to use `db.buffer`
-            for unmatched in srdr.unmatched_braces {
+            for unmatched in unmatched_braces {
                 let mut db = sess.span_diagnostic.struct_span_err(unmatched.found_span, &format!(
                     "incorrect close delimiter: `{}`",
                     token_to_string(&token::Token::CloseDelim(unmatched.found_delim)),
index 2d6c8c540758322cd83924e180f78f59e99cc408..99e8db9d8e6d2ec8fabc1f982c4176a8fbdb9181 100644 (file)
@@ -2635,6 +2635,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                     self.expect(&token::OpenDelim(token::Paren))?;
                     let expr = self.parse_expr()?;
                     self.expect(&token::CloseDelim(token::Paren))?;
+                    hi = self.prev_span;
                     ex = ExprKind::Await(ast::AwaitOrigin::MacroLike, expr);
                 } else if self.token.is_path_start() {
                     let path = self.parse_path(PathStyle::Expr)?;
index b6833655f6d8aa3462293058494097cc0e5325fc..699a7a8886e890eae72b10d8c584c1c1ffac0239 100644 (file)
@@ -2,7 +2,7 @@ error[E0658]: `await!(<expr>)` macro syntax is unstable, and will soon be remove
   --> $DIR/await-macro.rs:9:5
    |
 LL |     await!(bar());
-   |     ^^^^^
+   |     ^^^^^^^^^^^^^
    |
    = note: for more information, see https://github.com/rust-lang/rust/issues/50547
    = help: add #![feature(await_macro)] to the crate attributes to enable