diff options
809 files changed, 12072 insertions, 5580 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 223fd0065bf..d732075fb2d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,9 +8,9 @@ members](https://rust-lang.zulipchat.com/#narrow/stream/122652-new-members) Zulip stream. We have lots of docs below of how to get started on your own, but the Zulip stream is the best place to *ask* for help. -Documentation for contributing to Rust is located in the [Guide to Rustc Development](https://rustc-dev-guide.rust-lang.org/), -commonly known as the [rustc-dev-guide]. Despite the name, this guide documents -not just how to develop rustc (the Rust compiler), but also how to contribute to the standard library and rustdoc. +Documentation for contributing to the compiler or tooling is located in the [Guide to Rustc +Development][rustc-dev-guide], commonly known as the [rustc-dev-guide]. Documentation for the +standard library in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide]. ## About the [rustc-dev-guide] @@ -35,6 +35,7 @@ refer to [this section][contributing-bug-reports] and [open an issue][issue temp [Contributing to Rust]: https://rustc-dev-guide.rust-lang.org/contributing.html#contributing-to-rust [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ +[std-dev-guide]: https://std-dev-guide.rust-lang.org/ [contributing-bug-reports]: https://rustc-dev-guide.rust-lang.org/contributing.html#bug-reports [issue template]: https://github.com/rust-lang/rust/issues/new/choose [internals]: https://internals.rust-lang.org diff --git a/Cargo.lock b/Cargo.lock index 9581099c210..f99e58e59b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2675,9 +2675,9 @@ dependencies = [ [[package]] name = "owo-colors" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "packed_simd_2" @@ -5203,9 +5203,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -5309,6 +5309,7 @@ dependencies = [ "lazy_static", "miropt-test-tools", "regex", + "termcolor", "walkdir", ] diff --git a/README.md b/README.md index 27e7145c5a9..ac39435a8c7 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,8 @@ standard library, and documentation. [Rust]: https://www.rust-lang.org -**Note: this README is for _users_ rather than _contributors_. -If you wish to _contribute_ to the compiler, you should read the -[Getting Started][gettingstarted] section of the rustc-dev-guide instead. -You can ask for help in the [#new members Zulip stream][new-members].** - -[new-members]: https://rust-lang.zulipchat.com/#narrow/stream/122652-new-members +**Note: this README is for _users_ rather than _contributors_.** +If you wish to _contribute_ to the compiler, you should read [CONTRIBUTING.md](CONTRIBUTING.md) instead. ## Quick Start @@ -24,22 +20,23 @@ Read ["Installation"] from [The Book]. The Rust build system uses a Python script called `x.py` to build the compiler, which manages the bootstrapping process. It lives at the root of the project. -The `x.py` command can be run directly on most systems in the following format: +The `x.py` command can be run directly on most Unix systems in the following format: ```sh ./x.py <subcommand> [flags] ``` -This is how the documentation and examples assume you are running `x.py`. - -Systems such as Ubuntu 20.04 LTS do not create the necessary `python` command by default when Python is installed that allows `x.py` to be run directly. In that case, you can either create a symlink for `python` (Ubuntu provides the `python-is-python3` package for this), or run `x.py` using Python itself: +This is how the documentation and examples assume you are running `x.py`. Some alternative ways are: ```sh -# Python 3 -python3 x.py <subcommand> [flags] +# On a Unix shell if you don't have the necessary `python3` command +./x <subcommand> [flags] -# Python 2.7 -python2.7 x.py <subcommand> [flags] +# On the Windows Command Prompt (if .py files are configured to run Python) +x.py <subcommand> [flags] + +# You can also run Python yourself, e.g.: +python x.py <subcommand> [flags] ``` More information about `x.py` can be found @@ -48,20 +45,37 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide [gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html [rustcguidebuild]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html -### Building on a Unix-like system -1. Make sure you have installed the dependencies: +### Dependencies + +Make sure you have installed the dependencies: - * `g++` 5.1 or later or `clang++` 3.5 or later * `python` 3 or 2.7 - * GNU `make` 3.81 or later - * `cmake` 3.13.4 or later - * `ninja` - * `curl` * `git` - * `ssl` which comes in `libssl-dev` or `openssl-devel` + * A C compiler (when building for the host, `cc` is enough; cross-compiling may need additional compilers) + * `curl` (not needed on Windows) * `pkg-config` if you are compiling on Linux and targeting Linux + * `libiconv` (already included with glibc on Debian-based distros) + +To build cargo, you'll also need OpenSSL (`libssl-dev` or `openssl-devel` on most Unix distros). + +If building LLVM from source, you'll need additional tools: + +* `g++`, `clang++`, or MSVC with versions listed on + [LLVM's documentation](https://llvm.org/docs/GettingStarted.html#host-c-toolchain-both-compiler-and-standard-library) +* `ninja`, or GNU `make` 3.81 or later (ninja is recommended, especially on Windows) +* `cmake` 3.13.4 or later +* `libstdc++-static` may be required on some Linux distributions such as Fedora and Ubuntu + +On tier 1 or tier 2 with host tools platforms, you can also choose to download LLVM by setting `llvm.download-ci-llvm = true`. +Otherwise, you'll need LLVM installed and `llvm-config` in your path. +See [the rustc-dev-guide for more info][sysllvm]. + +[sysllvm]: https://rustc-dev-guide.rust-lang.org/building/new-target.html#using-pre-built-llvm + + +### Building on a Unix-like system -2. Clone the [source] with `git`: +1. Clone the [source] with `git`: ```sh git clone https://github.com/rust-lang/rust.git @@ -70,22 +84,21 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide [source]: https://github.com/rust-lang/rust -3. Configure the build settings: +2. Configure the build settings: The Rust build system uses a file named `config.toml` in the root of the source tree to determine various configuration settings for the build. - Copy the default `config.toml.example` to `config.toml` to get started. + Set up the defaults intended for distros to get started. You can see a full list of options + in `config.toml.example`. ```sh - cp config.toml.example config.toml + printf 'profile = "user" \nchangelog-seen = 2 \n' > config.toml ``` If you plan to use `x.py install` to create an installation, it is recommended that you set the `prefix` value in the `[install]` section to a directory. - Create an install directory if you are not installing in the default directory. - -4. Build and install: +3. Build and install: ```sh ./x.py build && ./x.py install @@ -93,15 +106,27 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide When complete, `./x.py install` will place several programs into `$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the - API-documentation tool. This install does not include [Cargo], - Rust's package manager. To build and install Cargo, you may - run `./x.py install cargo` or set the `build.extended` key in - `config.toml` to `true` to build and install all tools. + API-documentation tool. If you've set `profile = "user"` or `build.extended = true`, it will + also include [Cargo], Rust's package manager. [Cargo]: https://github.com/rust-lang/cargo ### Building on Windows +On Windows, we suggest using [winget] to install dependencies by running the following in a terminal: + +```powershell +winget install -e Python.Python.3 +winget install -e Kitware.CMake +winget install -e Git.Git +``` + +Then edit your system's `PATH` variable and add: `C:\Program Files\CMake\bin`. See +[this guide on editing the system `PATH`](https://www.java.com/en/download/help/path.html) from the +Java documentation. + +[winget]: https://github.com/microsoft/winget-cli + There are two prominent ABIs in use on Windows: the native (MSVC) ABI used by Visual Studio and the GNU ABI used by the GCC toolchain. Which version of Rust you need depends largely on what C/C++ libraries you want to interoperate with. @@ -190,7 +215,7 @@ Windows build triples are: - `x86_64-pc-windows-msvc` The build triple can be specified by either specifying `--build=<triple>` when -invoking `x.py` commands, or by copying the `config.toml` file (as described +invoking `x.py` commands, or by creating a `config.toml` file (as described in [Installing From Source](#installing-from-source)), and modifying the `build` option under the `[build]` section. @@ -204,9 +229,7 @@ configure script and makefile (the latter of which just invokes `x.py`). make && sudo make install ``` -When using the configure script, the generated `config.mk` file may override the -`config.toml` file. To go back to the `config.toml` file, delete the generated -`config.mk` file. +`configure` generates a `config.toml` which can also be used with normal `x.py` invocations. ## Building Documentation @@ -227,41 +250,20 @@ precompiled "snapshot" version of itself (made in an earlier stage of development). As such, source builds require an Internet connection to fetch snapshots, and an OS that can execute the available snapshot binaries. -Snapshot binaries are currently built and tested on several platforms: - -| Platform / Architecture | x86 | x86_64 | -|---------------------------------------------|-----|--------| -| Windows (7, 8, 10, ...) | ✓ | ✓ | -| Linux (kernel 3.2, glibc 2.17 or later) | ✓ | ✓ | -| macOS (10.7 Lion or later) | (\*) | ✓ | - -(\*): Apple dropped support for running 32-bit binaries starting from macOS 10.15 and iOS 11. -Due to this decision from Apple, the targets are no longer useful to our users. -Please read [our blog post][macx32] for more info. - -[macx32]: https://blog.rust-lang.org/2020/01/03/reducing-support-for-32-bit-apple-targets.html +See https://doc.rust-lang.org/nightly/rustc/platform-support.html for a list of supported platforms. +Only "host tools" platforms have a pre-compiled snapshot binary available; to compile for a platform +without host tools you must cross-compile. You may find that other platforms work, but these are our officially supported build environments that are most likely to work. ## Getting Help -The Rust community congregates in a few places: - -* [Stack Overflow] - Direct questions about using the language. -* [users.rust-lang.org] - General discussion and broader questions. -* [/r/rust] - News and general discussion. - -[Stack Overflow]: https://stackoverflow.com/questions/tagged/rust -[/r/rust]: https://reddit.com/r/rust -[users.rust-lang.org]: https://users.rust-lang.org/ +See https://www.rust-lang.org/community for a list of chat platforms and forums. ## Contributing -If you are interested in contributing to the Rust project, please take a look -at the [Getting Started][gettingstarted] guide in the [rustc-dev-guide]. - -[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org +See [CONTRIBUTING.md](CONTRIBUTING.md). ## License diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 31596a1e9bf..c1b26ca0925 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -572,7 +572,7 @@ impl Pat { PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()), // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type. PatKind::Ref(pat, mutbl) => { - pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))? + pat.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))? } // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array, // when `P` can be reparsed as a type `T`. @@ -1193,7 +1193,7 @@ impl Expr { ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?, ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => { - expr.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))? + expr.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))? } ExprKind::Repeat(expr, expr_len) => { @@ -2031,7 +2031,7 @@ impl Clone for Ty { impl Ty { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; - while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { + while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { final_ty = ty; } final_ty @@ -2058,7 +2058,7 @@ pub enum TyKind { /// A raw pointer (`*const T` or `*mut T`). Ptr(MutTy), /// A reference (`&'a T` or `&'a mut T`). - Rptr(Option<Lifetime>, MutTy), + Ref(Option<Lifetime>, MutTy), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(P<BareFnTy>), /// The never type (`!`). @@ -2286,7 +2286,7 @@ impl Param { if ident.name == kw::SelfLower { return match self.ty.kind { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { + TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) } _ => Some(respan( @@ -2319,7 +2319,7 @@ impl Param { Mutability::Not, P(Ty { id: DUMMY_NODE_ID, - kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }), + kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }), span, tokens: None, }), @@ -2743,8 +2743,19 @@ impl Item { /// `extern` qualifier on a function item or function type. #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub enum Extern { + /// No explicit extern keyword was used + /// + /// E.g. `fn foo() {}` None, + /// An explicit extern keyword was used, but with implicit ABI + /// + /// E.g. `extern fn foo() {}` + /// + /// This is just `extern "C"` (see `rustc_target::spec::abi::Abi::FALLBACK`) Implicit(Span), + /// An explicit extern keyword was used with an explicit ABI + /// + /// E.g. `extern "C" fn foo() {}` Explicit(StrLit, Span), } @@ -2763,9 +2774,13 @@ impl Extern { /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`). #[derive(Clone, Copy, Encodable, Decodable, Debug)] pub struct FnHeader { + /// The `unsafe` keyword, if any pub unsafety: Unsafe, + /// The `async` keyword, if any pub asyncness: Async, + /// The `const` keyword, if any pub constness: Const, + /// The `extern` keyword and corresponding ABI string, if any pub ext: Extern, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index a45ee6067bb..c572171e8f4 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -459,7 +459,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) { TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | TyKind::Never | TyKind::CVarArgs => {} TyKind::Slice(ty) => vis.visit_ty(ty), TyKind::Ptr(mt) => vis.visit_mt(mt), - TyKind::Rptr(lt, mt) => { + TyKind::Ref(lt, mt) => { visit_opt(lt, |lt| noop_visit_lifetime(lt, vis)); vis.visit_mt(mt); } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 7b8c0d79a17..5b6cf30fa96 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -379,6 +379,10 @@ impl Token { } } + pub fn is_range_separator(&self) -> bool { + [DotDot, DotDotDot, DotDotEq].contains(&self.kind) + } + pub fn is_op(&self) -> bool { match self.kind { Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_) diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 991eb489f6b..df7145a722a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -92,7 +92,7 @@ impl<'a> FnKind<'a> { #[derive(Copy, Clone, Debug)] pub enum LifetimeCtxt { /// Appears in a reference type. - Rptr, + Ref, /// Appears as a bound on a type or another lifetime. Bound, /// Appears as a generic argument. @@ -396,8 +396,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { match &typ.kind { TyKind::Slice(ty) | TyKind::Paren(ty) => visitor.visit_ty(ty), TyKind::Ptr(mutable_type) => visitor.visit_ty(&mutable_type.ty), - TyKind::Rptr(opt_lifetime, mutable_type) => { - walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Rptr); + TyKind::Ref(opt_lifetime, mutable_type) => { + walk_list!(visitor, visit_lifetime, opt_lifetime, LifetimeCtxt::Ref); visitor.visit_ty(&mutable_type.ty) } TyKind::Tup(tuple_element_types) => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9d4c2900eaf..b6b242bfc27 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -259,8 +259,8 @@ impl<'hir> LoweringContext<'_, 'hir> { body.as_deref(), ); - let mut itctx = ImplTraitContext::Universal; - let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { + let itctx = ImplTraitContext::Universal; + let (generics, decl) = this.lower_generics(generics, id, &itctx, |this| { let ret_id = asyncness.opt_return_id(); this.lower_fn_decl(&decl, id, *fn_sig_span, FnDeclKind::Fn, ret_id) }); @@ -369,9 +369,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // method, it will not be considered an in-band // lifetime to be added, but rather a reference to a // parent lifetime. - let mut itctx = ImplTraitContext::Universal; + let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, id, &mut itctx, |this| { + self.lower_generics(ast_generics, id, &itctx, |this| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( trait_ref, @@ -590,9 +590,9 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: match &i.kind { ForeignItemKind::Fn(box Fn { sig, generics, .. }) => { let fdec = &sig.decl; - let mut itctx = ImplTraitContext::Universal; + let itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, i.id, &mut itctx, |this| { + self.lower_generics(generics, i.id, &itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl( @@ -1184,8 +1184,8 @@ impl<'hir> LoweringContext<'_, 'hir> { is_async: Option<(NodeId, Span)>, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); - let mut itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, id, &mut itctx, |this| { + let itctx = ImplTraitContext::Universal; + let (generics, decl) = self.lower_generics(generics, id, &itctx, |this| { this.lower_fn_decl(&sig.decl, id, sig.span, kind, is_async) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) @@ -1316,6 +1316,8 @@ impl<'hir> LoweringContext<'_, 'hir> { param.id, ¶m.kind, ¶m.bounds, + param.colon_span, + generics.span, itctx, PredicateOrigin::GenericParam, ) @@ -1365,6 +1367,8 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: &GenericParamKind, bounds: &[GenericBound], + colon_span: Option<Span>, + parent_span: Span, itctx: &ImplTraitContext, origin: PredicateOrigin, ) -> Option<hir::WherePredicate<'hir>> { @@ -1377,21 +1381,17 @@ impl<'hir> LoweringContext<'_, 'hir> { let ident = self.lower_ident(ident); let param_span = ident.span; - let span = bounds - .iter() - .fold(Some(param_span.shrink_to_hi()), |span: Option<Span>, bound| { - let bound_span = bound.span(); - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. - if !bound_span.can_be_used_for_suggestions() { - None - } else if let Some(span) = span { - Some(span.to(bound_span)) - } else { - Some(bound_span) - } - }) - .unwrap_or(param_span.shrink_to_hi()); + + // Reconstruct the span of the entire predicate from the individual generic bounds. + let span_start = colon_span.unwrap_or_else(|| param_span.shrink_to_hi()); + let span = bounds.iter().fold(span_start, |span_accum, bound| { + match bound.span().find_ancestor_inside(parent_span) { + Some(bound_span) => span_accum.to(bound_span), + None => span_accum, + } + }); + let span = self.lower_span(span); + match kind { GenericParamKind::Const { .. } => None, GenericParamKind::Type { .. } => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index db2527a200c..83174afdb12 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -776,7 +776,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Intercept all spans entering HIR. /// Mark a span as relative to the current owning item. fn lower_span(&self, span: Span) -> Span { - if self.tcx.sess.opts.unstable_opts.incremental_relative_spans { + if self.tcx.sess.opts.incremental_relative_spans() { span.with_parent(Some(self.current_hir_id_owner.def_id)) } else { // Do not make spans relative when not using incremental compilation. @@ -1238,7 +1238,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::Err => hir::TyKind::Err, TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), - TyKind::Rptr(region, mt) => { + TyKind::Ref(region, mt) => { let region = region.unwrap_or_else(|| { let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) = self.resolver.get_lifetime_res(t.id) @@ -1252,7 +1252,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Lifetime { ident: Ident::new(kw::UnderscoreLifetime, span), id } }); let lifetime = self.lower_lifetime(®ion); - hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) + hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(f) => { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); @@ -1656,9 +1656,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Lowers a function declaration. // // `decl`: the unlowered (AST) function declaration. - // `fn_def_id`: if `Some`, impl Trait arguments are lowered into generic parameters on the - // given DefId, otherwise impl Trait is disallowed. Must be `Some` if - // `make_ret_async` is also `Some`. + // `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given `NodeId`. // `make_ret_async`: if `Some`, converts `-> T` into `-> impl Future<Output = T>` in the // return type. This is used for `async fn` declarations. The `NodeId` is the ID of the // return type `impl Trait` item, and the `Span` points to the `async` keyword. @@ -1773,7 +1771,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Given we are only considering `ImplicitSelf` types, we needn't consider // the case where we have a mutable pattern to a reference as that would // no longer be an `ImplicitSelf`. - TyKind::Rptr(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl { + TyKind::Ref(_, mt) if mt.ty.kind.is_implicit_self() => match mt.mutbl { hir::Mutability::Not => hir::ImplicitSelfKind::ImmRef, hir::Mutability::Mut => hir::ImplicitSelfKind::MutRef, }, @@ -1789,7 +1787,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // type OpaqueTy<generics_from_parent_fn> = impl Future<Output = T>; // // `output`: unlowered output type (`T` in `-> T`) - // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) + // `fn_node_id`: `NodeId` of the parent function (used to create child impl trait definition) // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created #[instrument(level = "debug", skip(self))] fn lower_async_fn_ret_ty( @@ -2031,7 +2029,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, output: &FnRetTy, span: Span, - mut nested_impl_trait_context: ImplTraitContext, + nested_impl_trait_context: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future<Output = T>` from the return type. let output_ty = match output { @@ -2039,7 +2037,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - self.lower_ty(ty, &mut nested_impl_trait_context) + self.lower_ty(ty, &nested_impl_trait_context) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2247,6 +2245,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> (hir::GenericParam<'hir>, Option<hir::WherePredicate<'hir>>, hir::TyKind<'hir>) { // Add a definition for the in-band `Param`. let def_id = self.local_def_id(node_id); + let span = self.lower_span(span); // Set the name to `impl Bound1 + Bound2`. let param = hir::GenericParam { @@ -2254,7 +2253,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { def_id, name: ParamName::Plain(self.lower_ident(ident)), pure_wrt_drop: false, - span: self.lower_span(span), + span, kind: hir::GenericParamKind::Type { default: None, synthetic: true }, colon_span: None, }; @@ -2264,6 +2263,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { node_id, &GenericParamKind::Type { default: None }, bounds, + /* colon_span */ None, + span, &ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); @@ -2273,7 +2274,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { - span: self.lower_span(span), + span, res, segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 914fc5f58da..3989fc48619 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -83,7 +83,7 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { visit::walk_ty(self, t); self.current_binders.pop(); } - TyKind::Rptr(None, _) => { + TyKind::Ref(None, _) => { self.record_elided_anchor(t.id, t.span); visit::walk_ty(self, t); } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 16b012630da..06d885a45fb 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -37,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); @@ -53,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); break hir::PatKind::Path(qpath); } @@ -63,7 +63,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &mut ImplTraitContext::Disallowed(ImplTraitPosition::Path), + &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d0e4761a10d..104cdd3a8e1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1025,7 +1025,7 @@ impl<'a> State<'a> { self.word("*"); self.print_mt(mt, true); } - ast::TyKind::Rptr(lifetime, mt) => { + ast::TyKind::Ref(lifetime, mt) => { self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 01be379120d..e4942f9b666 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -12,7 +12,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { place: &str, borrow_place: &str, value_place: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow { place, span, @@ -28,7 +28,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, borrow_span: Span, borrow_desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, span, @@ -50,7 +50,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_loan_span: Span, old_opt_via: &str, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( @@ -98,7 +98,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc: &str, old_loan_span: Span, old_load_end_span: Option<Span>, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, new_loan_span, @@ -269,7 +269,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0594, "cannot assign to {}", desc) } @@ -348,7 +348,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, path: &str, reason: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,) } @@ -359,7 +359,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { immutable_place: &str, immutable_section: &str, action: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, mutate_span, @@ -378,7 +378,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, yield_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, span, @@ -392,7 +392,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn cannot_borrow_across_destructor( &self, borrow_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!( self, borrow_span, @@ -405,7 +405,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, span: Span, path: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0597, "{} does not live long enough", path,) } @@ -415,7 +415,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { return_kind: &str, reference_desc: &str, path_desc: &str, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, span, @@ -440,7 +440,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { closure_kind: &str, borrowed_path: &str, capture_span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, closure_span, @@ -458,14 +458,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { pub(crate) fn thread_local_value_does_not_live_long_enough( &self, span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",) } pub(crate) fn temporary_value_borrowed_for_too_long( &self, span: Span, - ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",) } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8d5c5a7124f..3c3cb8c6b9c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -194,7 +194,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if !seen_spans.contains(&move_span) { if !closure { - self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern); + self.suggest_ref_or_clone( + mpi, + move_span, + &mut err, + &mut in_pattern, + move_spans, + ); } self.explain_captures( @@ -312,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span: Span, err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, in_pattern: &mut bool, + move_spans: UseSpans<'_>, ) { struct ExpressionFinder<'hir> { expr_span: Span, @@ -440,6 +447,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) = call_expr.kind { // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. + } else if let UseSpans::FnSelfUse { + kind: CallKind::Normal { .. }, + .. + } = move_spans { + // We already suggest cloning for these cases in `explain_captures`. } else { self.suggest_cloning(err, ty, move_span); } @@ -2669,7 +2681,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Need to use the `rustc_middle::ty` types to compare against the // `return_region`. Then use the `rustc_hir` type to get only // the lifetime span. - if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind { + if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind { // With access to the lifetime, we can get // the span of it. arguments.push((*argument, lifetime.ident.span)); @@ -2690,7 +2702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let return_ty = sig.output().skip_binder(); let mut return_span = fn_decl.output.span(); if let hir::FnRetTy::Return(ty) = &fn_decl.output { - if let hir::TyKind::Rptr(lifetime, _) = ty.kind { + if let hir::TyKind::Ref(lifetime, _) = ty.kind { return_span = lifetime.ident.span; } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index cbd59005200..63b16aa95a6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::GeneratorKind; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand, @@ -18,7 +18,10 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; use rustc_span::def_id::LocalDefId; use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::VariantIdx; -use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{ + type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause, +}; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; @@ -1066,18 +1069,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } CallKind::Normal { self_arg, desugaring, method_did } => { let self_arg = self_arg.unwrap(); + let tcx = self.infcx.tcx; if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring { - let ty = moved_place.ty(self.body, self.infcx.tcx).ty; - let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) { + let ty = moved_place.ty(self.body, tcx).ty; + let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) { Some(def_id) => { let infcx = self.infcx.tcx.infer_ctxt().build(); type_known_to_meet_bound_modulo_regions( &infcx, self.param_env, - infcx.tcx.mk_imm_ref( - infcx.tcx.lifetimes.re_erased, - infcx.tcx.erase_regions(ty), - ), + tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)), def_id, DUMMY_SP, ) @@ -1133,8 +1134,44 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place_name, partially_str, loop_message ), ); + let infcx = tcx.infer_ctxt().build(); + let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty); + if let ty::Adt(def, substs) = ty.kind() + && Some(def.did()) == tcx.lang_items().pin_type() + && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind() + && let self_ty = infcx.replace_bound_vars_with_fresh_vars( + fn_call_span, + LateBoundRegionConversionTime::FnCall, + tcx.fn_sig(method_did).input(0), + ) + && infcx.can_eq(self.param_env, ty, self_ty).is_ok() + { + err.span_suggestion_verbose( + fn_call_span.shrink_to_lo(), + "consider reborrowing the `Pin` instead of moving it", + "as_mut().".to_string(), + Applicability::MaybeIncorrect, + ); + } + if let Some(clone_trait) = tcx.lang_items().clone_trait() + && let trait_ref = tcx.mk_trait_ref(clone_trait, [ty]) + && let o = Obligation::new( + tcx, + ObligationCause::dummy(), + self.param_env, + ty::Binder::dummy(trait_ref), + ) + && infcx.predicate_must_hold_modulo_regions(&o) + { + err.span_suggestion_verbose( + fn_call_span.shrink_to_lo(), + "you can `clone` the value and consume it, but this might not be \ + your desired behavior", + "clone().".to_string(), + Applicability::MaybeIncorrect, + ); + } } - let tcx = self.infcx.tcx; // Avoid pointing to the same function in multiple different // error messages. if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3319a80681f..6f6d1b01bd4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -180,6 +180,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // the verbs used in some diagnostic messages. let act; let acted_on; + let mut suggest = true; + let mut mut_error = None; + let mut count = 1; let span = match error_access { AccessKind::Mutate => { @@ -194,15 +197,50 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let borrow_spans = self.borrow_spans(span, location); let borrow_span = borrow_spans.args_or_use(); - err = self.cannot_borrow_path_as_mutable_because(borrow_span, &item_msg, &reason); - borrow_spans.var_span_label( - &mut err, - format!( - "mutable borrow occurs due to use of {} in closure", - self.describe_any_place(access_place.as_ref()), - ), - "mutable", - ); + match the_place_err { + PlaceRef { local, projection: [] } + if self.body.local_decls[local].can_be_made_mutable() => + { + let span = self.body.local_decls[local].source_info.span; + mut_error = Some(span); + if let Some((buffer, c)) = self.get_buffered_mut_error(span) { + // We've encountered a second (or more) attempt to mutably borrow an + // immutable binding, so the likely problem is with the binding + // declaration, not the use. We collect these in a single diagnostic + // and make the binding the primary span of the error. + err = buffer; + count = c + 1; + if count == 2 { + err.replace_span_with(span, false); + err.span_label(span, "not mutable"); + } + suggest = false; + } else { + err = self.cannot_borrow_path_as_mutable_because( + borrow_span, + &item_msg, + &reason, + ); + } + } + _ => { + err = self.cannot_borrow_path_as_mutable_because( + borrow_span, + &item_msg, + &reason, + ); + } + } + if suggest { + borrow_spans.var_span_label( + &mut err, + format!( + "mutable borrow occurs due to use of {} in closure", + self.describe_any_place(access_place.as_ref()), + ), + "mutable", + ); + } borrow_span } }; @@ -276,7 +314,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { pat_span: _, }, )))) => { - err.span_note(sp, "the binding is already a mutable borrow"); + if suggest { + err.span_note(sp, "the binding is already a mutable borrow"); + } } _ => { err.span_note( @@ -333,16 +373,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let local_decl = &self.body.local_decls[local]; assert_eq!(local_decl.mutability, Mutability::Not); - err.span_label(span, format!("cannot {ACT}", ACT = act)); - err.span_suggestion( - local_decl.source_info.span, - "consider changing this to be mutable", - format!("mut {}", self.local_names[local].unwrap()), - Applicability::MachineApplicable, - ); - let tcx = self.infcx.tcx; - if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() { - self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err); + if count < 10 { + err.span_label(span, format!("cannot {act}")); + } + if suggest { + err.span_suggestion_verbose( + local_decl.source_info.span.shrink_to_lo(), + "consider changing this to be mutable", + "mut ".to_string(), + Applicability::MachineApplicable, + ); + let tcx = self.infcx.tcx; + if let ty::Closure(id, _) = *the_place_err.ty(self.body, tcx).ty.kind() { + self.show_mutating_upvar(tcx, id.expect_local(), the_place_err, &mut err); + } } } @@ -357,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let captured_place = &self.upvars[upvar_index.index()].place; - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); let upvar_hir_id = captured_place.get_root_variable(); @@ -397,7 +441,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .span_to_snippet(span) .map_or(false, |snippet| snippet.starts_with("&mut ")) => { - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); err.span_suggestion( span, "try removing `&mut` here", @@ -409,7 +453,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { local, projection: [ProjectionElem::Deref] } if self.body.local_decls[local].is_ref_for_guard() => { - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); err.note( "variables bound in patterns are immutable until the end of the pattern guard", ); @@ -537,7 +581,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some((true, err_help_span, suggested_code)) => { let (is_trait_sig, local_trait) = self.is_error_in_trait(local); if !is_trait_sig { - err.span_suggestion( + err.span_suggestion_verbose( err_help_span, &format!( "consider changing this to be a mutable {pointer_desc}" @@ -546,7 +590,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } else if let Some(x) = local_trait { - err.span_suggestion( + err.span_suggestion_verbose( x, &format!( "consider changing that to be a mutable {pointer_desc}" @@ -569,24 +613,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.span_label( span, format!( - "`{NAME}` is a `{SIGIL}` {DESC}, \ - so the data it refers to cannot be {ACTED_ON}", - NAME = name, - SIGIL = pointer_sigil, - DESC = pointer_desc, - ACTED_ON = acted_on + "`{name}` is a `{pointer_sigil}` {pointer_desc}, \ + so the data it refers to cannot be {acted_on}", ), ); } _ => { err.span_label( span, - format!( - "cannot {ACT} through `{SIGIL}` {DESC}", - ACT = act, - SIGIL = pointer_sigil, - DESC = pointer_desc - ), + format!("cannot {act} through `{pointer_sigil}` {pointer_desc}"), ); } } @@ -605,13 +640,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(BorrowedContentSource::OverloadedDeref(ty)) => { err.help(&format!( "trait `DerefMut` is required to modify through a dereference, \ - but it is not implemented for `{ty}`", + but it is not implemented for `{ty}`", )); } Some(BorrowedContentSource::OverloadedIndex(ty)) => { err.help(&format!( "trait `IndexMut` is required to modify indexed content, \ - but it is not implemented for `{ty}`", + but it is not implemented for `{ty}`", )); self.suggest_map_index_mut_alternatives(ty, &mut err, span); } @@ -620,11 +655,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } _ => { - err.span_label(span, format!("cannot {ACT}", ACT = act)); + err.span_label(span, format!("cannot {act}")); } } - self.buffer_error(err); + if let Some(span) = mut_error { + self.buffer_mut_error(span, err, count); + } else { + self.buffer_error(err); + } } fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) { @@ -1209,7 +1248,7 @@ fn get_mut_span_in_struct_field<'tcx>( // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. && let hir::Node::Field(field) = node - && let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind + && let hir::TyKind::Ref(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind { return Some(lt.ident.span.between(ty.span)); } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 171e62d91e1..dbd4cac7b14 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -493,10 +493,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // // & // - let's call the lifetime of this reference `'1` - ( - ty::Ref(region, referent_ty, _), - hir::TyKind::Rptr(_lifetime, referent_hir_ty), - ) => { + (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => { if region.to_region_vid() == needle_fr { // Just grab the first character, the `&`. let source_map = self.infcx.tcx.sess.source_map(); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 168b798788b..ae1bea008b6 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2270,6 +2270,7 @@ mod error { /// same primary span come out in a consistent order. buffered_move_errors: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>, + buffered_mut_errors: FxHashMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>, /// Diagnostics to be reported buffer. buffered: Vec<Diagnostic>, /// Set to Some if we emit an error during borrowck @@ -2281,6 +2282,7 @@ mod error { BorrowckErrors { tcx, buffered_move_errors: BTreeMap::new(), + buffered_mut_errors: Default::default(), buffered: Default::default(), tainted_by_errors: None, } @@ -2331,12 +2333,34 @@ mod error { } } + pub fn get_buffered_mut_error( + &mut self, + span: Span, + ) -> Option<(DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)> { + self.errors.buffered_mut_errors.remove(&span) + } + + pub fn buffer_mut_error( + &mut self, + span: Span, + t: DiagnosticBuilder<'tcx, ErrorGuaranteed>, + count: usize, + ) { + self.errors.buffered_mut_errors.insert(span, (t, count)); + } + pub fn emit_errors(&mut self) -> Option<ErrorGuaranteed> { // Buffer any move errors that we collected and de-duplicated. for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. diag.buffer(&mut self.errors.buffered); } + for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) { + if count > 10 { + diag.note(&format!("...and {} other attempted mutable borrows", count - 10)); + } + diag.buffer(&mut self.errors.buffered); + } if !self.errors.buffered.is_empty() { self.errors.buffered.sort_by_key(|diag| diag.sort_span); diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 62c6f958137..8fa43f8528c 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -37,31 +37,30 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // those. // // e.g., `|x: FxHashMap<_, &'static u32>| ...` - let user_provided_sig; - if !self.tcx().is_closure(mir_def_id.to_def_id()) { - user_provided_sig = None; + let user_provided_sig = if !self.tcx().is_closure(mir_def_id.to_def_id()) { + None } else { let typeck_results = self.tcx().typeck(mir_def_id); - user_provided_sig = - typeck_results.user_provided_sigs.get(&mir_def_id).map(|user_provided_poly_sig| { - // Instantiate the canonicalized variables from - // user-provided signature (e.g., the `_` in the code - // above) with fresh variables. - let poly_sig = self.instantiate_canonical_with_fresh_inference_vars( - body.span, - &user_provided_poly_sig, - ); - - // Replace the bound items in the fn sig with fresh - // variables, so that they represent the view from - // "inside" the closure. - self.infcx.replace_bound_vars_with_fresh_vars( - body.span, - LateBoundRegionConversionTime::FnCall, - poly_sig, - ) - }); - } + + typeck_results.user_provided_sigs.get(&mir_def_id).map(|user_provided_poly_sig| { + // Instantiate the canonicalized variables from + // user-provided signature (e.g., the `_` in the code + // above) with fresh variables. + let poly_sig = self.instantiate_canonical_with_fresh_inference_vars( + body.span, + &user_provided_poly_sig, + ); + + // Replace the bound items in the fn sig with fresh + // variables, so that they represent the view from + // "inside" the closure. + self.infcx.replace_bound_vars_with_fresh_vars( + body.span, + LateBoundRegionConversionTime::FnCall, + poly_sig, + ) + }) + }; debug!(?normalized_input_tys, ?body.local_decls); diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 544d971b27a..5b1b7e6804c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -117,8 +117,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // `let names: &'static _ = &["field1", "field2"];` let names_let = if is_struct { let lt_static = Some(cx.lifetime_static(span)); - let ty_static_ref = - cx.ty_rptr(span, cx.ty_infer(span), lt_static, ast::Mutability::Not); + let ty_static_ref = cx.ty_ref(span, cx.ty_infer(span), lt_static, ast::Mutability::Not); Some(cx.stmt_let_ty( span, false, @@ -138,13 +137,13 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> ); let ty_slice = cx.ty( span, - ast::TyKind::Slice(cx.ty_rptr(span, ty_dyn_debug, None, ast::Mutability::Not)), + ast::TyKind::Slice(cx.ty_ref(span, ty_dyn_debug, None, ast::Mutability::Not)), ); let values_let = cx.stmt_let_ty( span, false, Ident::new(sym::values, span), - Some(cx.ty_rptr(span, ty_slice, None, ast::Mutability::Not)), + Some(cx.ty_ref(span, ty_slice, None, ast::Mutability::Not)), cx.expr_array_ref(span, value_exprs), ); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index eaa4881906a..c6f5f5d0807 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -97,7 +97,7 @@ impl Ty { match self { Ref(ty, mutbl) => { let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); - cx.ty_rptr(span, raw_ty, None, *mutbl) + cx.ty_ref(span, raw_ty, None, *mutbl) } Path(p) => p.to_ty(cx, span, self_ty, self_generics), Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)), diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index a7283ea601b..84d06b69a9d 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -30,7 +30,7 @@ pub fn expand_option_env<'cx>( sp, true, cx.std_path(&[sym::option, sym::Option, sym::None]), - vec![GenericArg::Type(cx.ty_rptr( + vec![GenericArg::Type(cx.ty_ref( sp, cx.ty_ident(sp, Ident::new(sym::str, sp)), Some(lt), diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index b88de224675..21c8caa658f 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -349,7 +349,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> { .item_static( span, Ident::new(sym::_DECLS, span), - cx.ty_rptr( + cx.ty_ref( span, cx.ty( span, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 487eead22b8..95baa95b021 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -102,10 +102,10 @@ pub fn uwtable_attr(llcx: &llvm::Context) -> &Attribute { pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { let mut fp = cx.sess().target.frame_pointer; + let opts = &cx.sess().opts; // "mcount" function relies on stack pointer. // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>. - if cx.sess().instrument_mcount() || matches!(cx.sess().opts.cg.force_frame_pointers, Some(true)) - { + if opts.unstable_opts.instrument_mcount || matches!(opts.cg.force_frame_pointers, Some(true)) { fp = FramePointer::Always; } let attr_value = match fp { @@ -119,7 +119,7 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr /// Tell LLVM what instrument function to insert. #[inline] fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { - if cx.sess().instrument_mcount() { + if cx.sess().opts.unstable_opts.instrument_mcount { // Similar to `clang -pg` behavior. Handled by the // `post-inline-ee-instrument` LLVM pass. diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 97d0de47b3a..e23c88b62c1 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -203,7 +203,7 @@ pub fn target_machine_factory( sess.opts.unstable_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable); let emit_stack_size_section = sess.opts.unstable_opts.emit_stack_sizes; - let asm_comments = sess.asm_comments(); + let asm_comments = sess.opts.unstable_opts.asm_comments; let relax_elf_relocations = sess.opts.unstable_opts.relax_elf_relocations.unwrap_or(sess.target.relax_elf_relocations); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 2fa602520dc..79b243f73d1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -81,10 +81,10 @@ unsafe fn configure_llvm(sess: &Session) { }; // Set the llvm "program name" to make usage and invalid argument messages more clear. add("rustc -Cllvm-args=\"...\" with", true); - if sess.time_llvm_passes() { + if sess.opts.unstable_opts.time_llvm_passes { add("-time-passes", false); } - if sess.print_llvm_passes() { + if sess.opts.unstable_opts.print_llvm_passes { add("-debug-pass=Structure", false); } if sess.target.generate_arange_section diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 12fca64968a..1a7de1a184a 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1899,7 +1899,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> { // FIXME: time_llvm_passes support - does this use a global context or // something? - if sess.codegen_units() == 1 && sess.time_llvm_passes() { + if sess.codegen_units() == 1 && sess.opts.unstable_opts.time_llvm_passes { self.backend.print_pass_timings() } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 664697e0eda..8b34be38580 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -681,7 +681,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( }); let mut total_codegen_time = Duration::new(0, 0); - let start_rss = tcx.sess.time_passes().then(|| get_resident_set_size()); + let start_rss = tcx.sess.opts.unstable_opts.time_passes.then(|| get_resident_set_size()); // The non-parallel compiler can only translate codegen units to LLVM IR // on a single thread, leading to a staircase effect where the N LLVM @@ -781,7 +781,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( // Since the main thread is sometimes blocked during codegen, we keep track // -Ztime-passes output manually. - if tcx.sess.time_passes() { + if tcx.sess.opts.unstable_opts.time_passes { let end_rss = get_resident_set_size(); print_time_passes_entry( diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index c7f2e1966c1..b0fa7745667 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -2,6 +2,7 @@ use rustc_ast::{ast, MetaItemKind, NestedMetaItem}; use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr}; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -60,6 +61,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); + // In some cases, attribute are only valid on functions, but it's the `check_attr` + // pass that check that they aren't used anywhere else, rather this module. + // In these cases, we bail from performing further checks that are only meaningful for + // functions (such as calling `fn_sig`, which ICEs if given a non-function). We also + // report a delayed bug, just in case `check_attr` isn't doing its job. + let validate_fn_only_attr = |attr_sp| -> bool { + let def_kind = tcx.def_kind(did); + if let DefKind::Fn | DefKind::AssocFn | DefKind::Variant | DefKind::Ctor(..) = def_kind { + true + } else { + tcx.sess.delay_span_bug(attr_sp, "this attribute can only be applied to functions"); + false + } + }; + let mut inline_span = None; let mut link_ordinal_span = None; let mut no_sanitize_span = None; @@ -197,7 +213,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } } } else if attr.has_name(sym::cmse_nonsecure_entry) { - if !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) { + if validate_fn_only_attr(attr.span) + && !matches!(tcx.fn_sig(did).abi(), abi::Abi::C { .. }) + { struct_span_err!( tcx.sess, attr.span, @@ -214,7 +232,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; } else if attr.has_name(sym::track_caller) { - if !tcx.is_closure(did.to_def_id()) && tcx.fn_sig(did).abi() != abi::Abi::Rust { + if !tcx.is_closure(did.to_def_id()) + && validate_fn_only_attr(attr.span) + && tcx.fn_sig(did).abi() != abi::Abi::Rust + { struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") .emit(); } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 819c2678d6c..3ae6c531b44 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -509,7 +509,7 @@ pub fn compute_debuginfo_vtable_name<'tcx>( visited.clear(); push_generic_params_internal(tcx, trait_ref.substs, &mut vtable_name, &mut visited); } else { - vtable_name.push_str("_"); + vtable_name.push('_'); } push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index cff72048ead..978aff511bf 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -637,7 +637,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.set_debug_loc(bx, terminator.source_info); // Obtain the panic entry point. - let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicNoUnwind); + let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind); // Codegen the actual panic invoke/call. let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, None, &[], false); @@ -698,11 +698,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) }); let msg = bx.const_str(&msg_str); - let location = self.get_caller_location(bx, source_info).immediate(); // Obtain the panic entry point. let (fn_abi, llfn) = - common::build_langcall(bx, Some(source_info.span), LangItem::Panic); + common::build_langcall(bx, Some(source_info.span), LangItem::PanicNounwind); // Codegen the actual panic invoke/call. helper.do_call( @@ -710,7 +709,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx, fn_abi, llfn, - &[msg.0, msg.1, location], + &[msg.0, msg.1], target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)), cleanup, &[], @@ -1665,7 +1664,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llpersonality = self.cx.eh_personality(); bx.cleanup_landing_pad(llpersonality); - let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind); + let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind); let fn_ty = bx.fn_decl_backend_type(&fn_abi); let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None); diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 6777fae74f1..04ce701452b 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -216,12 +216,6 @@ impl<'tcx> Validator<'_, 'tcx> { return Err(Unpromotable); } - // We cannot promote things that need dropping, since the promoted value - // would not get dropped. - if self.qualif_local::<qualifs::NeedsDrop>(place.local) { - return Err(Unpromotable); - } - Ok(()) } _ => bug!(), @@ -262,13 +256,17 @@ impl<'tcx> Validator<'_, 'tcx> { } } } else { - let span = self.body.local_decls[local].source_info.span; - span_bug!(span, "{:?} not promotable, qualif_local shouldn't have been called", local); + false } } fn validate_local(&mut self, local: Local) -> Result<(), Unpromotable> { if let TempState::Defined { location: loc, uses, valid } = self.temps[local] { + // We cannot promote things that need dropping, since the promoted value + // would not get dropped. + if self.qualif_local::<qualifs::NeedsDrop>(local) { + return Err(Unpromotable); + } valid.or_else(|_| { let ok = { let block = &self.body[loc.block]; diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index 05f059c89d5..c63caa06818 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -1,6 +1,7 @@ use crate::stable_hasher::{HashStable, StableHasher, StableOrd}; use std::borrow::Borrow; use std::cmp::Ordering; +use std::fmt::Debug; use std::mem; use std::ops::{Bound, Index, IndexMut, RangeBounds}; @@ -16,7 +17,7 @@ pub use index_map::SortedIndexMultiMap; /// stores data in a more compact way. It also supports accessing contiguous /// ranges of elements as a slice, and slices of already sorted elements can be /// inserted efficiently. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] pub struct SortedMap<K, V> { data: Vec<(K, V)>, } @@ -314,5 +315,11 @@ impl<K: HashStable<CTX> + StableOrd, V: HashStable<CTX>, CTX> HashStable<CTX> fo } } +impl<K: Debug, V: Debug> Debug for SortedMap<K, V> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_map().entries(self.data.iter().map(|(a, b)| (a, b))).finish() + } +} + #[cfg(test)] mod tests; diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 1a728f82f00..ae4836645fa 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -223,7 +223,7 @@ pub trait ToStableHashKey<HCX> { /// stable across compilation session boundaries. More formally: /// /// ```txt -/// Ord::cmp(a1, b1) == Ord:cmp(a2, b2) +/// Ord::cmp(a1, b1) == Ord::cmp(a2, b2) /// where a2 = decode(encode(a1, context1), context2) /// b2 = decode(encode(b1, context1), context2) /// ``` diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 236f66eae72..30179e97872 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -653,7 +653,7 @@ fn print_crate_info( for req in &sess.opts.prints { match *req { TargetList => { - let mut targets = rustc_target::spec::TARGETS.iter().copied().collect::<Vec<_>>(); + let mut targets = rustc_target::spec::TARGETS.to_vec(); targets.sort_unstable(); println!("{}", targets.join("\n")); } @@ -1199,8 +1199,8 @@ static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + }; // Invoke the default handler, which prints the actual panic message and optionally a backtrace - // Don't do this for `ExplicitBug`, which has an unhelpful message and backtrace. - if !info.payload().is::<rustc_errors::ExplicitBug>() { + // Don't do this for `GoodPathBug`, which already emits its own more useful backtrace. + if !info.payload().is::<rustc_errors::GoodPathBug>() { (*DEFAULT_HOOK)(info); // Separate the output with an empty line @@ -1237,7 +1237,9 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { // a .span_bug or .bug call has already printed what // it wants to print. - if !info.payload().is::<rustc_errors::ExplicitBug>() { + if !info.payload().is::<rustc_errors::ExplicitBug>() + && !info.payload().is::<rustc_errors::GoodPathBug>() + { let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); handler.emit_diagnostic(&mut d); } diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index d05559e9244..3fba2cf5749 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -244,6 +244,7 @@ E0457: include_str!("./error_codes/E0457.md"), E0458: include_str!("./error_codes/E0458.md"), E0459: include_str!("./error_codes/E0459.md"), E0460: include_str!("./error_codes/E0460.md"), +E0461: include_str!("./error_codes/E0461.md"), E0462: include_str!("./error_codes/E0462.md"), E0463: include_str!("./error_codes/E0463.md"), E0464: include_str!("./error_codes/E0464.md"), @@ -275,10 +276,12 @@ E0509: include_str!("./error_codes/E0509.md"), E0510: include_str!("./error_codes/E0510.md"), E0511: include_str!("./error_codes/E0511.md"), E0512: include_str!("./error_codes/E0512.md"), +E0514: include_str!("./error_codes/E0514.md"), E0515: include_str!("./error_codes/E0515.md"), E0516: include_str!("./error_codes/E0516.md"), E0517: include_str!("./error_codes/E0517.md"), E0518: include_str!("./error_codes/E0518.md"), +E0519: include_str!("./error_codes/E0519.md"), E0520: include_str!("./error_codes/E0520.md"), E0521: include_str!("./error_codes/E0521.md"), E0522: include_str!("./error_codes/E0522.md"), @@ -595,8 +598,7 @@ E0791: include_str!("./error_codes/E0791.md"), // E0421, // merged into 531 // E0427, // merged into 530 // E0456, // plugin `..` is not available for triple `..` - E0461, // couldn't find crate `..` with expected target triple .. - E0465, // multiple .. candidates for `..` found +// E0465, // removed: merged with E0464 // E0467, // removed // E0470, // removed // E0471, // constant evaluation error (in pattern) @@ -615,8 +617,6 @@ E0791: include_str!("./error_codes/E0791.md"), // E0488, // lifetime of variable does not enclose its declaration // E0489, // type/lifetime parameter not in scope here E0490, // a value of type `..` is borrowed for too long - E0514, // metadata version mismatch - E0519, // local crate and dependency have same (crate-name, disambiguator) E0523, // two dependencies have same (crate-name, disambiguator) but different SVH // E0526, // shuffle indices are not constant // E0540, // multiple rustc_deprecated attributes diff --git a/compiler/rustc_error_codes/src/error_codes/E0461.md b/compiler/rustc_error_codes/src/error_codes/E0461.md new file mode 100644 index 00000000000..33105c43ccf --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0461.md @@ -0,0 +1,30 @@ +Couldn't find crate `..` with expected target triple `..`. + +Example of erroneous code: + +`a.rs` +```ignore (cannot-link-with-other-tests) +#![crate_type = "lib"] + +fn foo() {} +``` + +`main.rs` +```ignore (cannot-link-with-other-tests) +extern crate a; + +fn main() { + a::foo(); +} +``` + +`a.rs` is then compiled with `--target powerpc-unknown-linux-gnu` and `b.rs` +with `--target x86_64-unknown-linux-gnu`. `a.rs` is compiled into a binary +format incompatible with `b.rs`; PowerPC and x86 are totally different +architectures. This issue also extends to any difference in target triples, as +`std` is operating-system specific. + +This error can be fixed by: + * Using [Cargo](../cargo/index.html), the Rust package manager, automatically + fixing this issue. + * Recompiling either crate so that they target a consistent target triple. diff --git a/compiler/rustc_error_codes/src/error_codes/E0514.md b/compiler/rustc_error_codes/src/error_codes/E0514.md new file mode 100644 index 00000000000..ce2bbc5c505 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0514.md @@ -0,0 +1,33 @@ +Dependency compiled with different version of `rustc`. + +Example of erroneous code: + +`a.rs` +```ignore (cannot-link-with-other-tests) +// compiled with stable `rustc` + +#[crate_type = "lib"] +``` + +`b.rs` +```ignore (cannot-link-with-other-tests) +// compiled with nightly `rustc` + +#[crate_type = "lib"] + +extern crate a; // error: found crate `a` compiled by an incompatible version + // of rustc +``` + +This error is caused when the version of `rustc` used to compile a crate, as +stored in the binary's metadata, differs from the version of one of its +dependencies. Many parts of Rust binaries are considered unstable. For +instance, the Rust ABI is not stable between compiler versions. This means that +the compiler cannot be sure about *how* to call a function between compiler +versions, and therefore this error occurs. + +This error can be fixed by: + * Using [Cargo](../cargo/index.html), the Rust package manager and + [Rustup](https://rust-lang.github.io/rustup/), the Rust toolchain installer, + automatically fixing this issue. + * Recompiling the crates with a uniform `rustc` version. diff --git a/compiler/rustc_error_codes/src/error_codes/E0519.md b/compiler/rustc_error_codes/src/error_codes/E0519.md new file mode 100644 index 00000000000..12876e2ad75 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0519.md @@ -0,0 +1,40 @@ +The current crate is indistinguishable from one of its dependencies, in terms +of metadata. + +Example of erroneous code: + +`a.rs` +```ignore (cannot-link-with-other-tests) +#![crate_name = "a"] +#![crate_type = "lib"] + +pub fn foo() {} +``` + +`b.rs` +```ignore (cannot-link-with-other-tests) +#![crate_name = "a"] +#![crate_type = "lib"] + +// error: the current crate is indistinguishable from one of its dependencies: +// it has the same crate-name `a` and was compiled with the same +// `-C metadata` arguments. This will result in symbol conflicts between +// the two. +extern crate a; + +pub fn foo() {} + +fn bar() { + a::foo(); // is this calling the local crate or the dependency? +} +``` + +The above example compiles two crates with exactly the same name and +`crate_type` (plus any other metadata). This causes an error because it becomes +impossible for the compiler to distinguish between symbols (`pub` item names). + +This error can be fixed by: + * Using [Cargo](../cargo/index.html), the Rust package manager, automatically + fixing this issue. + * Recompiling the crate with different metadata (different name/ + `crate_type`). diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index b3ca540417d..79b8b417257 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -4,6 +4,11 @@ metadata_rlib_required = metadata_lib_required = crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form +metadata_rustc_lib_required = + crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form + .note = only .rmeta files are distributed for `rustc_private` crates other than `rustc_driver` + .help = try adding `extern crate rustc_driver;` at the top level of this crate + metadata_crate_dep_multiple = cannot satisfy dependencies so `{$crate_name}` only shows up once .help = having upstream crates all available in one format will likely make this go away @@ -196,11 +201,7 @@ metadata_extern_location_not_file = extern location for {$crate_name} is not a file: {$location} metadata_multiple_candidates = - multiple {$flavor} candidates for `{$crate_name}` found - -metadata_multiple_matching_crates = - multiple matching crates for `{$crate_name}` - .note = candidates:{$candidates} + multiple candidates for `{$flavor}` dependency `{$crate_name}` found metadata_symbol_conflicts_current = the current crate is indistinguishable from one of its dependencies: it has the same crate-name `{$crate_name}` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index b53550e5fd5..3401978caf5 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -365,3 +365,6 @@ parse_invalid_identifier_with_leading_number = expected identifier, found number parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn` .suggestion = replace `fn` with `impl` here + +parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn` + .suggestion = use `Fn` to refer to the trait diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 585a54308c6..e19a6fe0ee9 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -365,12 +365,12 @@ impl Diagnostic { self } - pub fn replace_span_with(&mut self, after: Span) -> &mut Self { + pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self { let before = self.span.clone(); self.set_span(after); for span_label in before.span_labels() { if let Some(label) = span_label.label { - if span_label.is_primary { + if span_label.is_primary && keep_label { self.span.push_span_label(after, label); } else { self.span.push_span_label(span_label.span, label); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index e2a0e436fd5..0ca200abe19 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -845,7 +845,10 @@ impl EmitterWriter { // 3 | | // 4 | | } // | |_^ test - if let [ann] = &line.annotations[..] { + let mut buffer_ops = vec![]; + let mut annotations = vec![]; + let mut short_start = true; + for ann in &line.annotations { if let AnnotationType::MultilineStart(depth) = ann.annotation_type { if source_string.chars().take(ann.start_col).all(|c| c.is_whitespace()) { let style = if ann.is_primary { @@ -853,10 +856,23 @@ impl EmitterWriter { } else { Style::UnderlineSecondary }; - buffer.putc(line_offset, width_offset + depth - 1, '/', style); - return vec![(depth, style)]; + annotations.push((depth, style)); + buffer_ops.push((line_offset, width_offset + depth - 1, '/', style)); + } else { + short_start = false; + break; } + } else if let AnnotationType::MultilineLine(_) = ann.annotation_type { + } else { + short_start = false; + break; + } + } + if short_start { + for (y, x, c, s) in buffer_ops { + buffer.putc(y, x, c, s); } + return annotations; } // We want to display like this: diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 518b5ec10f8..136c360201e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -40,12 +40,13 @@ use rustc_span::source_map::SourceMap; use rustc_span::HashStableContext; use rustc_span::{Loc, Span}; +use std::any::Any; use std::borrow::Cow; +use std::fmt; use std::hash::Hash; use std::num::NonZeroUsize; use std::panic; use std::path::Path; -use std::{error, fmt}; use termcolor::{Color, ColorSpec}; @@ -361,16 +362,11 @@ pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker}; /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. -#[derive(Copy, Clone, Debug)] pub struct ExplicitBug; -impl fmt::Display for ExplicitBug { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "parser internal bug") - } -} - -impl error::Error for ExplicitBug {} +/// Signifies that the compiler died with an explicit call to `.delay_good_path_bug` +/// rather than a failed assertion, etc. +pub struct GoodPathBug; pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, @@ -473,10 +469,12 @@ pub enum StashKey { CallAssocMethod, } -fn default_track_diagnostic(_: &Diagnostic) {} +fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { + (*f)(d) +} -pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&Diagnostic)> = - AtomicRef::new(&(default_track_diagnostic as fn(&_))); +pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&mut Diagnostic, &mut dyn FnMut(&mut Diagnostic))> = + AtomicRef::new(&(default_track_diagnostic as _)); #[derive(Copy, Clone, Default)] pub struct HandlerFlags { @@ -507,7 +505,11 @@ impl Drop for HandlerInner { if !self.has_errors() { let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new()); - self.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued"); + self.flush_delayed( + bugs, + "no errors encountered even though `delay_span_bug` issued", + ExplicitBug, + ); } // FIXME(eddyb) this explains what `delayed_good_path_bugs` are! @@ -520,6 +522,7 @@ impl Drop for HandlerInner { self.flush_delayed( bugs.into_iter().map(DelayedDiagnostic::decorate), "no warnings or errors encountered even though `delayed_good_path_bugs` issued", + GoodPathBug, ); } @@ -653,17 +656,19 @@ impl Handler { /// Retrieve a stashed diagnostic with `steal_diagnostic`. pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) { let mut inner = self.inner.borrow_mut(); - inner.stash((span, key), diag); + inner.stash((span.with_parent(None), key), diag); } /// Steal a previously stashed diagnostic with the given `Span` and [`StashKey`] as the key. pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> { let mut inner = self.inner.borrow_mut(); - inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) + inner + .steal((span.with_parent(None), key)) + .map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) } pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool { - self.inner.borrow().stashed_diagnostics.get(&(span, key)).is_some() + self.inner.borrow().stashed_diagnostics.get(&(span.with_parent(None), key)).is_some() } /// Emit all stashed diagnostics. @@ -1203,7 +1208,11 @@ impl Handler { pub fn flush_delayed(&self) { let mut inner = self.inner.lock(); let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new()); - inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued"); + inner.flush_delayed( + bugs, + "no errors encountered even though `delay_span_bug` issued", + ExplicitBug, + ); } } @@ -1212,8 +1221,8 @@ impl HandlerInner { self.taught_diagnostics.insert(code.clone()) } - fn force_print_diagnostic(&mut self, mut db: Diagnostic) { - self.emitter.emit_diagnostic(&mut db); + fn force_print_diagnostic(&mut self, db: Diagnostic) { + self.emitter.emit_diagnostic(&db); } /// Emit all stashed diagnostics. @@ -1288,67 +1297,69 @@ impl HandlerInner { && !diagnostic.is_force_warn() { if diagnostic.has_future_breakage() { - (*TRACK_DIAGNOSTICS)(diagnostic); + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {}); } return None; } - (*TRACK_DIAGNOSTICS)(diagnostic); - if matches!(diagnostic.level, Level::Expect(_) | Level::Allow) { + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |_| {}); return None; } - if let Some(ref code) = diagnostic.code { - self.emitted_diagnostic_codes.insert(code.clone()); - } - - let already_emitted = |this: &mut Self| { - let mut hasher = StableHasher::new(); - diagnostic.hash(&mut hasher); - let diagnostic_hash = hasher.finish(); - !this.emitted_diagnostics.insert(diagnostic_hash) - }; + let mut guaranteed = None; + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |diagnostic| { + if let Some(ref code) = diagnostic.code { + self.emitted_diagnostic_codes.insert(code.clone()); + } - // Only emit the diagnostic if we've been asked to deduplicate or - // haven't already emitted an equivalent diagnostic. - if !(self.flags.deduplicate_diagnostics && already_emitted(self)) { - debug!(?diagnostic); - debug!(?self.emitted_diagnostics); - let already_emitted_sub = |sub: &mut SubDiagnostic| { - debug!(?sub); - if sub.level != Level::OnceNote { - return false; - } + let already_emitted = |this: &mut Self| { let mut hasher = StableHasher::new(); - sub.hash(&mut hasher); + diagnostic.hash(&mut hasher); let diagnostic_hash = hasher.finish(); - debug!(?diagnostic_hash); - !self.emitted_diagnostics.insert(diagnostic_hash) + !this.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {}); - - self.emitter.emit_diagnostic(diagnostic); - if diagnostic.is_error() { - self.deduplicated_err_count += 1; - } else if let Warning(_) = diagnostic.level { - self.deduplicated_warn_count += 1; + // Only emit the diagnostic if we've been asked to deduplicate or + // haven't already emitted an equivalent diagnostic. + if !(self.flags.deduplicate_diagnostics && already_emitted(self)) { + debug!(?diagnostic); + debug!(?self.emitted_diagnostics); + let already_emitted_sub = |sub: &mut SubDiagnostic| { + debug!(?sub); + if sub.level != Level::OnceNote { + return false; + } + let mut hasher = StableHasher::new(); + sub.hash(&mut hasher); + let diagnostic_hash = hasher.finish(); + debug!(?diagnostic_hash); + !self.emitted_diagnostics.insert(diagnostic_hash) + }; + + diagnostic.children.drain_filter(already_emitted_sub).for_each(|_| {}); + + self.emitter.emit_diagnostic(diagnostic); + if diagnostic.is_error() { + self.deduplicated_err_count += 1; + } else if let Warning(_) = diagnostic.level { + self.deduplicated_warn_count += 1; + } } - } - if diagnostic.is_error() { - if matches!(diagnostic.level, Level::Error { lint: true }) { - self.bump_lint_err_count(); + if diagnostic.is_error() { + if matches!(diagnostic.level, Level::Error { lint: true }) { + self.bump_lint_err_count(); + } else { + self.bump_err_count(); + } + + guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); } else { - self.bump_err_count(); + self.bump_warn_count(); } + }); - Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } else { - self.bump_warn_count(); - - None - } + guaranteed } fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { @@ -1580,6 +1591,7 @@ impl HandlerInner { &mut self, bugs: impl IntoIterator<Item = Diagnostic>, explanation: impl Into<DiagnosticMessage> + Copy, + panic_with: impl Any + Send + 'static, ) { let mut no_bugs = true; for mut bug in bugs { @@ -1607,7 +1619,7 @@ impl HandlerInner { // Panic with `ExplicitBug` to avoid "unexpected panic" messages. if !no_bugs { - panic::panic_any(ExplicitBug); + panic::panic_any(panic_with); } } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index ef50efb8125..93b3af4ab97 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -87,14 +87,14 @@ impl<'a> ExtCtxt<'a> { self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident))) } - pub fn ty_rptr( + pub fn ty_ref( &self, span: Span, ty: P<ast::Ty>, lifetime: Option<ast::Lifetime>, mutbl: ast::Mutability, ) -> P<ast::Ty> { - self.ty(span, ast::TyKind::Rptr(lifetime, self.ty_mt(ty, mutbl))) + self.ty(span, ast::TyKind::Ref(lifetime, self.ty_mt(ty, mutbl))) } pub fn ty_ptr(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty> { @@ -626,7 +626,7 @@ impl<'a> ExtCtxt<'a> { // Builds `#[name = val]`. // - // Note: `span` is used for both the identifer and the value. + // Note: `span` is used for both the identifier and the value. pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute { let g = &self.sess.parse_sess.attr_id_generator; attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e26c16dcd7e..5d47c1ed363 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -587,7 +587,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { .resolver .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment); - if self.cx.sess.opts.unstable_opts.incremental_relative_spans { + if self.cx.sess.opts.incremental_relative_spans() { for (invoc, _) in invocations.iter_mut() { let expn_id = invoc.expansion_data.id; let parent_def = self.cx.resolver.invocation_parent(expn_id); diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 197f056917f..3a38d7a9669 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -43,7 +43,7 @@ pub(super) fn failed_to_match_macro<'cx>( return result; } - let Some((token, label, remaining_matcher)) = tracker.best_failure else { + let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure else { return DummyResult::any(sp); }; @@ -95,11 +95,24 @@ struct CollectTrackerAndEmitter<'a, 'cx, 'matcher> { cx: &'a mut ExtCtxt<'cx>, remaining_matcher: Option<&'matcher MatcherLoc>, /// Which arm's failure should we report? (the one furthest along) - best_failure: Option<(Token, &'static str, MatcherLoc)>, + best_failure: Option<BestFailure>, root_span: Span, result: Option<Box<dyn MacResult + 'cx>>, } +struct BestFailure { + token: Token, + position_in_tokenstream: usize, + msg: &'static str, + remaining_matcher: MatcherLoc, +} + +impl BestFailure { + fn is_better_position(&self, position: usize) -> bool { + position > self.position_in_tokenstream + } +} + impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> { fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) { if self.remaining_matcher.is_none() @@ -119,18 +132,25 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, "should not collect detailed info for successful macro match", ); } - Failure(token, msg) => match self.best_failure { - Some((ref best_token, _, _)) if best_token.span.lo() >= token.span.lo() => {} - _ => { - self.best_failure = Some(( - token.clone(), + Failure(token, approx_position, msg) => { + debug!(?token, ?msg, "a new failure of an arm"); + + if self + .best_failure + .as_ref() + .map_or(true, |failure| failure.is_better_position(*approx_position)) + { + self.best_failure = Some(BestFailure { + token: token.clone(), + position_in_tokenstream: *approx_position, msg, - self.remaining_matcher + remaining_matcher: self + .remaining_matcher .expect("must have collected matcher already") .clone(), - )) + }) } - }, + } Error(err_sp, msg) => { let span = err_sp.substitute_dummy(self.root_span); self.cx.struct_span_err(span, msg).emit(); @@ -178,12 +198,12 @@ pub(super) fn emit_frag_parse_err( ); if !e.span.is_dummy() { // early end of macro arm (#52866) - e.replace_span_with(parser.token.span.shrink_to_hi()); + e.replace_span_with(parser.token.span.shrink_to_hi(), true); } } if e.span.is_dummy() { // Get around lack of span in error (#30128) - e.replace_span_with(site_span); + e.replace_span_with(site_span, true); if !parser.sess.source_map().is_imported(arm_span) { e.span_label(arm_span, "in this macro arm"); } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index d161868edce..df1c1834c1d 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -310,7 +310,8 @@ pub(crate) enum ParseResult<T> { Success(T), /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected /// end of macro invocation. Otherwise, it indicates that no rules expected the given token. - Failure(Token, &'static str), + /// The usize is the approximate position of the token in the input token stream. + Failure(Token, usize, &'static str), /// Fatal error (malformed macro?). Abort compilation. Error(rustc_span::Span, String), ErrorReported(ErrorGuaranteed), @@ -455,6 +456,7 @@ impl TtParser { &mut self, matcher: &'matcher [MatcherLoc], token: &Token, + approx_position: usize, track: &mut T, ) -> Option<NamedParseResult> { // Matcher positions that would be valid if the macro invocation was over now. Only @@ -598,6 +600,7 @@ impl TtParser { token::Eof, if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() }, ), + approx_position, "missing tokens in macro arguments", ), }) @@ -627,7 +630,12 @@ impl TtParser { // Process `cur_mps` until either we have finished the input or we need to get some // parsing from the black-box parser done. - let res = self.parse_tt_inner(matcher, &parser.token, track); + let res = self.parse_tt_inner( + matcher, + &parser.token, + parser.approx_token_stream_pos(), + track, + ); if let Some(res) = res { return res; } @@ -642,6 +650,7 @@ impl TtParser { // parser: syntax error. return Failure( parser.token.clone(), + parser.approx_token_stream_pos(), "no rules expected this token in macro call", ); } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 320c533a66e..fbb806fe81b 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -326,8 +326,8 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( return Ok((i, named_matches)); } - Failure(_, _) => { - trace!("Failed to match arm, trying the next one"); + Failure(_, reached_position, _) => { + trace!(%reached_position, "Failed to match arm, trying the next one"); // Try the next arm. } Error(_, _) => { @@ -432,7 +432,7 @@ pub fn compile_declarative_macro( let argument_map = match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) { Success(m) => m, - Failure(token, msg) => { + Failure(token, _, msg) => { let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s); @@ -1166,11 +1166,7 @@ fn check_matcher_core<'tt>( err.note(&format!( "{}{} or {}", msg, - ts[..ts.len() - 1] - .iter() - .copied() - .collect::<Vec<_>>() - .join(", "), + ts[..ts.len() - 1].to_vec().join(", "), ts[ts.len() - 1], )); } diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e5348039edd..e2f30fb89b9 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -194,7 +194,7 @@ declare_features! ( /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), /// Allows `#[instruction_set(_)]` attribute. - (accepted, isa_attribute, "CURRENT_RUSTC_VERSION", Some(74727), None), + (accepted, isa_attribute, "1.67.0", Some(74727), None), /// Allows some increased flexibility in the name resolution rules, /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120), None), @@ -240,7 +240,7 @@ declare_features! ( /// Allows specifying the bundle link modifier (accepted, native_link_modifiers_bundle, "1.63.0", Some(81490), None), /// Allows specifying the verbatim link modifier - (accepted, native_link_modifiers_verbatim, "CURRENT_RUSTC_VERSION", Some(81490), None), + (accepted, native_link_modifiers_verbatim, "1.67.0", Some(81490), None), /// Allows specifying the whole-archive link modifier (accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490), None), /// Allows using non lexical lifetimes (RFC 2094). diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index a616dd70f8e..beade4d44da 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -383,7 +383,7 @@ declare_features! ( /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), /// Allows `dyn* Trait` objects. - (incomplete, dyn_star, "1.65.0", Some(91611), None), + (incomplete, dyn_star, "1.65.0", Some(102425), None), /// Allows `X..Y` patterns. (active, exclusive_range_pattern, "1.11.0", Some(37854), None), /// Allows exhaustive pattern matching on types that contain uninhabited types. @@ -418,7 +418,7 @@ declare_features! ( /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), /// Allows referencing `Self` and projections in impl-trait. - (active, impl_trait_projections, "CURRENT_RUSTC_VERSION", Some(103532), None), + (active, impl_trait_projections, "1.67.0", Some(103532), None), /// Allows using imported `main` function (active, imported_main, "1.53.0", Some(28937), None), /// Allows associated types in inherent impls. @@ -505,7 +505,7 @@ declare_features! ( /// Allows lints part of the strict provenance effort. (active, strict_provenance, "1.61.0", Some(95228), None), /// Allows string patterns to dereference values to match them. - (active, string_deref_patterns, "CURRENT_RUSTC_VERSION", Some(87121), None), + (active, string_deref_patterns, "1.67.0", Some(87121), None), /// Allows the use of `#[target_feature]` on safe functions. (active, target_feature_11, "1.45.0", Some(69098), None), /// Allows using `#[thread_local]` on `static` items. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 91825c29258..034f06bb889 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -854,7 +854,11 @@ impl fmt::Debug for OwnerNodes<'_> { &self .nodes .iter_enumerated() - .map(|(id, parented_node)| (id, parented_node.as_ref().map(|node| node.parent))) + .map(|(id, parented_node)| { + let parented_node = parented_node.as_ref().map(|node| node.parent); + + debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})")) + }) .collect::<Vec<_>>(), ) .field("bodies", &self.bodies) @@ -2431,7 +2435,7 @@ impl<'hir> Ty<'hir> { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; - while let TyKind::Rptr(_, MutTy { ty, .. }) = &final_ty.kind { + while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { final_ty = ty; } final_ty @@ -2588,7 +2592,7 @@ pub enum TyKind<'hir> { /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). - Rptr(&'hir Lifetime, MutTy<'hir>), + Ref(&'hir Lifetime, MutTy<'hir>), /// A bare function (e.g., `fn(usize) -> bool`). BareFn(&'hir BareFnTy<'hir>), /// The never type (`!`). @@ -3609,16 +3613,19 @@ mod size_asserts { static_assert_size!(Res, 12); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); - // tidy-alphabetical-end - // FIXME: move the tidy directive to the end after the next bootstrap bump - #[cfg(bootstrap)] - static_assert_size!(TraitItem<'_>, 88); - #[cfg(not(bootstrap))] static_assert_size!(TraitItem<'_>, 80); - #[cfg(bootstrap)] - static_assert_size!(TraitItemKind<'_>, 48); - #[cfg(not(bootstrap))] static_assert_size!(TraitItemKind<'_>, 40); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); + // tidy-alphabetical-end +} + +fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug { + struct DebugFn<F>(F); + impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(fmt) + } + } + DebugFn(f) } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 03bcaa69468..5d05adfb556 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -1,14 +1,21 @@ use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_ID}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; use rustc_span::{def_id::DefPathHash, HashStableContext}; -use std::fmt; +use std::fmt::{self, Debug}; -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Encodable, Decodable)] pub struct OwnerId { pub def_id: LocalDefId, } +impl Debug for OwnerId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Example: DefId(0:1 ~ aa[7697]::{use#0}) + Debug::fmt(&self.def_id, f) + } +} + impl From<OwnerId> for HirId { fn from(owner: OwnerId) -> HirId { HirId { owner, local_id: ItemLocalId::from_u32(0) } @@ -60,7 +67,7 @@ impl<CTX: HashStableContext> ToStableHashKey<CTX> for OwnerId { /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Encodable, Decodable, HashStable_Generic)] #[rustc_pass_by_value] pub struct HirId { @@ -68,6 +75,14 @@ pub struct HirId { pub local_id: ItemLocalId, } +impl Debug for HirId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Example: HirId(DefId(0:1 ~ aa[7697]::{use#0}).10) + // Don't use debug_tuple to always keep this on one line. + write!(f, "HirId({:?}.{:?})", self.owner, self.local_id) + } +} + impl HirId { /// Signal local id which should never be used. pub const INVALID: HirId = diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 938ace2c785..6c475b659eb 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -809,7 +809,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { match typ.kind { TyKind::Slice(ref ty) => visitor.visit_ty(ty), TyKind::Ptr(ref mutable_type) => visitor.visit_ty(mutable_type.ty), - TyKind::Rptr(ref lifetime, ref mutable_type) => { + TyKind::Ref(ref lifetime, ref mutable_type) => { visitor.visit_lifetime(lifetime); visitor.visit_ty(mutable_type.ty) } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 038509031b1..3474fab34f0 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -146,7 +146,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> { } language_item_table! { -// Variant name, Name, Method name, Target Generic requirements; +// Variant name, Name, Getter method name, Target Generic requirements; Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0); Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). @@ -232,6 +232,7 @@ language_item_table! { // is required to define it somewhere. Additionally, there are restrictions on crates that use // a weak lang item, but do not have it defined. Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0); + PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0); PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None; PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None; ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None; @@ -239,7 +240,7 @@ language_item_table! { PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None; PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None; PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None; - PanicNoUnwind, sym::panic_no_unwind, panic_no_unwind, Target::Fn, GenericRequirement::Exact(0); + PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0); /// libstd panic entry point. Necessary for const eval to be able to catch it BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index c29a3afd7fb..d7ab942665b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2626,7 +2626,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let e = self .tcx() .sess - .delay_span_bug(path.span, "path with `Res:Err` but no error emitted"); + .delay_span_bug(path.span, "path with `Res::Err` but no error emitted"); self.set_tainted_by_errors(e); self.tcx().ty_error_with_guaranteed(e) } @@ -2657,7 +2657,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Ptr(ref mt) => { tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) } - hir::TyKind::Rptr(ref region, ref mt) => { + hir::TyKind::Ref(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); debug!(?r); let t = self.ast_ty_to_ty_inner(mt.ty, true, false); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a714663741b..28cd18bbb8e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,8 +1,8 @@ use crate::check::intrinsicck::InlineAsmCtxt; use crate::errors::LinkageType; -use super::compare_method::check_type_bounds; -use super::compare_method::{compare_impl_method, compare_ty_impl}; +use super::compare_impl_item::check_type_bounds; +use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; use super::*; use rustc_attr as attr; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan}; @@ -468,7 +468,7 @@ fn check_opaque_meets_bounds<'tcx>( // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors( + let _ = infcx.check_region_obligations_and_report_errors( defining_use_anchor, &outlives_environment, ); @@ -774,7 +774,7 @@ fn check_impl_items_against_trait<'tcx>( let impl_item_full = tcx.hir().impl_item(impl_item.id); match impl_item_full.kind { hir::ImplItemKind::Const(..) => { - let _ = tcx.compare_assoc_const_impl_item_with_trait_item(( + let _ = tcx.compare_impl_const(( impl_item.id.owner_id.def_id, ty_impl_item.trait_item_def_id.unwrap(), )); @@ -791,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>( } hir::ImplItemKind::Type(impl_ty) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); - compare_ty_impl( + compare_impl_ty( tcx, &ty_impl_item, impl_ty.span, @@ -1060,10 +1060,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) if adt.variants().len() != 1 { bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did()); - if adt.variants().is_empty() { - // Don't bother checking the fields. No variants (and thus no fields) exist. - return; - } + // Don't bother checking the fields. + return; } // For each field, figure out if it's known to be a ZST and align(1), with "known" diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index c6bda9b4641..a767338ab85 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -34,7 +34,7 @@ use std::iter; /// - `impl_m_span`: span to use for reporting errors /// - `trait_m`: the method in the trait /// - `impl_trait_ref`: the TraitRef corresponding to the trait implementation -pub(crate) fn compare_impl_method<'tcx>( +pub(super) fn compare_impl_method<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, trait_m: &ty::AssocItem, @@ -71,7 +71,7 @@ pub(crate) fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_predicate_entailment( + if let Err(_) = compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -150,7 +150,7 @@ pub(crate) fn compare_impl_method<'tcx>( /// Finally we register each of these predicates as an obligation and check that /// they hold. #[instrument(level = "debug", skip(tcx, impl_m_span, impl_trait_ref))] -fn compare_predicate_entailment<'tcx>( +fn compare_method_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, impl_m: &ty::AssocItem, impl_m_span: Span, @@ -337,7 +337,7 @@ fn compare_predicate_entailment<'tcx>( if !errors.is_empty() { match check_implied_wf { CheckImpliedWfMode::Check => { - return compare_predicate_entailment( + return compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -374,7 +374,7 @@ fn compare_predicate_entailment<'tcx>( // becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors` match check_implied_wf { CheckImpliedWfMode::Check => { - return compare_predicate_entailment( + return compare_method_predicate_entailment( tcx, impl_m, impl_m_span, @@ -407,7 +407,7 @@ enum CheckImpliedWfMode { /// re-check with `Skip`, and emit a lint if it succeeds. Check, /// Skips checking implied well-formedness of the impl method, but will emit - /// a lint if the `compare_predicate_entailment` succeeded. This means that + /// a lint if the `compare_method_predicate_entailment` succeeded. This means that /// the reason that we had failed earlier during `Check` was due to the impl /// having stronger requirements than the trait. Skip, @@ -441,8 +441,41 @@ fn compare_asyncness<'tcx>( Ok(()) } +/// Given a method def-id in an impl, compare the method signature of the impl +/// against the trait that it's implementing. In doing so, infer the hidden types +/// that this method's signature provides to satisfy each return-position `impl Trait` +/// in the trait signature. +/// +/// The method is also responsible for making sure that the hidden types for each +/// RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer +/// `impl Trait = Foo`, that `Foo: Trait` holds. +/// +/// For example, given the sample code: +/// +/// ``` +/// #![feature(return_position_impl_trait_in_trait)] +/// +/// use std::ops::Deref; +/// +/// trait Foo { +/// fn bar() -> impl Deref<Target = impl Sized>; +/// // ^- RPITIT #1 ^- RPITIT #2 +/// } +/// +/// impl Foo for () { +/// fn bar() -> Box<String> { Box::new(String::new()) } +/// } +/// ``` +/// +/// The hidden types for the RPITITs in `bar` would be inferred to: +/// * `impl Deref` (RPITIT #1) = `Box<String>` +/// * `impl Sized` (RPITIT #2) = `String` +/// +/// The relationship between these two types is straightforward in this case, but +/// may be more tenuously connected via other `impl`s and normalization rules for +/// cases of more complicated nested RPITITs. #[instrument(skip(tcx), level = "debug", ret)] -pub fn collect_trait_impl_trait_tys<'tcx>( +pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> { @@ -550,13 +583,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>( // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from - // `compare_predicate_entailment`. + // `compare_method_predicate_entailment`. match ocx.eq(&cause, param_env, trait_fty, impl_fty) { Ok(()) => {} Err(terr) => { - // This function gets called during `compare_predicate_entailment` when normalizing a + // This function gets called during `compare_method_predicate_entailment` when normalizing a // signature that contains RPITIT. When the method signatures don't match, we have to - // emit an error now because `compare_predicate_entailment` will not report the error + // emit an error now because `compare_method_predicate_entailment` will not report the error // when normalization fails. let emitted = report_trait_method_mismatch( infcx, @@ -589,7 +622,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>( infcx.check_region_obligations_and_report_errors( impl_m.def_id.expect_local(), &outlives_environment, - ); + )?; let mut collected_tys = FxHashMap::default(); for (def_id, (ty, substs)) in collector.types { @@ -1516,8 +1549,8 @@ fn compare_generic_param_kinds<'tcx>( Ok(()) } -/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead -pub(crate) fn raw_compare_const_impl( +/// Use `tcx.compare_impl_const` instead +pub(super) fn compare_impl_const_raw( tcx: TyCtxt<'_>, (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId), ) -> Result<(), ErrorGuaranteed> { @@ -1617,13 +1650,13 @@ pub(crate) fn raw_compare_const_impl( return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None)); } - // FIXME return `ErrorReported` if region obligations error? let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment); + infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; + Ok(()) } -pub(crate) fn compare_ty_impl<'tcx>( +pub(super) fn compare_impl_ty<'tcx>( tcx: TyCtxt<'tcx>, impl_ty: &ty::AssocItem, impl_ty_span: Span, @@ -1645,7 +1678,7 @@ pub(crate) fn compare_ty_impl<'tcx>( })(); } -/// The equivalent of [compare_predicate_entailment], but for associated types +/// The equivalent of [compare_method_predicate_entailment], but for associated types /// instead of associated functions. fn compare_type_predicate_entailment<'tcx>( tcx: TyCtxt<'tcx>, @@ -1730,7 +1763,7 @@ fn compare_type_predicate_entailment<'tcx>( infcx.check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, - ); + )?; Ok(()) } @@ -1749,7 +1782,7 @@ fn compare_type_predicate_entailment<'tcx>( /// from the impl could be overridden). We also can't normalize generic /// associated types (yet) because they contain bound parameters. #[instrument(level = "debug", skip(tcx))] -pub fn check_type_bounds<'tcx>( +pub(super) fn check_type_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_ty: &ty::AssocItem, impl_ty: &ty::AssocItem, @@ -1944,7 +1977,7 @@ pub fn check_type_bounds<'tcx>( infcx.check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, - ); + )?; let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); for (key, value) in constraints { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index ed2aed293a7..382c3f52945 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -63,7 +63,7 @@ a type parameter). */ mod check; -mod compare_method; +mod compare_impl_item; pub mod dropck; pub mod intrinsic; pub mod intrinsicck; @@ -94,7 +94,7 @@ use std::num::NonZeroU32; use crate::require_c_abi_if_c_variadic; use crate::util::common::indenter; -use self::compare_method::collect_trait_impl_trait_tys; +use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys; use self::region::region_scope_tree; pub fn provide(providers: &mut Providers) { @@ -103,8 +103,8 @@ pub fn provide(providers: &mut Providers) { adt_destructor, check_mod_item_types, region_scope_tree, - collect_trait_impl_trait_tys, - compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl, + collect_return_position_impl_trait_in_trait_tys, + compare_impl_const: compare_impl_item::compare_impl_const_raw, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index aedc736b023..0d1aa39c5d9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -115,7 +115,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( let outlives_environment = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); + let _ = infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { @@ -291,7 +291,7 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) { // Do some rudimentary sanity checking to avoid an ICE later (issue #83471). if let Some(hir::FnSig { decl, span, .. }) = method_sig { if let [self_ty, _] = decl.inputs { - if !matches!(self_ty.kind, hir::TyKind::Rptr(_, _)) { + if !matches!(self_ty.kind, hir::TyKind::Ref(_, _)) { tcx.sess .struct_span_err( self_ty.span, @@ -410,10 +410,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe tcx, param_env, item_hir_id, - tcx.explicit_item_bounds(item_def_id) - .iter() - .copied() - .collect::<Vec<_>>(), + tcx.explicit_item_bounds(item_def_id).to_vec(), &FxIndexSet::default(), gat_def_id.def_id, gat_generics, diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 2790d91572b..bfedf63da97 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -325,7 +325,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -565,7 +565,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c6d4aeefc80..e8b3f139623 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -53,7 +53,7 @@ fn do_orphan_check_impl<'tcx>( sp, item.span, tr.path.span, - trait_ref.self_ty(), + trait_ref, impl_.self_ty.span, &impl_.generics, err, @@ -154,11 +154,12 @@ fn emit_orphan_check_error<'tcx>( sp: Span, full_impl_span: Span, trait_span: Span, - self_ty: Ty<'tcx>, + trait_ref: ty::TraitRef<'tcx>, self_ty_span: Span, generics: &hir::Generics<'tcx>, err: traits::OrphanCheckErr<'tcx>, ) -> Result<!, ErrorGuaranteed> { + let self_ty = trait_ref.self_ty(); Err(match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { let msg = match self_ty.kind() { @@ -187,7 +188,14 @@ fn emit_orphan_check_error<'tcx>( let msg = |ty: &str, postfix: &str| { format!("{ty} is not defined in the current crate{postfix}") }; - let this = |name: &str| msg("this", &format!(" because {name} are always foreign")); + + let this = |name: &str| { + if !trait_ref.def_id.is_local() && !is_target_ty { + msg("this", &format!(" because this is a foreign trait")) + } else { + msg("this", &format!(" because {name} are always foreign")) + } + }; let msg = match &ty.kind() { ty::Slice(_) => this("slices"), ty::Array(..) => this("arrays"), diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b7d599f57fd..1ff7429e415 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -24,6 +24,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::hir::nested_filter; use rustc_middle::ty::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -31,7 +33,9 @@ use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyC use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use rustc_target::spec::abi; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; +use rustc_trait_selection::traits::ObligationCtxt; use std::iter; mod generics_of; @@ -1059,7 +1063,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _)) } Tup(tys) => tys.iter().any(is_suggestable_infer_ty), - Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), + Ptr(mut_ty) | Ref(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty), OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args), Path(hir::QPath::TypeRelative(ty, segment)) => { is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args) @@ -1224,7 +1228,17 @@ fn infer_return_ty_for_fn_sig<'tcx>( // to prevent the user from getting a papercut while trying to use the unique closure // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); - diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html"); + diag.note( + "for more information on `Fn` traits and closure types, see \ + https://doc.rust-lang.org/book/ch13-01-closures.html", + ); + } else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) { + diag.span_suggestion( + ty.span, + "replace with an appropriate return type", + format!("impl Iterator<Item = {}>", i_ty), + Applicability::MachineApplicable, + ); } diag.emit(); @@ -1242,6 +1256,51 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } +fn suggest_impl_iterator<'tcx>( + tcx: TyCtxt<'tcx>, + ret_ty: Ty<'tcx>, + span: Span, + hir_id: hir::HirId, + def_id: LocalDefId, +) -> Option<Ty<'tcx>> { + let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; }; + let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; }; + if !tcx + .infer_ctxt() + .build() + .type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id)) + .must_apply_modulo_regions() + { + return None; + } + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new_in_snapshot(&infcx); + // Find the type of `Iterator::Item`. + let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }; + let ty_var = infcx.next_ty_var(origin); + let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection( + ty::ProjectionPredicate { + projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())), + term: ty_var.into(), + }, + ))); + // Add `<ret_ty as Iterator>::Item = _` obligation. + ocx.register_obligation(crate::traits::Obligation::misc( + tcx, + span, + hir_id, + tcx.param_env(def_id), + projection, + )); + if ocx.select_where_possible().is_empty() + && let item_ty = infcx.resolve_vars_if_possible(ty_var) + && item_ty.is_suggestable(tcx, false) + { + return Some(item_ty); + } + None +} + fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id.expect_local()); diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index b63a8ef698d..fb519d6731d 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -617,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { LifetimeName::Error => {} } } - hir::TyKind::Rptr(ref lifetime_ref, ref mt) => { + hir::TyKind::Ref(ref lifetime_ref, ref mt) => { self.visit_lifetime(lifetime_ref); let scope = Scope::ObjectLifetimeDefault { lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(), diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index b678990f94e..4bd55a54831 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -5,6 +5,7 @@ use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::{HirId, Node}; use rustc_middle::hir::nested_filter; +use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; @@ -907,10 +908,10 @@ fn infer_placeholder_type<'a>( Applicability::MachineApplicable, ); } else { - err.span_note( + with_forced_trimmed_paths!(err.span_note( tcx.hir().body(body_id).value.span, - &format!("however, the inferred type `{}` cannot be named", ty), - ); + &format!("however, the inferred type `{ty}` cannot be named"), + )); } } @@ -931,10 +932,10 @@ fn infer_placeholder_type<'a>( Applicability::MaybeIncorrect, ); } else { - diag.span_note( + with_forced_trimmed_paths!(diag.span_note( tcx.hir().body(body_id).value.span, - &format!("however, the inferred type `{}` cannot be named", ty), - ); + &format!("however, the inferred type `{ty}` cannot be named"), + )); } } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index b60fc276178..1aae9e0bd20 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -81,7 +81,6 @@ use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt}; -use tracing::instrument; pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { if let Some(node) = parent_specialization_node(tcx, impl_def_id) { @@ -182,7 +181,7 @@ fn get_impl_substs( let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let _ = infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { let span = tcx.def_span(impl1_def_id); tcx.sess.emit_err(SubstsOnOverriddenImpl { span }); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 29a6902ccb0..24a67cc14c4 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -307,7 +307,7 @@ impl<'a> State<'a> { self.word("*"); self.print_mt(mt, true); } - hir::TyKind::Rptr(ref lifetime, ref mt) => { + hir::TyKind::Ref(ref lifetime, ref mt) => { self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index af14ee08a99..829913d278d 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -241,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if let Some(ok) = self.lookup_method_in_trait( - call_expr.span, + self.misc(call_expr.span), method_name, trait_def_id, adjusted_ty, diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index b0cd4a16e98..3fb14e31ea1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -171,6 +171,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Just ignore error types. if a.references_error() || b.references_error() { + // Best-effort try to unify these types -- we're already on the error path, + // so this will have the side-effect of making sure we have no ambiguities + // due to `[type error]` and `_` not coercing together. + let _ = self.commit_if_ok(|_| self.at(&self.cause, self.param_env).eq(a, b)); return success(vec![], self.fcx.tcx.ty_error(), vec![]); } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index e68bd1297c8..1360383a75a 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,5 +1,6 @@ use crate::FnCtxt; use rustc_ast::util::parser::PREC_POSTFIX; +use rustc_errors::MultiSpan; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -30,14 +31,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, expected: Ty<'tcx>, expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, - _error: Option<TypeError<'tcx>>, + error: Option<TypeError<'tcx>>, ) { if expr_ty == expected { return; } + self.annotate_alternative_method_deref(err, expr, error); + // Use `||` to give these suggestions a precedence let _ = self.suggest_missing_parentheses(err, expr) + || self.suggest_remove_last_method_call(err, expr, expected) || self.suggest_associated_const(err, expr, expected) || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) || self.suggest_option_to_bool(err, expr, expr_ty, expected) @@ -70,6 +74,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_type_is_not_clone(err, expected, expr_ty, expr); self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); + self.check_for_range_as_method_call(err, expr, expr_ty, expected); } /// Requires that the two types unify, and prints an error message if @@ -315,6 +320,162 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn annotate_alternative_method_deref( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + error: Option<TypeError<'tcx>>, + ) { + let parent = self.tcx.hir().get_parent_node(expr.hir_id); + let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;}; + let Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Assign(lhs, rhs, _), .. + })) = self.tcx.hir().find(parent) else {return; }; + if rhs.hir_id != expr.hir_id || expected.is_closure() { + return; + } + let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; }; + let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { return; }; + let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; }; + + let Ok(pick) = self + .probe_for_name( + probe::Mode::MethodCall, + path.ident, + probe::IsSuggestion(true), + self_ty, + deref.hir_id, + probe::ProbeScope::TraitsInScope, + ) else { + return; + }; + let in_scope_methods = self.probe_for_name_many( + probe::Mode::MethodCall, + path.ident, + probe::IsSuggestion(true), + self_ty, + deref.hir_id, + probe::ProbeScope::TraitsInScope, + ); + let other_methods_in_scope: Vec<_> = + in_scope_methods.iter().filter(|c| c.item.def_id != pick.item.def_id).collect(); + + let all_methods = self.probe_for_name_many( + probe::Mode::MethodCall, + path.ident, + probe::IsSuggestion(true), + self_ty, + deref.hir_id, + probe::ProbeScope::AllTraits, + ); + let suggestions: Vec<_> = all_methods + .into_iter() + .filter(|c| c.item.def_id != pick.item.def_id) + .map(|c| { + let m = c.item; + let substs = ty::InternalSubsts::for_item(self.tcx, m.def_id, |param, _| { + self.var_for_def(deref.span, param) + }); + vec![ + ( + deref.span.until(base.span), + format!( + "{}({}", + with_no_trimmed_paths!( + self.tcx.def_path_str_with_substs(m.def_id, substs,) + ), + match self.tcx.fn_sig(m.def_id).input(0).skip_binder().kind() { + ty::Ref(_, _, hir::Mutability::Mut) => "&mut ", + ty::Ref(_, _, _) => "&", + _ => "", + }, + ), + ), + match &args[..] { + [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()), + [first, ..] => (base.span.between(first.span), ", ".to_string()), + }, + ] + }) + .collect(); + if suggestions.is_empty() { + return; + } + let mut path_span: MultiSpan = path.ident.span.into(); + path_span.push_span_label( + path.ident.span, + with_no_trimmed_paths!(format!( + "refers to `{}`", + self.tcx.def_path_str(pick.item.def_id), + )), + ); + let container_id = pick.item.container_id(self.tcx); + let container = with_no_trimmed_paths!(self.tcx.def_path_str(container_id)); + for def_id in pick.import_ids { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + path_span.push_span_label( + self.tcx.hir().span(hir_id), + format!("`{container}` imported here"), + ); + } + let tail = with_no_trimmed_paths!(match &other_methods_in_scope[..] { + [] => return, + [candidate] => format!( + "the method of the same name on {} `{}`", + match candidate.kind { + probe::CandidateKind::InherentImplCandidate(..) => "the inherent impl for", + _ => "trait", + }, + self.tcx.def_path_str(candidate.item.container_id(self.tcx)) + ), + [.., last] if other_methods_in_scope.len() < 5 => { + format!( + "the methods of the same name on {} and `{}`", + other_methods_in_scope[..other_methods_in_scope.len() - 1] + .iter() + .map(|c| format!( + "`{}`", + self.tcx.def_path_str(c.item.container_id(self.tcx)) + )) + .collect::<Vec<String>>() + .join(", "), + self.tcx.def_path_str(last.item.container_id(self.tcx)) + ) + } + _ => format!( + "the methods of the same name on {} other traits", + other_methods_in_scope.len() + ), + }); + err.span_note( + path_span, + &format!( + "the `{}` call is resolved to the method in `{container}`, shadowing {tail}", + path.ident, + ), + ); + if suggestions.len() > other_methods_in_scope.len() { + err.note(&format!( + "additionally, there are {} other available methods that aren't in scope", + suggestions.len() - other_methods_in_scope.len() + )); + } + err.multipart_suggestions( + &format!( + "you might have meant to call {}; you can use the fully-qualified path to call {} \ + explicitly", + if suggestions.len() == 1 { + "the other method" + } else { + "one of the other methods" + }, + if suggestions.len() == 1 { "it" } else { "one of them" }, + ), + suggestions, + Applicability::MaybeIncorrect, + ); + } + /// If the expected type is an enum (Issue #55250) with any variants whose /// sole field is of the found type, suggest such variants. (Issue #42764) fn suggest_compatible_variants( @@ -1447,4 +1608,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => false, } } + + /// Identify when the user has written `foo..bar()` instead of `foo.bar()`. + pub fn check_for_range_as_method_call( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + checked_ty: Ty<'tcx>, + expected_ty: Ty<'tcx>, + ) { + if !hir::is_range_literal(expr) { + return; + } + let hir::ExprKind::Struct( + hir::QPath::LangItem(LangItem::Range, ..), + [start, end], + _, + ) = expr.kind else { return; }; + let parent = self.tcx.hir().get_parent_node(expr.hir_id); + if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) { + // Ignore `Foo { field: a..Default::default() }` + return; + } + let mut expr = end.expr; + while let hir::ExprKind::MethodCall(_, rcvr, ..) = expr.kind { + // Getting to the root receiver and asserting it is a fn call let's us ignore cases in + // `src/test/ui/methods/issues/issue-90315.stderr`. + expr = rcvr; + } + let hir::ExprKind::Call(method_name, _) = expr.kind else { return; }; + let ty::Adt(adt, _) = checked_ty.kind() else { return; }; + if self.tcx.lang_items().range_struct() != Some(adt.did()) { + return; + } + if let ty::Adt(adt, _) = expected_ty.kind() + && self.tcx.lang_items().range_struct() == Some(adt.did()) + { + return; + } + // Check if start has method named end. + let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else { return; }; + let [hir::PathSegment { ident, .. }] = p.segments else { return; }; + let self_ty = self.typeck_results.borrow().expr_ty(start.expr); + let Ok(_pick) = self.probe_for_name( + probe::Mode::MethodCall, + *ident, + probe::IsSuggestion(true), + self_ty, + expr.hir_id, + probe::ProbeScope::AllTraits, + ) else { return; }; + let mut sugg = "."; + let mut span = start.expr.span.between(end.expr.span); + if span.lo() + BytePos(2) == span.hi() { + // There's no space between the start, the range op and the end, suggest removal which + // will be more noticeable than the replacement of `..` with `.`. + span = span.with_lo(span.lo() + BytePos(1)); + sugg = ""; + } + err.span_suggestion_verbose( + span, + "you likely meant to write a method call instead of a range", + sugg, + Applicability::MachineApplicable, + ); + } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ae641b26eee..b8b4e873663 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0614, "type `{oprnd_t}` cannot be dereferenced", ); - let sp = tcx.sess.source_map().start_point(expr.span); + let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 877680053f0..d342d96a10f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1307,7 +1307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the initializer. if let Some(ref init) = decl.init { let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init); - self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty); } // Does the expected pattern type originate from an expression and what is the span? @@ -1322,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the pattern. Override if necessary to avoid knock-on errors. self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr); let pat_ty = self.node_ty(decl.pat.hir_id); - self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); if let Some(blk) = decl.els { let previous_diverges = self.diverges.get(); @@ -1627,14 +1627,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, hir_id: hir::HirId, pat: &'tcx hir::Pat<'tcx>, - decl_ty: Ty<'tcx>, ty: Ty<'tcx>, ) { if ty.references_error() { // Override the types everywhere with `err()` to avoid knock on errors. - self.write_ty(hir_id, ty); - self.write_ty(pat.hir_id, ty); - let local_ty = LocalTy { decl_ty, revealed_ty: ty }; + let err = self.tcx.ty_error(); + self.write_ty(hir_id, err); + self.write_ty(pat.hir_id, err); + let local_ty = LocalTy { decl_ty: err, revealed_ty: err }; self.locals.borrow_mut().insert(hir_id, local_ty); self.locals.borrow_mut().insert(pat.hir_id, local_ty); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index efec0244633..322e11c978f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::{ TypeVisitable, }; use rustc_session::errors::ExprParenthesesNeeded; +use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; @@ -329,6 +330,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + pub fn suggest_remove_last_method_call( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'tcx>, + expected: Ty<'tcx>, + ) -> bool { + if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, &[], _) = expr.kind && + let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) && + self.can_coerce(recv_ty, expected) { + let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) { + expr.span.with_lo(recv_span.hi()) + } else { + expr.span.with_lo(method.span.lo() - rustc_span::BytePos(1)) + }; + err.span_suggestion_verbose( + span, + "try removing the method call", + "", + Applicability::MachineApplicable, + ); + return true; + } + false + } + pub fn suggest_deref_ref_or_into( &self, err: &mut Diagnostic, @@ -948,7 +974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err: &mut Diagnostic, expr: &hir::Expr<'_>, ) -> bool { - let sp = self.tcx.sess.source_map().start_point(expr.span); + let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); @@ -1234,6 +1260,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); true } + ExprKind::Lit(Spanned { + node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed), + span, + }) => { + let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; }; + if !(snippet.starts_with("0x") || snippet.starts_with("0X")) { + return false; + } + if snippet.len() <= 5 || !snippet.is_char_boundary(snippet.len() - 3) { + return false; + } + let (_, suffix) = snippet.split_at(snippet.len() - 3); + let value = match suffix { + "f32" => (lit - 0xf32) / (16 * 16 * 16), + "f64" => (lit - 0xf64) / (16 * 16 * 16), + _ => return false, + }; + err.span_suggestions( + expr.span, + "rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float", + [format!("0x{value:X} as {suffix}"), format!("{value}_{suffix}")], + Applicability::MaybeIncorrect, + ); + true + } _ => false, } } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index fddb8a458a7..b9b27e8627a 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -11,7 +11,7 @@ pub use self::suggest::SelfSource; pub use self::MethodError::*; use crate::errors::OpMethodGenericParams; -use crate::{Expectation, FnCtxt}; +use crate::FnCtxt; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; @@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(super) fn obligation_for_method( &self, - span: Span, + cause: ObligationCause<'tcx>, trait_def_id: DefId, self_ty: Ty<'tcx>, opt_input_types: Option<&[Ty<'tcx>]>, @@ -282,71 +282,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.var_for_def(span, param) - }); - - let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs); - - // Construct an obligation - let poly_trait_ref = ty::Binder::dummy(trait_ref); - ( - traits::Obligation::misc( - self.tcx, - span, - self.body_id, - self.param_env, - poly_trait_ref.without_const(), - ), - substs, - ) - } - - pub(super) fn obligation_for_op_method( - &self, - span: Span, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - opt_input_type: Option<Ty<'tcx>>, - opt_input_expr: Option<&'tcx hir::Expr<'tcx>>, - expected: Expectation<'tcx>, - ) -> (traits::Obligation<'tcx, ty::Predicate<'tcx>>, &'tcx ty::List<ty::subst::GenericArg<'tcx>>) - { - // Construct a trait-reference `self_ty : Trait<input_tys>` - let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { - match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} - GenericParamDefKind::Type { .. } => { - if param.index == 0 { - return self_ty.into(); - } else if let Some(input_type) = opt_input_type { - return input_type.into(); - } - } - } - self.var_for_def(span, param) + self.var_for_def(cause.span, param) }); let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs); // Construct an obligation let poly_trait_ref = ty::Binder::dummy(trait_ref); - let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty)); - ( traits::Obligation::new( self.tcx, - traits::ObligationCause::new( - span, - self.body_id, - traits::BinOp { - rhs_span: opt_input_expr.map(|expr| expr.span), - is_lit: opt_input_expr - .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_ty, - }, - ), + cause, self.param_env, - poly_trait_ref, + poly_trait_ref.without_const(), ), substs, ) @@ -357,55 +305,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// In particular, it doesn't really do any probing: it simply constructs /// an obligation for a particular trait with the given self type and checks /// whether that trait is implemented. - #[instrument(level = "debug", skip(self, span))] + #[instrument(level = "debug", skip(self))] pub(super) fn lookup_method_in_trait( &self, - span: Span, + cause: ObligationCause<'tcx>, m_name: Ident, trait_def_id: DefId, self_ty: Ty<'tcx>, opt_input_types: Option<&[Ty<'tcx>]>, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { let (obligation, substs) = - self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types); - self.construct_obligation_for_trait( - span, - m_name, - trait_def_id, - obligation, - substs, - None, - false, - ) - } - - pub(super) fn lookup_op_method_in_trait( - &self, - span: Span, - m_name: Ident, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - opt_input_type: Option<Ty<'tcx>>, - opt_input_expr: Option<&'tcx hir::Expr<'tcx>>, - expected: Expectation<'tcx>, - ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { - let (obligation, substs) = self.obligation_for_op_method( - span, - trait_def_id, - self_ty, - opt_input_type, - opt_input_expr, - expected, - ); - self.construct_obligation_for_trait( - span, - m_name, - trait_def_id, - obligation, - substs, - opt_input_expr, - true, - ) + self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types); + self.construct_obligation_for_trait(m_name, trait_def_id, obligation, substs) } // FIXME(#18741): it seems likely that we can consolidate some of this @@ -413,13 +324,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // of this method is basically the same as confirmation. fn construct_obligation_for_trait( &self, - span: Span, m_name: Ident, trait_def_id: DefId, obligation: traits::PredicateObligation<'tcx>, substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>, - opt_input_expr: Option<&'tcx hir::Expr<'tcx>>, - is_op: bool, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { debug!(?obligation); @@ -435,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; let Some(method_item) = self.associated_value(trait_def_id, m_name) else { tcx.sess.delay_span_bug( - span, + obligation.cause.span, "operator trait does not have corresponding operator method", ); return None; @@ -461,24 +369,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // with bound regions. let fn_sig = tcx.bound_fn_sig(def_id); let fn_sig = fn_sig.subst(self.tcx, substs); - let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig); - - let cause = if is_op { - ObligationCause::new( - span, - self.body_id, - traits::BinOp { - rhs_span: opt_input_expr.map(|expr| expr.span), - is_lit: opt_input_expr - .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_ty: None, - }, - ) - } else { - traits::ObligationCause::misc(span, self.body_id) - }; + let fn_sig = + self.replace_bound_vars_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig); - let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(fn_sig); + let InferOk { value, obligations: o } = + self.at(&obligation.cause, self.param_env).normalize(fn_sig); let fn_sig = { obligations.extend(o); value @@ -494,7 +389,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // any late-bound regions appearing in its bounds. let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); - let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(bounds); + let InferOk { value, obligations: o } = + self.at(&obligation.cause, self.param_env).normalize(bounds); let bounds = { obligations.extend(o); value @@ -502,7 +398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(!bounds.has_escaping_bound_vars()); - let predicates_cause = cause.clone(); + let predicates_cause = obligation.cause.clone(); obligations.extend(traits::predicates_for_generics( move |_, _| predicates_cause.clone(), self.param_env, @@ -517,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); obligations.push(traits::Obligation::new( tcx, - cause, + obligation.cause, self.param_env, ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())), )); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index b9e7830bf07..1afaae0e020 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { } #[derive(Debug, Clone)] -struct Candidate<'tcx> { +pub(crate) struct Candidate<'tcx> { // Candidates are (I'm not quite sure, but they are mostly) basically // some metadata on top of a `ty::AssocItem` (without substs). // @@ -131,13 +131,13 @@ struct Candidate<'tcx> { // if `T: Sized`. xform_self_ty: Ty<'tcx>, xform_ret_ty: Option<Ty<'tcx>>, - item: ty::AssocItem, - kind: CandidateKind<'tcx>, - import_ids: SmallVec<[LocalDefId; 1]>, + pub(crate) item: ty::AssocItem, + pub(crate) kind: CandidateKind<'tcx>, + pub(crate) import_ids: SmallVec<[LocalDefId; 1]>, } #[derive(Debug, Clone)] -enum CandidateKind<'tcx> { +pub(crate) enum CandidateKind<'tcx> { InherentImplCandidate( SubstsRef<'tcx>, // Normalize obligations @@ -322,6 +322,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } + #[instrument(level = "debug", skip(self))] + pub(crate) fn probe_for_name_many( + &self, + mode: Mode, + item_name: Ident, + is_suggestion: IsSuggestion, + self_ty: Ty<'tcx>, + scope_expr_id: hir::HirId, + scope: ProbeScope, + ) -> Vec<Candidate<'tcx>> { + self.probe_op( + item_name.span, + mode, + Some(item_name), + None, + is_suggestion, + self_ty, + scope_expr_id, + scope, + |probe_cx| { + Ok(probe_cx + .inherent_candidates + .into_iter() + .chain(probe_cx.extension_candidates) + .collect()) + }, + ) + .unwrap() + } + fn probe_op<OP, R>( &'a self, span: Span, @@ -943,6 +973,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); } else { debug_assert!(self.tcx.is_trait(trait_def_id)); + if self.tcx.trait_is_auto(trait_def_id) { + return; + } for item in self.impl_or_trait_item(trait_def_id) { // Check whether `trait_def_id` defines a method with suitable name. if !self.has_applicable_self(&item) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7c5a9a333fe..7053c180685 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -339,7 +339,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, item_name, rcvr_ty, cal, span, ); } - if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) { + if let Some(span) = + tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None)) + { err.span_suggestion( span.shrink_to_lo(), "you are looking for the module in `std`, not the primitive type", @@ -2306,6 +2308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => false, } }) && (type_is_local || info.def_id.is_local()) + && !self.tcx.trait_is_auto(info.def_id) && self .associated_value(info.def_id, item_name) .filter(|item| { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 9f0d175c4c6..78cea1f4d8d 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -12,14 +12,16 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, }; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable}; +use rustc_middle::ty::{ + self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable, +}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::FulfillmentError; +use rustc_trait_selection::traits::{self, FulfillmentError}; use rustc_type_ir::sty::TyKind::*; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -48,8 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_deref_ty, - Some(rhs_ty), - Some(rhs), + Some((rhs, rhs_ty)), Op::Binary(op, IsAssign::Yes), expected, ) @@ -60,8 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs), + Some((rhs, rhs_ty)), Op::Binary(op, IsAssign::Yes), expected, ) @@ -248,8 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let result = self.lookup_op_method( lhs_ty, - Some(rhs_ty_var), - Some(rhs_expr), + Some((rhs_expr, rhs_ty_var)), Op::Binary(op, is_assign), expected, ); @@ -382,8 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self .lookup_op_method( lhs_deref_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -410,8 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_compatible = |lhs_ty, rhs_ty| { self.lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -471,8 +468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let errors = self .lookup_op_method( lhs_ty, - Some(rhs_ty), - Some(rhs_expr), + Some((rhs_expr, rhs_ty)), Op::Binary(op, is_assign), expected, ) @@ -492,6 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(output_def_id) = output_def_id && let Some(trait_def_id) = trait_def_id && self.tcx.parent(output_def_id) == trait_def_id + && output_ty.is_suggestable(self.tcx, false) { Some(("Output", *output_ty)) } else { @@ -625,7 +622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Expectation<'tcx>, ) -> Ty<'tcx> { assert!(op.is_by_value()); - match self.lookup_op_method(operand_ty, None, None, Op::Unary(op, ex.span), expected) { + match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) { Ok(method) => { self.write_method_call(ex.hir_id, method); method.sig.output() @@ -660,7 +657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let sp = self.tcx.sess.source_map().start_point(ex.span); + let sp = self.tcx.sess.source_map().start_point(ex.span).with_parent(None); if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { @@ -712,8 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn lookup_op_method( &self, lhs_ty: Ty<'tcx>, - other_ty: Option<Ty<'tcx>>, - other_ty_expr: Option<&'tcx hir::Expr<'tcx>>, + opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>, op: Op, expected: Expectation<'tcx>, ) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> { @@ -742,20 +738,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Op::Unary(..) => 0, }, ) { + self.tcx + .sess + .delay_span_bug(span, "operator didn't have the right number of generic args"); return Err(vec![]); } let opname = Ident::with_dummy_span(opname); + let input_types = + opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default(); + let cause = self.cause( + span, + traits::BinOp { + rhs_span: opt_rhs.map(|(expr, _)| expr.span), + is_lit: opt_rhs + .map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))), + output_ty: expected.only_has_type(self), + }, + ); + let method = trait_did.and_then(|trait_did| { - self.lookup_op_method_in_trait( - span, - opname, - trait_did, - lhs_ty, - other_ty, - other_ty_expr, - expected, - ) + self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types)) }); match (method, trait_did) { @@ -766,14 +769,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } (None, None) => Err(vec![]), (None, Some(trait_did)) => { - let (obligation, _) = self.obligation_for_op_method( - span, - trait_did, - lhs_ty, - other_ty, - other_ty_expr, - expected, - ); + let (obligation, _) = + self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types)); Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation)) } } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index d3e88b1b80a..28e959b7c6a 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1013,7 +1013,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (res, opt_ty, segments) = self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); if res == Res::Err { - let e = tcx.sess.delay_span_bug(pat.span, "`Res:Err` but no error emitted"); + let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); on_error(e); return tcx.ty_error_with_guaranteed(e); @@ -1921,7 +1921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let expected = self.shallow_resolve(expected); - let (rptr_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, inner) { + let (ref_ty, inner_ty) = if self.check_dereferenceable(pat.span, expected, inner) { // `demand::subtype` would be good enough, but using `eqtype` turns // out to be equally general. See (note_1) for details. @@ -1936,9 +1936,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: TypeVariableOriginKind::TypeInference, span: inner.span, }); - let rptr_ty = self.new_ref_ty(pat.span, mutbl, inner_ty); - debug!("check_pat_ref: demanding {:?} = {:?}", expected, rptr_ty); - let err = self.demand_eqtype_pat_diag(pat.span, expected, rptr_ty, ti); + let ref_ty = self.new_ref_ty(pat.span, mutbl, inner_ty); + debug!("check_pat_ref: demanding {:?} = {:?}", expected, ref_ty); + let err = self.demand_eqtype_pat_diag(pat.span, expected, ref_ty, ti); // Look for a case like `fn foo(&foo: u32)` and suggest // `fn foo(foo: &u32)` @@ -1946,7 +1946,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.borrow_pat_suggestion(&mut err, pat); err.emit(); } - (rptr_ty, inner_ty) + (ref_ty, inner_ty) } } } else { @@ -1954,7 +1954,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (err, err) }; self.check_pat(inner, inner_ty, def_bm, ti); - rptr_ty + ref_ty } /// Create a reference type with a fresh region variable. diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 952ea14887f..a0f048fc09b 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -225,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { imm_tr.and_then(|trait_did| { self.lookup_method_in_trait( - span, + self.misc(span), Ident::with_dummy_span(imm_op), trait_did, base_ty, @@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut_tr.and_then(|trait_did| { self.lookup_method_in_trait( - span, + self.misc(span), Ident::with_dummy_span(mut_op), trait_did, base_ty, diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index c4f11472d55..4430acf34db 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -369,8 +369,8 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { { let mut mk_suggestion = || { let ( - hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. }, - hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. }, + hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. }, + hir::Ty { kind: hir::TyKind::Ref(lifetime_sup, _), .. }, ) = (self.ty_sub, self.ty_sup) else { return false; }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 96a976fb89e..7222eb77682 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -729,7 +729,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { format!("this and all prior arms are found to be of type `{}`", t), ); } - let outer_error_span = if any_multiline_arm { + let outer = if any_multiline_arm || !source_map.is_multiline(cause.span) { // Cover just `match` and the scrutinee expression, not // the entire match body, to reduce diagram noise. cause.span.shrink_to_lo().to(scrut_span) @@ -737,7 +737,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { cause.span }; let msg = "`match` arms have incompatible types"; - err.span_label(outer_error_span, msg); + err.span_label(outer, msg); self.suggest_remove_semi_or_return_binding( err, prior_arm_block_id, @@ -1836,7 +1836,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // In some (most?) cases cause.body_id points to actual body, but in some cases // it's an actual definition. According to the comments (e.g. in - // rustc_hir_analysis/check/compare_method.rs:compare_predicate_entailment) the latter + // rustc_hir_analysis/check/compare_impl_item.rs:compare_predicate_entailment) the latter // is relied upon by some other code. This might (or might not) need cleanup. let body_owner_def_id = self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index d8f540b7446..39f4d502259 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -96,8 +96,8 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { } } - hir::TyKind::Rptr(ref lifetime, _) => { - // the lifetime of the TyRptr + hir::TyKind::Ref(ref lifetime, _) => { + // the lifetime of the Ref let hir_id = lifetime.hir_id; match (self.tcx.named_region(hir_id), self.bound_region) { // Find the index of the named region that was part of the diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 5d536e982ed..dc1dc898922 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -147,7 +147,7 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { match arg.kind { - hir::TyKind::Rptr(_, ref mut_ty) => { + hir::TyKind::Ref(_, ref mut_ty) => { // We don't want to suggest looking into borrowing `&T` or `&Self`. hir::intravisit::walk_ty(self, mut_ty.ty); return; diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index d2dffa4a0b7..d91ef882bc4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -2,11 +2,14 @@ use crate::errors::RegionOriginNote; use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; use crate::infer::{self, SubregionOrigin}; use rustc_errors::{ - fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, }; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, Region}; +use rustc_middle::ty::{self, IsSuggestable, Region}; +use rustc_span::symbol::kw; use super::ObligationCauseAsDiagArg; @@ -313,55 +316,38 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); err } - infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self - .report_extra_impl_obligation( + infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { + let mut err = self.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, &format!("`{}: {}`", sup, sub), - ), + ); + // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause + if let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) + && generics.where_clause_span.contains(span) + { + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); + } + err + } infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { let mut err = self.report_concrete_failure(*parent, sub, sup); - let trait_item_span = self.tcx.def_span(trait_item_def_id); let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); err.span_label( trait_item_span, format!("definition of `{}` from trait", item_name), ); - - let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id); - let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id); - - let impl_predicates: rustc_data_structures::fx::FxHashSet<_> = - impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect(); - let clauses: Vec<_> = trait_predicates - .predicates - .into_iter() - .filter(|&(pred, _)| !impl_predicates.contains(pred)) - .map(|(pred, _)| format!("{}", pred)) - .collect(); - - if !clauses.is_empty() { - let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap(); - let where_clause_span = generics.tail_span_for_predicate_suggestion(); - - let suggestion = format!( - "{} {}", - generics.add_where_or_trailing_comma(), - clauses.join(", "), - ); - err.span_suggestion( - where_clause_span, - &format!( - "try copying {} from the trait", - if clauses.len() > 1 { "these clauses" } else { "this clause" } - ), - suggestion, - rustc_errors::Applicability::MaybeIncorrect, - ); - } - + self.suggest_copy_trait_method_bounds( + trait_item_def_id, + impl_item_def_id, + &mut err, + ); err } infer::AscribeUserTypeProvePredicate(span) => { @@ -388,6 +374,65 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } + pub fn suggest_copy_trait_method_bounds( + &self, + trait_item_def_id: DefId, + impl_item_def_id: LocalDefId, + err: &mut Diagnostic, + ) { + // FIXME(compiler-errors): Right now this is only being used for region + // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches, + // but right now it's not really very smart when it comes to implicit `Sized` + // predicates and bounds on the trait itself. + + let Some(impl_def_id) = + self.tcx.associated_item(impl_item_def_id).impl_container(self.tcx) else { return; }; + let Some(trait_ref) = self + .tcx + .impl_trait_ref(impl_def_id) + else { return; }; + let trait_substs = trait_ref + // Replace the explicit self type with `Self` for better suggestion rendering + .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper)) + .substs; + let trait_item_substs = + ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id.to_def_id()) + .rebase_onto(self.tcx, impl_def_id, trait_substs); + + let Ok(trait_predicates) = self + .tcx + .bound_explicit_predicates_of(trait_item_def_id) + .map_bound(|p| p.predicates) + .subst_iter_copied(self.tcx, trait_item_substs) + .map(|(pred, _)| { + if pred.is_suggestable(self.tcx, false) { + Ok(pred.to_string()) + } else { + Err(()) + } + }) + .collect::<Result<Vec<_>, ()>>() else { return; }; + + let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; }; + + if trait_predicates.is_empty() { + err.span_suggestion_verbose( + generics.where_clause_span, + "remove the `where` clause", + String::new(), + Applicability::MachineApplicable, + ); + } else { + let space = if generics.where_clause_span.is_empty() { " " } else { "" }; + err.span_suggestion_verbose( + generics.where_clause_span, + "copy the `where` clause predicates from the trait", + format!("{space}where {}", trait_predicates.join(", ")), + Applicability::MachineApplicable, + ); + } + } + pub(super) fn report_placeholder_failure( &self, placeholder_origin: SubregionOrigin<'tcx>, diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs b/compiler/rustc_infer/src/infer/error_reporting/note_region.rs deleted file mode 100644 index 41b115f3377..00000000000 --- a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs +++ /dev/null @@ -1,427 +0,0 @@ -use crate::errors::RegionOriginNote; -use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; -use crate::infer::{self, SubregionOrigin}; -use rustc_errors::{ - fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, -}; -use rustc_middle::traits::ObligationCauseCode; -use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, Region}; - -use super::ObligationCauseAsDiagArg; - -impl<'tcx> TypeErrCtxt<'_, 'tcx> { - pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) { - match *origin { - infer::Subtype(ref trace) => RegionOriginNote::WithRequirement { - span: trace.cause.span, - requirement: ObligationCauseAsDiagArg(trace.cause.clone()), - expected_found: self.values_str(trace.values), - } - .add_to_diagnostic(err), - infer::Reborrow(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err) - } - infer::ReborrowUpvar(span, ref upvar_id) => { - let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - RegionOriginNote::WithName { - span, - msg: fluent::infer_reborrow, - name: &var_name.to_string(), - continues: false, - } - .add_to_diagnostic(err); - } - infer::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound } - .add_to_diagnostic(err); - } - infer::DataBorrowed(ty, span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_data_borrowed, - name: &self.ty_to_string(ty), - continues: false, - } - .add_to_diagnostic(err); - } - infer::ReferenceOutlivesReferent(ty, span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_reference_outlives_referent, - name: &self.ty_to_string(ty), - continues: false, - } - .add_to_diagnostic(err); - } - infer::RelateParamBound(span, ty, opt_span) => { - RegionOriginNote::WithName { - span, - msg: fluent::infer_relate_param_bound, - name: &self.ty_to_string(ty), - continues: opt_span.is_some(), - } - .add_to_diagnostic(err); - if let Some(span) = opt_span { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 } - .add_to_diagnostic(err); - } - } - infer::RelateRegionParamBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound } - .add_to_diagnostic(err); - } - infer::CompareImplItemObligation { span, .. } => { - RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation } - .add_to_diagnostic(err); - } - infer::CheckAssociatedTypeBounds { ref parent, .. } => { - self.note_region_origin(err, &parent); - } - infer::AscribeUserTypeProvePredicate(span) => { - RegionOriginNote::Plain { - span, - msg: fluent::infer_ascribe_user_type_prove_predicate, - } - .add_to_diagnostic(err); - } - } - } - - pub(super) fn report_concrete_failure( - &self, - origin: SubregionOrigin<'tcx>, - sub: Region<'tcx>, - sup: Region<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - match origin { - infer::Subtype(box trace) => { - let terr = TypeError::RegionsDoesNotOutlive(sup, sub); - let mut err = self.report_and_explain_type_error(trace, terr); - match (*sub, *sup) { - (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} - (ty::RePlaceholder(_), _) => { - note_and_explain_region( - self.tcx, - &mut err, - "", - sup, - " doesn't meet the lifetime requirements", - None, - ); - } - (_, ty::RePlaceholder(_)) => { - note_and_explain_region( - self.tcx, - &mut err, - "the required lifetime does not necessarily outlive ", - sub, - "", - None, - ); - } - _ => { - note_and_explain_region(self.tcx, &mut err, "", sup, "...", None); - note_and_explain_region( - self.tcx, - &mut err, - "...does not necessarily outlive ", - sub, - "", - None, - ); - } - } - err - } - infer::Reborrow(span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0312, - "lifetime of reference outlives lifetime of borrowed content..." - ); - note_and_explain_region( - self.tcx, - &mut err, - "...the reference is valid for ", - sub, - "...", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "...but the borrowed content is only valid for ", - sup, - "", - None, - ); - err - } - infer::ReborrowUpvar(span, ref upvar_id) => { - let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0313, - "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", - var_name - ); - note_and_explain_region( - self.tcx, - &mut err, - "...the borrowed pointer is valid for ", - sub, - "...", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - &format!("...but `{}` is only valid for ", var_name), - sup, - "", - None, - ); - err - } - infer::RelateObjectBound(span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0476, - "lifetime of the source pointer does not outlive lifetime bound of the \ - object type" - ); - note_and_explain_region( - self.tcx, - &mut err, - "object type is valid for ", - sub, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "source pointer is only valid for ", - sup, - "", - None, - ); - err - } - infer::RelateParamBound(span, ty, opt_span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0477, - "the type `{}` does not fulfill the required lifetime", - self.ty_to_string(ty) - ); - match *sub { - ty::ReStatic => note_and_explain_region( - self.tcx, - &mut err, - "type must satisfy ", - sub, - if opt_span.is_some() { " as required by this binding" } else { "" }, - opt_span, - ), - _ => note_and_explain_region( - self.tcx, - &mut err, - "type must outlive ", - sub, - if opt_span.is_some() { " as required by this binding" } else { "" }, - opt_span, - ), - } - err - } - infer::RelateRegionParamBound(span) => { - let mut err = - struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); - note_and_explain_region( - self.tcx, - &mut err, - "lifetime parameter instantiated with ", - sup, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but lifetime parameter must outlive ", - sub, - "", - None, - ); - err - } - infer::DataBorrowed(ty, span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0490, - "a value of type `{}` is borrowed for too long", - self.ty_to_string(ty) - ); - note_and_explain_region( - self.tcx, - &mut err, - "the type is valid for ", - sub, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but the borrow lasts for ", - sup, - "", - None, - ); - err - } - infer::ReferenceOutlivesReferent(ty, span) => { - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0491, - "in type `{}`, reference has a longer lifetime than the data it references", - self.ty_to_string(ty) - ); - note_and_explain_region( - self.tcx, - &mut err, - "the pointer is valid for ", - sub, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but the referenced data is only valid for ", - sup, - "", - None, - ); - err - } - infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self - .report_extra_impl_obligation( - span, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", sup, sub), - ), - infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => { - let mut err = self.report_concrete_failure(*parent, sub, sup); - - let trait_item_span = self.tcx.def_span(trait_item_def_id); - let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label( - trait_item_span, - format!("definition of `{}` from trait", item_name), - ); - - let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id); - let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id); - - let impl_predicates: rustc_data_structures::fx::FxHashSet<_> = - impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect(); - let clauses: Vec<_> = trait_predicates - .predicates - .into_iter() - .filter(|&(pred, _)| !impl_predicates.contains(pred)) - .map(|(pred, _)| format!("{}", pred)) - .collect(); - - if !clauses.is_empty() { - let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap(); - let where_clause_span = generics.tail_span_for_predicate_suggestion(); - - let suggestion = format!( - "{} {}", - generics.add_where_or_trailing_comma(), - clauses.join(", "), - ); - err.span_suggestion( - where_clause_span, - &format!( - "try copying {} from the trait", - if clauses.len() > 1 { "these clauses" } else { "this clause" } - ), - suggestion, - rustc_errors::Applicability::MaybeIncorrect, - ); - } - - err - } - infer::AscribeUserTypeProvePredicate(span) => { - let mut err = - struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); - note_and_explain_region( - self.tcx, - &mut err, - "lifetime instantiated with ", - sup, - "", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - "but lifetime must outlive ", - sub, - "", - None, - ); - err - } - } - } - - pub(super) fn report_placeholder_failure( - &self, - placeholder_origin: SubregionOrigin<'tcx>, - sub: Region<'tcx>, - sup: Region<'tcx>, - ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - // I can't think how to do better than this right now. -nikomatsakis - debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure"); - match placeholder_origin { - infer::Subtype(box ref trace) - if matches!( - &trace.cause.code().peel_derives(), - ObligationCauseCode::BindingObligation(..) - | ObligationCauseCode::ExprBindingObligation(..) - ) => - { - // Hack to get around the borrow checker because trace.cause has an `Rc`. - if let ObligationCauseCode::BindingObligation(_, span) - | ObligationCauseCode::ExprBindingObligation(_, span, ..) = - &trace.cause.code().peel_derives() - { - let span = *span; - let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); - err.span_note(span, "the lifetime requirement is introduced here"); - err - } else { - unreachable!() - } - } - infer::Subtype(box trace) => { - let terr = TypeError::RegionsPlaceholderMismatch; - return self.report_and_explain_type_error(trace, terr); - } - _ => return self.report_concrete_failure(placeholder_origin, sub, sup), - } - } -} diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a9ef91db059..b17a465eb38 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1693,7 +1693,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, generic_param_scope: LocalDefId, outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Option<ErrorGuaranteed> { + ) -> Result<(), ErrorGuaranteed> { let errors = self.resolve_regions(outlives_env); if let None = self.tainted_by_errors() { @@ -1705,9 +1705,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_region_errors(generic_param_scope, &errors); } - (!errors.is_empty()).then(|| { - self.tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted") - }) + if errors.is_empty() { + Ok(()) + } else { + Err(self + .tcx + .sess + .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")) + } } // [Note-Type-error-reporting] diff --git a/compiler/rustc_infer/src/infer/note.rs b/compiler/rustc_infer/src/infer/note.rs deleted file mode 100644 index 2ccbd164faa..00000000000 --- a/compiler/rustc_infer/src/infer/note.rs +++ /dev/null @@ -1,203 +0,0 @@ -impl<'tcx> TypeErrCtxt<'_, 'tcx> { - fn note_error_origin( - &self, - err: &mut Diagnostic, - cause: &ObligationCause<'tcx>, - exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>, - terr: TypeError<'tcx>, - ) { - match *cause.code() { - ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { - let ty = self.resolve_vars_if_possible(root_ty); - if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_))) - { - // don't show type `_` - if span.desugaring_kind() == Some(DesugaringKind::ForLoop) - && let ty::Adt(def, substs) = ty.kind() - && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option) - { - err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0))); - } else { - err.span_label(span, format!("this expression has type `{}`", ty)); - } - } - if let Some(ty::error::ExpectedFound { found, .. }) = exp_found - && ty.is_box() && ty.boxed_ty() == found - && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) - { - err.span_suggestion( - span, - "consider dereferencing the boxed value", - format!("*{}", snippet), - Applicability::MachineApplicable, - ); - } - } - ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => { - err.span_label(span, "expected due to this"); - } - ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { - arm_block_id, - arm_span, - arm_ty, - prior_arm_block_id, - prior_arm_span, - prior_arm_ty, - source, - ref prior_arms, - scrut_hir_id, - opt_suggest_box_span, - scrut_span, - .. - }) => match source { - hir::MatchSource::TryDesugar => { - if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found { - let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id); - let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind { - let arg_expr = args.first().expect("try desugaring call w/out arg"); - self.typeck_results.as_ref().and_then(|typeck_results| { - typeck_results.expr_ty_opt(arg_expr) - }) - } else { - bug!("try desugaring w/out call expr as scrutinee"); - }; - - match scrut_ty { - Some(ty) if expected == ty => { - let source_map = self.tcx.sess.source_map(); - err.span_suggestion( - source_map.end_point(cause.span), - "try removing this `?`", - "", - Applicability::MachineApplicable, - ); - } - _ => {} - } - } - } - _ => { - // `prior_arm_ty` can be `!`, `expected` will have better info when present. - let t = self.resolve_vars_if_possible(match exp_found { - Some(ty::error::ExpectedFound { expected, .. }) => expected, - _ => prior_arm_ty, - }); - let source_map = self.tcx.sess.source_map(); - let mut any_multiline_arm = source_map.is_multiline(arm_span); - if prior_arms.len() <= 4 { - for sp in prior_arms { - any_multiline_arm |= source_map.is_multiline(*sp); - err.span_label(*sp, format!("this is found to be of type `{}`", t)); - } - } else if let Some(sp) = prior_arms.last() { - any_multiline_arm |= source_map.is_multiline(*sp); - err.span_label( - *sp, - format!("this and all prior arms are found to be of type `{}`", t), - ); - } - let outer_error_span = if any_multiline_arm { - // Cover just `match` and the scrutinee expression, not - // the entire match body, to reduce diagram noise. - cause.span.shrink_to_lo().to(scrut_span) - } else { - cause.span - }; - let msg = "`match` arms have incompatible types"; - err.span_label(outer_error_span, msg); - self.suggest_remove_semi_or_return_binding( - err, - prior_arm_block_id, - prior_arm_ty, - prior_arm_span, - arm_block_id, - arm_ty, - arm_span, - ); - if let Some(ret_sp) = opt_suggest_box_span { - // Get return type span and point to it. - self.suggest_boxing_for_return_impl_trait( - err, - ret_sp, - prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s), - ); - } - } - }, - ObligationCauseCode::IfExpression(box IfExpressionCause { - then_id, - else_id, - then_ty, - else_ty, - outer_span, - opt_suggest_box_span, - }) => { - let then_span = self.find_block_span_from_hir_id(then_id); - let else_span = self.find_block_span_from_hir_id(else_id); - err.span_label(then_span, "expected because of this"); - if let Some(sp) = outer_span { - err.span_label(sp, "`if` and `else` have incompatible types"); - } - self.suggest_remove_semi_or_return_binding( - err, - Some(then_id), - then_ty, - then_span, - Some(else_id), - else_ty, - else_span, - ); - if let Some(ret_sp) = opt_suggest_box_span { - self.suggest_boxing_for_return_impl_trait( - err, - ret_sp, - [then_span, else_span].into_iter(), - ); - } - } - ObligationCauseCode::LetElse => { - err.help("try adding a diverging expression, such as `return` or `panic!(..)`"); - err.help("...or use `match` instead of `let...else`"); - } - _ => { - if let ObligationCauseCode::BindingObligation(_, span) - | ObligationCauseCode::ExprBindingObligation(_, span, ..) - = cause.code().peel_derives() - && let TypeError::RegionsPlaceholderMismatch = terr - { - err.span_note( * span, - "the lifetime requirement is introduced here"); - } - } - } - } -} - -impl<'tcx> InferCtxt<'tcx> { - /// Given a [`hir::Block`], get the span of its last expression or - /// statement, peeling off any inner blocks. - pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span { - let block = block.innermost_block(); - if let Some(expr) = &block.expr { - expr.span - } else if let Some(stmt) = block.stmts.last() { - // possibly incorrect trailing `;` in the else arm - stmt.span - } else { - // empty block; point at its entirety - block.span - } - } - - /// Given a [`hir::HirId`] for a block, get the span of its last expression - /// or statement, peeling off any inner blocks. - pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span { - match self.tcx.hir().get(hir_id) { - hir::Node::Block(blk) => self.find_block_span(blk), - // The parser was in a weird state if either of these happen, but - // it's better not to panic. - hir::Node::Expr(e) => e.span, - _ => rustc_span::DUMMY_SP, - } - } -} diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 47bd1564f08..f71c39dc0d2 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -178,7 +178,7 @@ impl<'tcx> InferCtxt<'tcx> { &self, generic_param_scope: LocalDefId, outlives_env: &OutlivesEnvironment<'tcx>, - ) -> Option<ErrorGuaranteed> { + ) -> Result<(), ErrorGuaranteed> { self.process_registered_region_obligations( outlives_env.region_bound_pairs(), outlives_env.param_env, diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 76442de69d3..ee0552d77ce 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -10,6 +10,7 @@ //! origin crate when the `TyCtxt` is not present in TLS. use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS}; +use rustc_middle::dep_graph::TaskDepsRef; use rustc_middle::ty::tls; use std::fmt; @@ -26,14 +27,22 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { /// This is a callback from `rustc_ast` as it cannot access the implicit state /// in `rustc_middle` otherwise. It is used when diagnostic messages are /// emitted and stores them in the current query, if there is one. -fn track_diagnostic(diagnostic: &Diagnostic) { +fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { tls::with_context_opt(|icx| { if let Some(icx) = icx { if let Some(diagnostics) = icx.diagnostics { let mut diagnostics = diagnostics.lock(); diagnostics.extend(Some(diagnostic.clone())); + std::mem::drop(diagnostics); } + + // Diagnostics are tracked, we can ignore the dependency. + let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() }; + return tls::enter_context(&icx, move |_| (*f)(diagnostic)); } + + // In any other case, invoke diagnostics anyway. + (*f)(diagnostic); }) } @@ -55,5 +64,5 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> pub fn setup_callbacks() { rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_))); rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); - TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_))); + TRACK_DIAGNOSTICS.swap(&(track_diagnostic as _)); } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ff2196d5857..eb3baba999b 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -652,7 +652,6 @@ fn test_unstable_options_tracking_hash() { untracked!(future_incompat_test, true); untracked!(hir_stats, true); untracked!(identify_regions, true); - untracked!(incremental_ignore_spans, true); untracked!(incremental_info, true); untracked!(incremental_verify_ich, true); untracked!(input_stats, true); @@ -737,6 +736,7 @@ fn test_unstable_options_tracking_hash() { tracked!(fuel, Some(("abc".to_string(), 99))); tracked!(function_sections, Some(false)); tracked!(human_readable_cgu_names, true); + tracked!(incremental_ignore_spans, true); tracked!(inline_in_all_cgus, Some(true)); tracked!(inline_mir, Some(true)); tracked!(inline_mir_hint_threshold, Some(123)); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 50d6d5b9bab..4c65fca29b8 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -851,7 +851,7 @@ impl Cursor<'_> { } // Eats the identifier. Note: succeeds on `_`, which isn't a valid - // identifer. + // identifier. fn eat_identifier(&mut self) { if !is_id_start(self.first()) { return; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d6de6e70ead..cdb901b7f86 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2184,6 +2184,7 @@ impl ExplicitOutlivesRequirements { tcx: TyCtxt<'tcx>, bounds: &hir::GenericBounds<'_>, inferred_outlives: &[ty::Region<'tcx>], + predicate_span: Span, ) -> Vec<(usize, Span)> { use rustc_middle::middle::resolve_lifetime::Region; @@ -2191,23 +2192,28 @@ impl ExplicitOutlivesRequirements { .iter() .enumerate() .filter_map(|(i, bound)| { - if let hir::GenericBound::Outlives(lifetime) = bound { - let is_inferred = match tcx.named_region(lifetime.hir_id) { - Some(Region::EarlyBound(def_id)) => inferred_outlives.iter().any(|r| { - if let ty::ReEarlyBound(ebr) = **r { - ebr.def_id == def_id - } else { - false - } - }), - _ => false, - }; - is_inferred.then_some((i, bound.span())) - } else { - None + let hir::GenericBound::Outlives(lifetime) = bound else { + return None; + }; + + let is_inferred = match tcx.named_region(lifetime.hir_id) { + Some(Region::EarlyBound(def_id)) => inferred_outlives + .iter() + .any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })), + _ => false, + }; + + if !is_inferred { + return None; } + + let span = bound.span().find_ancestor_inside(predicate_span)?; + if in_external_macro(tcx.sess, span) { + return None; + } + + Some((i, span)) }) - .filter(|(_, span)| !in_external_macro(tcx.sess, *span)) .collect() } @@ -2273,9 +2279,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { use rustc_middle::middle::resolve_lifetime::Region; let def_id = item.owner_id.def_id; - if let hir::ItemKind::Struct(_, ref hir_generics) - | hir::ItemKind::Enum(_, ref hir_generics) - | hir::ItemKind::Union(_, ref hir_generics) = item.kind + if let hir::ItemKind::Struct(_, hir_generics) + | hir::ItemKind::Enum(_, hir_generics) + | hir::ItemKind::Union(_, hir_generics) = item.kind { let inferred_outlives = cx.tcx.inferred_outlives_of(def_id); if inferred_outlives.is_empty() { @@ -2290,53 +2296,58 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { let mut dropped_predicate_count = 0; let num_predicates = hir_generics.predicates.len(); for (i, where_predicate) in hir_generics.predicates.iter().enumerate() { - let (relevant_lifetimes, bounds, span, in_where_clause) = match where_predicate { - hir::WherePredicate::RegionPredicate(predicate) => { - if let Some(Region::EarlyBound(region_def_id)) = - cx.tcx.named_region(predicate.lifetime.hir_id) - { - ( - Self::lifetimes_outliving_lifetime( - inferred_outlives, - region_def_id, - ), - &predicate.bounds, - predicate.span, - predicate.in_where_clause, - ) - } else { - continue; - } - } - hir::WherePredicate::BoundPredicate(predicate) => { - // FIXME we can also infer bounds on associated types, - // and should check for them here. - match predicate.bounded_ty.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { - let Res::Def(DefKind::TyParam, def_id) = path.res else { - continue - }; - let index = ty_generics.param_def_id_to_index[&def_id]; + let (relevant_lifetimes, bounds, predicate_span, in_where_clause) = + match where_predicate { + hir::WherePredicate::RegionPredicate(predicate) => { + if let Some(Region::EarlyBound(region_def_id)) = + cx.tcx.named_region(predicate.lifetime.hir_id) + { ( - Self::lifetimes_outliving_type(inferred_outlives, index), + Self::lifetimes_outliving_lifetime( + inferred_outlives, + region_def_id, + ), &predicate.bounds, predicate.span, - predicate.origin == PredicateOrigin::WhereClause, + predicate.in_where_clause, ) - } - _ => { + } else { continue; } } - } - _ => continue, - }; + hir::WherePredicate::BoundPredicate(predicate) => { + // FIXME we can also infer bounds on associated types, + // and should check for them here. + match predicate.bounded_ty.kind { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => { + let Res::Def(DefKind::TyParam, def_id) = path.res else { + continue; + }; + let index = ty_generics.param_def_id_to_index[&def_id]; + ( + Self::lifetimes_outliving_type(inferred_outlives, index), + &predicate.bounds, + predicate.span, + predicate.origin == PredicateOrigin::WhereClause, + ) + } + _ => { + continue; + } + } + } + _ => continue, + }; if relevant_lifetimes.is_empty() { continue; } - let bound_spans = - self.collect_outlives_bound_spans(cx.tcx, bounds, &relevant_lifetimes); + let bound_spans = self.collect_outlives_bound_spans( + cx.tcx, + bounds, + &relevant_lifetimes, + predicate_span, + ); bound_count += bound_spans.len(); let drop_predicate = bound_spans.len() == bounds.len(); @@ -2345,15 +2356,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } if drop_predicate && !in_where_clause { - lint_spans.push(span); + lint_spans.push(predicate_span); } else if drop_predicate && i + 1 < num_predicates { // If all the bounds on a predicate were inferable and there are // further predicates, we want to eat the trailing comma. let next_predicate_span = hir_generics.predicates[i + 1].span(); - where_lint_spans.push(span.to(next_predicate_span.shrink_to_lo())); + where_lint_spans.push(predicate_span.to(next_predicate_span.shrink_to_lo())); } else { where_lint_spans.extend(self.consolidate_outlives_bound_spans( - span.shrink_to_lo(), + predicate_span.shrink_to_lo(), bounds, bound_spans, )); @@ -2374,12 +2385,26 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } else { hir_generics.span.shrink_to_hi().to(where_span) }; - lint_spans.push(full_where_span); + + // Due to macro expansions, the `full_where_span` might not actually contain all predicates. + if where_lint_spans.iter().all(|&sp| full_where_span.contains(sp)) { + lint_spans.push(full_where_span); + } else { + lint_spans.extend(where_lint_spans); + } } else { lint_spans.extend(where_lint_spans); } if !lint_spans.is_empty() { + // Do not automatically delete outlives requirements from macros. + let applicability = if lint_spans.iter().all(|sp| sp.can_be_used_for_suggestions()) + { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + cx.struct_span_lint( EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), @@ -2387,11 +2412,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { |lint| { lint.set_arg("count", bound_count).multipart_suggestion( fluent::suggestion, - lint_spans - .into_iter() - .map(|span| (span, String::new())) - .collect::<Vec<_>>(), - Applicability::MachineApplicable, + lint_spans.into_iter().map(|span| (span, String::new())).collect(), + applicability, ) }, ); diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 3c9ad410663..a16bb7f1a5f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -355,14 +355,12 @@ impl LintStore { sub: RequestedLevel { level, lint_name }, }); } - CheckLintNameResult::Tool(result) => { - if let Err((Some(_), new_name)) = result { - sess.emit_warning(CheckNameDeprecated { - lint_name: lint_name.clone(), - new_name, - sub: RequestedLevel { level, lint_name }, - }); - } + CheckLintNameResult::Tool(Err((Some(_), new_name))) => { + sess.emit_warning(CheckNameDeprecated { + lint_name: lint_name.clone(), + new_name, + sub: RequestedLevel { level, lint_name }, + }); } CheckLintNameResult::NoTool => { sess.emit_err(CheckNameUnknownTool { diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 0fa81b7e4e0..22caadfab17 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -22,7 +22,7 @@ declare_lint_pass!(PassByValue => [PASS_BY_VALUE]); impl<'tcx> LateLintPass<'tcx> for PassByValue { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { match &ty.kind { - TyKind::Rptr(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { + TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { if cx.tcx.impl_trait_ref(impl_did).is_some() { return; diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 3b8df61a0ea..a7a5234049f 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1142,6 +1142,7 @@ impl UnusedDelimLint for UnusedBraces { && !cx.sess().source_map().is_multiline(value.span) && value.attrs.is_empty() && !value.span.from_expansion() + && !inner.span.from_expansion() { self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos) } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 67868ded0b8..28317d6cea0 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3581,7 +3581,7 @@ declare_lint! { /// fn main() { /// let x: String = "3".try_into().unwrap(); /// // ^^^^^^^^ - /// // This call to try_into matches both Foo:try_into and TryInto::try_into as + /// // This call to try_into matches both Foo::try_into and TryInto::try_into as /// // `TryInto` has been added to the Rust prelude in 2021 edition. /// println!("{x}"); /// } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 6112ec9e4e9..cee4ba56a9d 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -54,7 +54,7 @@ use crate::creader::CStore; use crate::errors::{ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired, - RequiredPanicStrategy, RlibRequired, TwoPanicRuntimes, + RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes, }; use rustc_data_structures::fx::FxHashMap; @@ -224,7 +224,12 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { Linkage::Static => "rlib", _ => "dylib", }; - sess.emit_err(LibRequired { crate_name: tcx.crate_name(cnum), kind: kind }); + let crate_name = tcx.crate_name(cnum); + if crate_name.as_str().starts_with("rustc_") { + sess.emit_err(RustcLibRequired { crate_name, kind }); + } else { + sess.emit_err(LibRequired { crate_name, kind }); + } } } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index de2a879f1d7..02c03114eb6 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -25,6 +25,14 @@ pub struct LibRequired<'a> { } #[derive(Diagnostic)] +#[diag(metadata_rustc_lib_required)] +#[help] +pub struct RustcLibRequired<'a> { + pub crate_name: Symbol, + pub kind: &'a str, +} + +#[derive(Diagnostic)] #[diag(metadata_crate_dep_multiple)] #[help] pub struct CrateDepMultiple { @@ -486,26 +494,16 @@ impl IntoDiagnostic<'_> for MultipleCandidates { let mut diag = handler.struct_err(rustc_errors::fluent::metadata_multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); - diag.code(error_code!(E0465)); + diag.code(error_code!(E0464)); diag.set_span(self.span); for (i, candidate) in self.candidates.iter().enumerate() { - diag.span_note(self.span, &format!("candidate #{}: {}", i + 1, candidate.display())); + diag.note(&format!("candidate #{}: {}", i + 1, candidate.display())); } diag } } #[derive(Diagnostic)] -#[diag(metadata_multiple_matching_crates, code = "E0464")] -#[note] -pub struct MultipleMatchingCrates { - #[primary_span] - pub span: Span, - pub crate_name: Symbol, - pub candidates: String, -} - -#[derive(Diagnostic)] #[diag(metadata_symbol_conflicts_current, code = "E0519")] pub struct SymbolConflictsCurrent { #[primary_span] diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index dda5f4bac42..92dc5bd41cb 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -216,9 +216,8 @@ use crate::creader::Library; use crate::errors::{ CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist, ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles, - LibFilenameForm, MultipleCandidates, MultipleMatchingCrates, NewerCrateVersion, - NoCrateWithTriple, NoDylibPlugin, NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, - SymbolConflictsOthers, + LibFilenameForm, MultipleCandidates, NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin, + NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, SymbolConflictsOthers, }; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; @@ -240,7 +239,6 @@ use rustc_target::spec::{Target, TargetTriple}; use snap::read::FrameDecoder; use std::borrow::Cow; -use std::fmt::Write as _; use std::io::{Read, Result as IoResult, Write}; use std::path::{Path, PathBuf}; use std::{cmp, fmt, fs}; @@ -482,7 +480,22 @@ impl<'a> CrateLocator<'a> { match libraries.len() { 0 => Ok(None), 1 => Ok(Some(libraries.into_iter().next().unwrap().1)), - _ => Err(CrateError::MultipleMatchingCrates(self.crate_name, libraries)), + _ => { + let mut libraries: Vec<_> = libraries.into_values().collect(); + + libraries.sort_by_cached_key(|lib| lib.source.paths().next().unwrap().clone()); + let candidates = libraries + .iter() + .map(|lib| lib.source.paths().next().unwrap().clone()) + .collect::<Vec<_>>(); + + Err(CrateError::MultipleCandidates( + self.crate_name, + // these are the same for all candidates + get_flavor_from_path(candidates.first().unwrap()), + candidates, + )) + } } } @@ -882,17 +895,22 @@ pub fn list_file_metadata( metadata_loader: &dyn MetadataLoader, out: &mut dyn Write, ) -> IoResult<()> { + let flavor = get_flavor_from_path(path); + match get_metadata_section(target, flavor, path, metadata_loader) { + Ok(metadata) => metadata.list_crate_metadata(out), + Err(msg) => write!(out, "{}\n", msg), + } +} + +fn get_flavor_from_path(path: &Path) -> CrateFlavor { let filename = path.file_name().unwrap().to_str().unwrap(); - let flavor = if filename.ends_with(".rlib") { + + if filename.ends_with(".rlib") { CrateFlavor::Rlib } else if filename.ends_with(".rmeta") { CrateFlavor::Rmeta } else { CrateFlavor::Dylib - }; - match get_metadata_section(target, flavor, path, metadata_loader) { - Ok(metadata) => metadata.list_crate_metadata(out), - Err(msg) => write!(out, "{}\n", msg), } } @@ -931,7 +949,6 @@ pub(crate) enum CrateError { ExternLocationNotExist(Symbol, PathBuf), ExternLocationNotFile(Symbol, PathBuf), MultipleCandidates(Symbol, CrateFlavor, Vec<PathBuf>), - MultipleMatchingCrates(Symbol, FxHashMap<Svh, Library>), SymbolConflictsCurrent(Symbol), SymbolConflictsOthers(Symbol), StableCrateIdCollision(Symbol, Symbol), @@ -972,37 +989,7 @@ impl CrateError { sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc }); } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - sess.emit_err(MultipleCandidates { span, flavor: flavor, crate_name, candidates }); - } - CrateError::MultipleMatchingCrates(crate_name, libraries) => { - let mut libraries: Vec<_> = libraries.into_values().collect(); - // Make ordering of candidates deterministic. - // This has to `clone()` to work around lifetime restrictions with `sort_by_key()`. - // `sort_by()` could be used instead, but this is in the error path, - // so the performance shouldn't matter. - libraries.sort_by_cached_key(|lib| lib.source.paths().next().unwrap().clone()); - let candidates = libraries - .iter() - .map(|lib| { - let crate_name = lib.metadata.get_root().name(); - let crate_name = crate_name.as_str(); - let mut paths = lib.source.paths(); - - // This `unwrap()` should be okay because there has to be at least one - // source file. `CrateSource`'s docs confirm that too. - let mut s = format!( - "\ncrate `{}`: {}", - crate_name, - paths.next().unwrap().display() - ); - let padding = 8 + crate_name.len(); - for path in paths { - write!(s, "\n{:>padding$}", path.display(), padding = padding).unwrap(); - } - s - }) - .collect::<String>(); - sess.emit_err(MultipleMatchingCrates { span, crate_name, candidates }); + sess.emit_err(MultipleCandidates { span, crate_name, flavor, candidates }); } CrateError::SymbolConflictsCurrent(root_name) => { sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name }); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9d0ccfeb168..e167bbf57e6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -223,7 +223,7 @@ provide! { tcx, def_id, other, cdata, generator_kind => { table } trait_def => { table } deduced_param_attrs => { table } - collect_trait_impl_trait_tys => { + collect_return_position_impl_trait_in_trait_tys => { Ok(cdata .root .tables diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d5d31bc3edc..214a5842233 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -76,7 +76,7 @@ pub(super) struct EncodeContext<'a, 'tcx> { symbol_table: FxHashMap<Symbol, usize>, } -/// If the current crate is a proc-macro, returns early with `Lazy:empty()`. +/// If the current crate is a proc-macro, returns early with `LazyArray::empty()`. /// This is useful for skipping the encoding of things that aren't needed /// for proc-macro crates. macro_rules! empty_proc_macro { @@ -713,7 +713,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum(); assert_eq!(total_bytes, computed_total_bytes); - if tcx.sess.meta_stats() { + if tcx.sess.opts.unstable_opts.meta_stats { self.opaque.flush(); // Rewind and re-read all the metadata to count the zero bytes we wrote. @@ -1197,7 +1197,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record!(self.tables.params_in_repr[def_id] <- params_in_repr); } if should_encode_trait_impl_trait_tys(tcx, def_id) - && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id) + && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id) { record!(self.tables.trait_impl_trait_tys[def_id] <- table); } @@ -1564,7 +1564,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let trait_ref = self.tcx.impl_trait_ref(def_id); if let Some(trait_ref) = trait_ref { let trait_def = self.tcx.trait_def(trait_ref.def_id); - if let Some(mut an) = trait_def.ancestors(self.tcx, def_id).ok() { + if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) { if let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { self.tables.impl_parent.set(def_id.index, parent.into()); } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index fe640f185b6..d799d3a5ad7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -704,12 +704,10 @@ impl<'hir> Map<'hir> { pub fn get_return_block(self, id: HirId) -> Option<HirId> { let mut iter = self.parent_iter(id).peekable(); let mut ignore_tail = false; - if let Some(node) = self.find(id) { - if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = node { - // When dealing with `return` statements, we don't care about climbing only tail - // expressions. - ignore_tail = true; - } + if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.find(id) { + // When dealing with `return` statements, we don't care about climbing only tail + // expressions. + ignore_tail = true; } while let Some((hir_id, node)) = iter.next() { if let (Some((_, next_node)), false) = (iter.peek(), ignore_tail) { @@ -1162,7 +1160,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher); upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); source_file_names.hash_stable(&mut hcx, &mut stable_hasher); - if tcx.sess.opts.unstable_opts.incremental_relative_spans { + if tcx.sess.opts.incremental_relative_spans() { let definitions = tcx.definitions_untracked(); let mut owner_spans: Vec<_> = krate .owners diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 3f6e29ad611..a633201e3d9 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -160,9 +160,13 @@ pub fn provide(providers: &mut Providers) { } else if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Required(idents)), .. + }) + | Node::ForeignItem(&ForeignItem { + kind: ForeignItemKind::Fn(_, idents, _), + .. }) = hir.get(hir_id) { - tcx.arena.alloc_slice(idents) + idents } else { span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id); } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 50e41e3e006..a89e6566d56 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2894,7 +2894,7 @@ fn pretty_print_const_value<'tcx>( if let Some(contents) = tcx.try_destructure_mir_constant( ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)), ) { - let fields = contents.fields.iter().copied().collect::<Vec<_>>(); + let fields = contents.fields.to_vec(); match *ty.kind() { ty::Array(..) => { fmt.write_str("[")?; diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 013a1bccd3b..438f36373ca 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -1,4 +1,4 @@ -use smallvec::{smallvec, SmallVec}; +use smallvec::SmallVec; use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind}; use rustc_ast::InlineAsmTemplatePiece; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ab512804330..37db2274f67 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -169,7 +169,7 @@ rustc_queries! { separate_provide_extern } - query collect_trait_impl_trait_tys(key: DefId) + query collect_return_position_impl_trait_in_trait_tys(key: DefId) -> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed> { desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } @@ -2117,7 +2117,7 @@ rustc_queries! { desc { "checking to see if `{}` permits being left zeroed", key.ty } } - query compare_assoc_const_impl_item_with_trait_item( + query compare_impl_const( key: (LocalDefId, DefId) ) -> Result<(), ErrorGuaranteed> { desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6d3b94c1fdb..cc53659f827 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -641,11 +641,11 @@ impl<'tcx> TyCtxt<'tcx> { ty::EarlyBinder(self.type_of(def_id)) } - pub fn bound_trait_impl_trait_tys( + pub fn bound_return_position_impl_trait_in_trait_tys( self, def_id: DefId, ) -> ty::EarlyBinder<Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>> { - ty::EarlyBinder(self.collect_trait_impl_trait_tys(def_id)) + ty::EarlyBinder(self.collect_return_position_impl_trait_in_trait_tys(def_id)) } pub fn bound_fn_sig(self, def_id: DefId) -> ty::EarlyBinder<ty::PolyFnSig<'tcx>> { diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 34dbb6e9f68..708a5e4d059 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -4,7 +4,7 @@ use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::{self, Ty}; use rustc_data_structures::sso::SsoHashSet; -use smallvec::{self, SmallVec}; +use smallvec::SmallVec; // The TypeWalker's stack is hot enough that it's worth going to some effort to // avoid heap allocations. diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9d560f5c837..4219e6280eb 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1,6 +1,7 @@ //! Inlining pass for MIR functions use crate::deref_separator::deref_finder; use rustc_attr::InlineAttr; +use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -27,6 +28,8 @@ const RESUME_PENALTY: usize = 45; const UNKNOWN_SIZE_COST: usize = 10; +const TOP_DOWN_DEPTH_LIMIT: usize = 5; + pub struct Inline; #[derive(Copy, Clone, Debug)] @@ -86,8 +89,13 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { let param_env = tcx.param_env_reveal_all_normalized(def_id); - let mut this = - Inliner { tcx, param_env, codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), changed: false }; + let mut this = Inliner { + tcx, + param_env, + codegen_fn_attrs: tcx.codegen_fn_attrs(def_id), + history: Vec::new(), + changed: false, + }; let blocks = BasicBlock::new(0)..body.basic_blocks.next_index(); this.process_blocks(body, blocks); this.changed @@ -98,12 +106,26 @@ struct Inliner<'tcx> { param_env: ParamEnv<'tcx>, /// Caller codegen attributes. codegen_fn_attrs: &'tcx CodegenFnAttrs, + /// Stack of inlined instances. + /// We only check the `DefId` and not the substs because we want to + /// avoid inlining cases of polymorphic recursion. + /// The number of `DefId`s is finite, so checking history is enough + /// to ensure that we do not loop endlessly while inlining. + history: Vec<DefId>, /// Indicates that the caller body has been modified. changed: bool, } impl<'tcx> Inliner<'tcx> { fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range<BasicBlock>) { + // How many callsites in this body are we allowed to inline? We need to limit this in order + // to prevent super-linear growth in MIR size + let inline_limit = match self.history.len() { + 0 => usize::MAX, + 1..=TOP_DOWN_DEPTH_LIMIT => 1, + _ => return, + }; + let mut inlined_count = 0; for bb in blocks { let bb_data = &caller_body[bb]; if bb_data.is_cleanup { @@ -122,12 +144,16 @@ impl<'tcx> Inliner<'tcx> { debug!("not-inlined {} [{}]", callsite.callee, reason); continue; } - Ok(_) => { + Ok(new_blocks) => { debug!("inlined {}", callsite.callee); self.changed = true; - // We could process the blocks returned by `try_inlining` here. However, that - // leads to exponential compile times due to the top-down nature of this kind - // of inlining. + inlined_count += 1; + if inlined_count == inline_limit { + return; + } + self.history.push(callsite.callee.def_id()); + self.process_blocks(caller_body, new_blocks); + self.history.pop(); } } } @@ -289,7 +315,7 @@ impl<'tcx> Inliner<'tcx> { ) -> Option<CallSite<'tcx>> { // Only consider direct calls to functions let terminator = bb_data.terminator(); - if let TerminatorKind::Call { ref func, target, .. } = terminator.kind { + if let TerminatorKind::Call { ref func, target, fn_span, .. } = terminator.kind { let func_ty = func.ty(caller_body, self.tcx); if let ty::FnDef(def_id, substs) = *func_ty.kind() { // To resolve an instance its substs have to be fully normalized. @@ -301,15 +327,14 @@ impl<'tcx> Inliner<'tcx> { return None; } + if self.history.contains(&callee.def_id()) { + return None; + } + let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, substs); + let source_info = SourceInfo { span: fn_span, ..terminator.source_info }; - return Some(CallSite { - callee, - fn_sig, - block: bb, - target, - source_info: terminator.source_info, - }); + return Some(CallSite { callee, fn_sig, block: bb, target, source_info }); } } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index deeeb9af4eb..59cc500a99d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -843,7 +843,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { mir::TerminatorKind::Abort { .. } => { let instance = Instance::mono( tcx, - tcx.require_lang_item(LangItem::PanicNoUnwind, Some(source)), + tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)), ); if should_codegen_locally(tcx, &instance) { self.output.push(create_fn_mono_item(tcx, instance, source)); diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index a55a3fe5cca..4f25fc71314 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -305,7 +305,7 @@ where ); } - let _ = writeln!(s, ""); + let _ = writeln!(s); } std::mem::take(s) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 18a0bee9c2e..574591529f3 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1229,3 +1229,11 @@ pub(crate) struct FnTypoWithImpl { #[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")] pub fn_span: Span, } + +#[derive(Diagnostic)] +#[diag(parse_expected_fn_path_found_fn_keyword)] +pub(crate) struct ExpectedFnPathFoundFnKeyword { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "Fn", style = "verbose")] + pub fn_token_span: Span, +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 0191ab730c8..b3231f55bc6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -31,7 +31,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, + fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, FatalError, Handler, MultiSpan, + PResult, }; use rustc_errors::{pluralize, Diagnostic, ErrorGuaranteed, IntoDiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -41,7 +42,6 @@ use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; use std::mem::take; use std::ops::{Deref, DerefMut}; use thin_vec::{thin_vec, ThinVec}; -use tracing::{debug, trace}; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident) -> Param { @@ -1230,7 +1230,7 @@ impl<'a> Parser<'a> { let sum_span = ty.span.to(self.prev_token.span); let sub = match &ty.kind { - TyKind::Rptr(lifetime, mut_ty) => { + TyKind::Ref(lifetime, mut_ty) => { let sum_with_parens = pprust::to_string(|s| { s.s.word("&"); s.print_opt_lifetime(lifetime); @@ -2557,6 +2557,75 @@ impl<'a> Parser<'a> { Ok(()) } + pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool { + (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind)) + && self.look_ahead(3, |tok| tok == short_kind) + } + + fn diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> Option<Span> { + if self.is_diff_marker(long_kind, short_kind) { + let lo = self.token.span; + for _ in 0..4 { + self.bump(); + } + return Some(lo.to(self.prev_token.span)); + } + None + } + + pub fn recover_diff_marker(&mut self) { + let Some(start) = self.diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) else { + return; + }; + let mut spans = Vec::with_capacity(3); + spans.push(start); + let mut middlediff3 = None; + let mut middle = None; + let mut end = None; + loop { + if self.token.kind == TokenKind::Eof { + break; + } + if let Some(span) = self.diff_marker(&TokenKind::OrOr, &TokenKind::BinOp(token::Or)) { + middlediff3 = Some(span); + } + if let Some(span) = self.diff_marker(&TokenKind::EqEq, &TokenKind::Eq) { + middle = Some(span); + } + if let Some(span) = self.diff_marker(&TokenKind::BinOp(token::Shr), &TokenKind::Gt) { + spans.push(span); + end = Some(span); + break; + } + self.bump(); + } + let mut err = self.struct_span_err(spans, "encountered diff marker"); + err.span_label(start, "after this is the code before the merge"); + if let Some(middle) = middlediff3 { + err.span_label(middle, ""); + } + if let Some(middle) = middle { + err.span_label(middle, ""); + } + if let Some(end) = end { + err.span_label(end, "above this are the incoming code changes"); + } + err.help( + "if you're having merge conflicts after pulling new code, the top section is the code \ + you already had and the bottom section is the remote code", + ); + err.help( + "if you're in the middle of a rebase, the top section is the code being rebased onto \ + and the bottom section is the code coming from the current commit being rebased", + ); + err.note( + "for an explanation on these markers from the `git` documentation, visit \ + <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts>", + ); + err.emit(); + FatalError.raise() + } + /// Parse and throw away a parenthesized comma separated /// sequence of patterns until `)` is reached. fn skip_pat_list(&mut self) -> PResult<'a, ()> { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c0ed450b985..1fc1ffd6cb6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -182,7 +182,7 @@ impl<'a> Parser<'a> { LhsExpr::AttributesParsed(attrs) => Some(attrs), _ => None, }; - if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind) { + if self.token.is_range_separator() { return self.parse_prefix_range_expr(attrs); } else { self.parse_prefix_expr(attrs)? @@ -514,7 +514,7 @@ impl<'a> Parser<'a> { } debug_assert!( - [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token.kind), + self.token.is_range_separator(), "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq", self.token ); @@ -899,7 +899,11 @@ impl<'a> Parser<'a> { let has_lifetime = self.token.is_lifetime() && self.look_ahead(1, |t| t != &token::Colon); let lifetime = has_lifetime.then(|| self.expect_lifetime()); // For recovery, see below. let (borrow_kind, mutbl) = self.parse_borrow_modifiers(lo); - let expr = self.parse_prefix_expr(None); + let expr = if self.token.is_range_separator() { + self.parse_prefix_range_expr(None) + } else { + self.parse_prefix_expr(None) + }; let (hi, expr) = self.interpolated_or_expr_span(expr)?; let span = lo.to(hi); if let Some(lt) = lifetime { @@ -3035,6 +3039,7 @@ impl<'a> Parser<'a> { /// Parses `ident (COLON expr)?`. fn parse_expr_field(&mut self) -> PResult<'a, ExprField> { let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 7c2d01509de..a958c294930 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -24,7 +24,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::DUMMY_SP; use std::mem; use thin_vec::ThinVec; -use tracing::debug; impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. @@ -99,7 +98,9 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option<Item>> { + self.recover_diff_marker(); let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect) } @@ -705,6 +706,7 @@ impl<'a> Parser<'a> { if self.recover_doc_comment_before_brace() { continue; } + self.recover_diff_marker(); match parse_item(self) { Ok(None) => { let mut is_unnecessary_semicolon = !items.is_empty() @@ -1040,8 +1042,11 @@ impl<'a> Parser<'a> { /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] /// ``` fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> { - self.parse_delim_comma_seq(Delimiter::Brace, |p| Ok((p.parse_use_tree()?, DUMMY_NODE_ID))) - .map(|(r, _)| r) + self.parse_delim_comma_seq(Delimiter::Brace, |p| { + p.recover_diff_marker(); + Ok((p.parse_use_tree()?, DUMMY_NODE_ID)) + }) + .map(|(r, _)| r) } fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> { @@ -1380,7 +1385,9 @@ impl<'a> Parser<'a> { } fn parse_enum_variant(&mut self) -> PResult<'a, Option<Variant>> { + self.recover_diff_marker(); let variant_attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token( variant_attrs, ForceCollect::No, @@ -1574,9 +1581,32 @@ impl<'a> Parser<'a> { self.parse_paren_comma_seq(|p| { let attrs = p.parse_outer_attributes()?; p.collect_tokens_trailing_token(attrs, ForceCollect::No, |p, attrs| { + let mut snapshot = None; + if p.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { + // Account for `<<<<<<<` diff markers. We can't proactively error here because + // that can be a valid type start, so we snapshot and reparse only we've + // encountered another parse error. + snapshot = Some(p.create_snapshot_for_diagnostic()); + } let lo = p.token.span; - let vis = p.parse_visibility(FollowedByType::Yes)?; - let ty = p.parse_ty()?; + let vis = match p.parse_visibility(FollowedByType::Yes) { + Ok(vis) => vis, + Err(err) => { + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } + return Err(err); + } + }; + let ty = match p.parse_ty() { + Ok(ty) => ty, + Err(err) => { + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } + return Err(err); + } + }; Ok(( FieldDef { @@ -1597,7 +1627,9 @@ impl<'a> Parser<'a> { /// Parses an element of a struct declaration. fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> { + self.recover_diff_marker(); let attrs = self.parse_outer_attributes()?; + self.recover_diff_marker(); self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; @@ -2424,10 +2456,11 @@ impl<'a> Parser<'a> { } /// Parses the parameter list of a function, including the `(` and `)` delimiters. - fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> { + pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, Vec<Param>> { let mut first_param = true; // Parse the arguments, starting out with `self` being allowed... let (mut params, _) = self.parse_paren_comma_seq(|p| { + p.recover_diff_marker(); let param = p.parse_param_general(req_name, first_param).or_else(|mut e| { e.emit(); let lo = p.prev_token.span; @@ -2465,7 +2498,6 @@ impl<'a> Parser<'a> { }; let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); - let (pat, colon) = this.parse_fn_param_pat_colon()?; if !colon { let mut err = this.unexpected::<()>().unwrap_err(); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 40b88788caa..49d31981539 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -317,7 +317,7 @@ impl TokenCursor { // required to wrap the text. E.g. // - `abc d` is wrapped as `r"abc d"` (num_of_hashes = 0) // - `abc "d"` is wrapped as `r#"abc "d""#` (num_of_hashes = 1) - // - `abc "##d##"` is wrapped as `r###"abc "d""###` (num_of_hashes = 3) + // - `abc "##d##"` is wrapped as `r###"abc ##"d"##"###` (num_of_hashes = 3) let mut num_of_hashes = 0; let mut count = 0; for ch in data.as_str().chars() { @@ -1499,6 +1499,10 @@ impl<'a> Parser<'a> { pub fn clear_expected_tokens(&mut self) { self.expected_tokens.clear(); } + + pub fn approx_token_stream_pos(&self) -> usize { + self.token_cursor.num_next_calls + } } pub(crate) fn make_unclosed_delims_error( diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index a1981e11477..0b057f2f577 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -491,17 +491,6 @@ impl<'a> Parser<'a> { if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind { // The user inverted the order, so help them fix that. - let mut applicability = Applicability::MachineApplicable; - // FIXME(bindings_after_at): Remove this code when stabilizing the feature. - lhs.walk(&mut |p| match p.kind { - // `check_match` is unhappy if the subpattern has a binding anywhere. - PatKind::Ident(..) => { - applicability = Applicability::MaybeIncorrect; - false // Short-circuit. - } - _ => true, - }); - let lhs_span = lhs.span; // Move the LHS into the RHS as a subpattern. // The RHS is now the full pattern. @@ -510,7 +499,12 @@ impl<'a> Parser<'a> { self.struct_span_err(sp, "pattern on wrong side of `@`") .span_label(lhs_span, "pattern on the left, should be on the right") .span_label(rhs.span, "binding on the right, should be on the left") - .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability) + .span_suggestion( + sp, + "switch the order", + pprust::pat_to_string(&rhs), + Applicability::MachineApplicable, + ) .emit(); } else { // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index bae7f2670cb..0daae457d30 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -531,13 +531,23 @@ impl<'a> Parser<'a> { recover: AttemptLocalParseRecovery, ) -> PResult<'a, P<Block>> { let mut stmts = vec![]; + let mut snapshot = None; while !self.eat(&token::CloseDelim(Delimiter::Brace)) { if self.token == token::Eof { break; } + if self.is_diff_marker(&TokenKind::BinOp(token::Shl), &TokenKind::Lt) { + // Account for `<<<<<<<` diff markers. We can't proactively error here because + // that can be a valid path start, so we snapshot and reparse only we've + // encountered another parse error. + snapshot = Some(self.create_snapshot_for_diagnostic()); + } let stmt = match self.parse_full_stmt(recover) { Err(mut err) if recover.yes() => { self.maybe_annotate_with_ascription(&mut err, false); + if let Some(ref mut snapshot) = snapshot { + snapshot.recover_diff_marker(); + } err.emit(); self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); Some(self.mk_stmt_err(self.token.span)) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index b7206b57642..a6f702e5428 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,8 +1,9 @@ use super::{Parser, PathStyle, TokenType}; -use crate::errors::{FnPtrWithGenerics, FnPtrWithGenericsSugg}; +use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; +use ast::DUMMY_NODE_ID; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; @@ -12,7 +13,9 @@ use rustc_ast::{ }; use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::Symbol; +use thin_vec::thin_vec; /// Any `?` or `~const` modifiers that appear at the start of a bound. struct BoundModifiers { @@ -501,7 +504,7 @@ impl<'a> Parser<'a> { self.bump_with((dyn_tok, dyn_tok_sp)); } let ty = self.parse_ty_no_plus()?; - Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl })) + Ok(TyKind::Ref(opt_lifetime, MutTy { ty, mutbl })) } // Parses the `typeof(EXPR)`. @@ -613,6 +616,25 @@ impl<'a> Parser<'a> { /// Parses an `impl B0 + ... + Bn` type. fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { // Always parse bounds greedily for better error recovery. + if self.token.is_lifetime() { + self.look_ahead(1, |t| { + if let token::Ident(symname, _) = t.kind { + // parse pattern with "'a Sized" we're supposed to give suggestion like + // "'a + Sized" + self.struct_span_err( + self.token.span, + &format!("expected `+` between lifetime and {}", symname), + ) + .span_suggestion_verbose( + self.token.span.shrink_to_hi(), + "add `+`", + " +", + Applicability::MaybeIncorrect, + ) + .emit(); + } + }) + } let bounds = self.parse_generic_bounds(None)?; *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) @@ -911,8 +933,20 @@ impl<'a> Parser<'a> { has_parens: bool, modifiers: BoundModifiers, ) -> PResult<'a, GenericBound> { - let lifetime_defs = self.parse_late_bound_lifetime_defs()?; - let path = self.parse_path(PathStyle::Type)?; + let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?; + let mut path = if self.token.is_keyword(kw::Fn) + && self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis)) + && let Some(path) = self.recover_path_from_fn() + { + path + } else { + self.parse_path(PathStyle::Type)? + }; + + if self.may_recover() && self.token == TokenKind::OpenDelim(Delimiter::Parenthesis) { + self.recover_fn_trait_with_lifetime_params(&mut path, &mut lifetime_defs)?; + } + if has_parens { if self.token.is_like_plus() { // Someone has written something like `&dyn (Trait + Other)`. The correct code @@ -941,6 +975,38 @@ impl<'a> Parser<'a> { Ok(GenericBound::Trait(poly_trait, modifier)) } + // recovers a `Fn(..)` parenthesized-style path from `fn(..)` + fn recover_path_from_fn(&mut self) -> Option<ast::Path> { + let fn_token_span = self.token.span; + self.bump(); + let args_lo = self.token.span; + let snapshot = self.create_snapshot_for_diagnostic(); + match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) { + Ok(decl) => { + self.sess.emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span }); + Some(ast::Path { + span: fn_token_span.to(self.prev_token.span), + segments: thin_vec![ast::PathSegment { + ident: Ident::new(Symbol::intern("Fn"), fn_token_span), + id: DUMMY_NODE_ID, + args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs { + span: args_lo.to(self.prev_token.span), + inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(), + inputs_span: args_lo.until(decl.output.span()), + output: decl.output.clone(), + }))), + }], + tokens: None, + }) + } + Err(diag) => { + diag.cancel(); + self.restore_snapshot(snapshot); + None + } + } + } + /// Optionally parses `for<$generic_params>`. pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> { if self.eat_keyword(kw::For) { @@ -955,6 +1021,92 @@ impl<'a> Parser<'a> { } } + /// Recover from `Fn`-family traits (Fn, FnMut, FnOnce) with lifetime arguments + /// (e.g. `FnOnce<'a>(&'a str) -> bool`). Up to generic arguments have already + /// been eaten. + fn recover_fn_trait_with_lifetime_params( + &mut self, + fn_path: &mut ast::Path, + lifetime_defs: &mut Vec<GenericParam>, + ) -> PResult<'a, ()> { + let fn_path_segment = fn_path.segments.last_mut().unwrap(); + let generic_args = if let Some(p_args) = &fn_path_segment.args { + p_args.clone().into_inner() + } else { + // Normally it wouldn't come here because the upstream should have parsed + // generic parameters (otherwise it's impossible to call this function). + return Ok(()); + }; + let lifetimes = + if let ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { span: _, args }) = + &generic_args + { + args.into_iter() + .filter_map(|arg| { + if let ast::AngleBracketedArg::Arg(generic_arg) = arg + && let ast::GenericArg::Lifetime(lifetime) = generic_arg { + Some(lifetime) + } else { + None + } + }) + .collect() + } else { + Vec::new() + }; + // Only try to recover if the trait has lifetime params. + if lifetimes.is_empty() { + return Ok(()); + } + + // Parse `(T, U) -> R`. + let inputs_lo = self.token.span; + let inputs: Vec<_> = + self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect(); + let inputs_span = inputs_lo.to(self.prev_token.span); + let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?; + let args = ast::ParenthesizedArgs { + span: fn_path_segment.span().to(self.prev_token.span), + inputs, + inputs_span, + output, + } + .into(); + *fn_path_segment = + ast::PathSegment { ident: fn_path_segment.ident, args, id: ast::DUMMY_NODE_ID }; + + // Convert parsed `<'a>` in `Fn<'a>` into `for<'a>`. + let mut generic_params = lifetimes + .iter() + .map(|lt| GenericParam { + id: lt.id, + ident: lt.ident, + attrs: ast::AttrVec::new(), + bounds: Vec::new(), + is_placeholder: false, + kind: ast::GenericParamKind::Lifetime, + colon_span: None, + }) + .collect::<Vec<GenericParam>>(); + lifetime_defs.append(&mut generic_params); + + let generic_args_span = generic_args.span(); + let mut err = + self.struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters"); + let snippet = format!( + "for<{}> ", + lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::<String>(), + ); + let before_fn_path = fn_path.span.shrink_to_lo(); + err.multipart_suggestion( + "consider using a higher-ranked trait bound instead", + vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)], + Applicability::MaybeIncorrect, + ) + .emit(); + Ok(()) + } + pub(super) fn check_lifetime(&mut self) -> bool { self.expected_tokens.push(TokenType::Lifetime); self.token.is_lifetime() diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 9cbe04c1288..9f2aaca0acf 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -20,6 +20,7 @@ pub use Flag::*; pub use Piece::*; pub use Position::*; +use rustc_lexer::unescape; use std::iter; use std::str; use std::string; @@ -38,6 +39,31 @@ impl InnerSpan { } } +/// The location and before/after width of a character whose width has changed from its source code +/// representation +#[derive(Copy, Clone, PartialEq, Eq)] +pub struct InnerWidthMapping { + /// Index of the character in the source + pub position: usize, + /// The inner width in characters + pub before: usize, + /// The transformed width in characters + pub after: usize, +} + +impl InnerWidthMapping { + pub fn new(position: usize, before: usize, after: usize) -> InnerWidthMapping { + InnerWidthMapping { position, before, after } + } +} + +/// Whether the input string is a literal. If yes, it contains the inner width mappings. +#[derive(Clone, PartialEq, Eq)] +enum InputStringKind { + NotALiteral, + Literal { width_mappings: Vec<InnerWidthMapping> }, +} + /// The type of format string that we are parsing. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ParseMode { @@ -200,8 +226,8 @@ pub struct Parser<'a> { style: Option<usize>, /// Start and end byte offset of every successfully parsed argument pub arg_places: Vec<InnerSpan>, - /// Characters that need to be shifted - skips: Vec<usize>, + /// Characters whose length has been changed from their in-code representation + width_map: Vec<InnerWidthMapping>, /// Span of the last opening brace seen, used for error reporting last_opening_brace: Option<InnerSpan>, /// Whether the source string is comes from `println!` as opposed to `format!` or `print!` @@ -224,7 +250,7 @@ impl<'a> Iterator for Parser<'a> { '{' => { let curr_last_brace = self.last_opening_brace; let byte_pos = self.to_span_index(pos); - let lbrace_end = self.to_span_index(pos + 1); + let lbrace_end = InnerOffset(byte_pos.0 + self.to_span_width(pos)); self.last_opening_brace = Some(byte_pos.to(lbrace_end)); self.cur.next(); if self.consume('{') { @@ -233,12 +259,15 @@ impl<'a> Iterator for Parser<'a> { Some(String(self.string(pos + 1))) } else { let arg = self.argument(lbrace_end); - if let Some(rbrace_byte_idx) = self.must_consume('}') { - let lbrace_inner_offset = self.to_span_index(pos); - let rbrace_inner_offset = self.to_span_index(rbrace_byte_idx); + if let Some(rbrace_pos) = self.must_consume('}') { if self.is_literal { + let lbrace_byte_pos = self.to_span_index(pos); + let rbrace_byte_pos = self.to_span_index(rbrace_pos); + + let width = self.to_span_width(rbrace_pos); + self.arg_places.push( - lbrace_inner_offset.to(InnerOffset(rbrace_inner_offset.0 + 1)), + lbrace_byte_pos.to(InnerOffset(rbrace_byte_pos.0 + width)), ); } } else { @@ -285,7 +314,11 @@ impl<'a> Parser<'a> { append_newline: bool, mode: ParseMode, ) -> Parser<'a> { - let (skips, is_literal) = find_skips_from_snippet(snippet, style); + let input_string_kind = find_width_map_from_snippet(s, snippet, style); + let (width_map, is_literal) = match input_string_kind { + InputStringKind::Literal { width_mappings } => (width_mappings, true), + InputStringKind::NotALiteral => (Vec::new(), false), + }; Parser { mode, input: s, @@ -294,7 +327,7 @@ impl<'a> Parser<'a> { curarg: 0, style, arg_places: vec![], - skips, + width_map, last_opening_brace: None, append_newline, is_literal, @@ -367,21 +400,34 @@ impl<'a> Parser<'a> { None } + fn remap_pos(&self, mut pos: usize) -> InnerOffset { + for width in &self.width_map { + if pos > width.position { + pos += width.before - width.after; + } else if pos == width.position && width.after == 0 { + pos += width.before; + } else { + break; + } + } + + InnerOffset(pos) + } + fn to_span_index(&self, pos: usize) -> InnerOffset { - let mut pos = pos; // This handles the raw string case, the raw argument is the number of # // in r###"..."### (we need to add one because of the `r`). let raw = self.style.map_or(0, |raw| raw + 1); - for skip in &self.skips { - if pos > *skip { - pos += 1; - } else if pos == *skip && raw == 0 { - pos += 1; - } else { - break; - } + let pos = self.remap_pos(pos); + InnerOffset(raw + pos.0 + 1) + } + + fn to_span_width(&self, pos: usize) -> usize { + let pos = self.remap_pos(pos); + match self.width_map.iter().find(|w| w.position == pos.0) { + Some(w) => w.before, + None => 1, } - InnerOffset(raw + pos + 1) } fn span(&self, start_pos: usize, end_pos: usize) -> InnerSpan { @@ -809,59 +855,75 @@ impl<'a> Parser<'a> { /// Finds the indices of all characters that have been processed and differ between the actual /// written code (code snippet) and the `InternedString` that gets processed in the `Parser` /// in order to properly synthesise the intra-string `Span`s for error diagnostics. -fn find_skips_from_snippet( +fn find_width_map_from_snippet( + input: &str, snippet: Option<string::String>, str_style: Option<usize>, -) -> (Vec<usize>, bool) { +) -> InputStringKind { let snippet = match snippet { Some(ref s) if s.starts_with('"') || s.starts_with("r\"") || s.starts_with("r#") => s, - _ => return (vec![], false), + _ => return InputStringKind::NotALiteral, }; if str_style.is_some() { - return (vec![], true); + return InputStringKind::Literal { width_mappings: Vec::new() }; } + // Strip quotes. let snippet = &snippet[1..snippet.len() - 1]; + // Macros like `println` add a newline at the end. That technically doens't make them "literals" anymore, but it's fine + // since we will never need to point our spans there, so we lie about it here by ignoring it. + // Since there might actually be newlines in the source code, we need to normalize away all trailing newlines. + // If we only trimmed it off the input, `format!("\n")` would cause a mismatch as here we they actually match up. + // Alternatively, we could just count the trailing newlines and only trim one from the input if they don't match up. + let input_no_nl = input.trim_end_matches('\n'); + let Ok(unescaped) = unescape_string(snippet) else { + return InputStringKind::NotALiteral; + }; + + let unescaped_no_nl = unescaped.trim_end_matches('\n'); + + if unescaped_no_nl != input_no_nl { + // The source string that we're pointing at isn't our input, so spans pointing at it will be incorrect. + // This can for example happen with proc macros that respan generated literals. + return InputStringKind::NotALiteral; + } + let mut s = snippet.char_indices(); - let mut skips = vec![]; + let mut width_mappings = vec![]; while let Some((pos, c)) = s.next() { match (c, s.clone().next()) { // skip whitespace and empty lines ending in '\\' - ('\\', Some((next_pos, '\n'))) => { - skips.push(pos); - skips.push(next_pos); + ('\\', Some((_, '\n'))) => { let _ = s.next(); + let mut width = 2; - while let Some((pos, c)) = s.clone().next() { + while let Some((_, c)) = s.clone().next() { if matches!(c, ' ' | '\n' | '\t') { - skips.push(pos); + width += 1; let _ = s.next(); } else { break; } } + + width_mappings.push(InnerWidthMapping::new(pos, width, 0)); } - ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { - skips.push(next_pos); + ('\\', Some((_, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { + width_mappings.push(InnerWidthMapping::new(pos, 2, 1)); let _ = s.next(); } ('\\', Some((_, 'x'))) => { - for _ in 0..3 { - // consume `\xAB` literal - if let Some((pos, _)) = s.next() { - skips.push(pos); - } else { - break; - } - } + // consume `\xAB` literal + s.nth(2); + width_mappings.push(InnerWidthMapping::new(pos, 4, 1)); } ('\\', Some((_, 'u'))) => { - if let Some((pos, _)) = s.next() { - skips.push(pos); - } - if let Some((next_pos, next_c)) = s.next() { + let mut width = 2; + let _ = s.next(); + + if let Some((_, next_c)) = s.next() { if next_c == '{' { // consume up to 6 hexanumeric chars let digits_len = @@ -881,19 +943,18 @@ fn find_skips_from_snippet( let required_skips = digits_len.saturating_sub(len_utf8.saturating_sub(1)); // skip '{' and '}' also - for pos in (next_pos..).take(required_skips + 2) { - skips.push(pos) - } + width += required_skips + 2; s.nth(digits_len); } else if next_c.is_digit(16) { - skips.push(next_pos); + width += 1; + // We suggest adding `{` and `}` when appropriate, accept it here as if // it were correct let mut i = 0; // consume up to 6 hexanumeric chars - while let (Some((next_pos, c)), _) = (s.next(), i < 6) { + while let (Some((_, c)), _) = (s.next(), i < 6) { if c.is_digit(16) { - skips.push(next_pos); + width += 1; } else { break; } @@ -901,11 +962,27 @@ fn find_skips_from_snippet( } } } + + width_mappings.push(InnerWidthMapping::new(pos, width, 1)); } _ => {} } } - (skips, true) + + InputStringKind::Literal { width_mappings } +} + +fn unescape_string(string: &str) -> Result<string::String, unescape::EscapeError> { + let mut buf = string::String::new(); + let mut error = Ok(()); + unescape::unescape_literal(string, unescape::Mode::Str, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(err) => error = Err(err), + } + }); + + error.map(|_| buf) } // Assert a reasonable size for `Piece` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2e2874dbccb..c59c06ac31e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1090,9 +1090,7 @@ impl CheckAttrVisitor<'_> { errors::DocTestUnknownInclude { path, value: value.to_string(), - inner: (attr.style == AttrStyle::Inner) - .then_some("!") - .unwrap_or(""), + inner: if attr.style == AttrStyle::Inner { "!" } else { "" }, sugg: (attr.meta().unwrap().span, applicability), } ); diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 272386f313e..b86d2316820 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -324,7 +324,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { Slice, Array, Ptr, - Rptr, + Ref, BareFn, Never, Tup, @@ -580,7 +580,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Slice, Array, Ptr, - Rptr, + Ref, BareFn, Never, Tup, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index d426a2b6b78..2d243e13cc2 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -34,7 +34,6 @@ use rustc_query_system::query::*; pub use rustc_query_system::query::{deadlock, QueryContext}; pub use rustc_query_system::query::QueryConfig; -pub(crate) use rustc_query_system::query::QueryVTable; mod on_disk_cache; pub use on_disk_cache::OnDiskCache; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 9ffcc5672cc..535445e70bc 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -493,28 +493,32 @@ macro_rules! define_queries { &tcx.query_caches.$name } + fn execute_query(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Stored { + tcx.$name(key) + } + #[inline] - fn make_vtable(tcx: QueryCtxt<'tcx>, key: &Self::Key) -> - QueryVTable<QueryCtxt<'tcx>, Self::Key, Self::Value> - { - let compute = get_provider!([$($modifiers)*][tcx, $name, key]); - let cache_on_disk = Self::cache_on_disk(tcx.tcx, key); - QueryVTable { - anon: is_anon!([$($modifiers)*]), - eval_always: is_eval_always!([$($modifiers)*]), - depth_limit: depth_limit!([$($modifiers)*]), - feedable: feedable!([$($modifiers)*]), - dep_kind: dep_graph::DepKind::$name, - hash_result: hash_result!([$($modifiers)*]), - handle_cycle_error: handle_cycle_error!([$($modifiers)*]), - compute, - try_load_from_disk: if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None }, - } + // key is only sometimes used + #[allow(unused_variables)] + fn compute(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> fn(TyCtxt<'tcx>, Self::Key) -> Self::Value { + get_provider!([$($modifiers)*][qcx, $name, key]) } - fn execute_query(tcx: TyCtxt<'tcx>, k: Self::Key) -> Self::Stored { - tcx.$name(k) + #[inline] + fn try_load_from_disk(qcx: QueryCtxt<'tcx>, key: &Self::Key) -> rustc_query_system::query::TryLoadFromDisk<QueryCtxt<'tcx>, Self> { + let cache_on_disk = Self::cache_on_disk(qcx.tcx, key); + if cache_on_disk { should_ever_cache_on_disk!([$($modifiers)*]) } else { None } } + + const ANON: bool = is_anon!([$($modifiers)*]); + const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); + const DEPTH_LIMIT: bool = depth_limit!([$($modifiers)*]); + const FEEDABLE: bool = feedable!([$($modifiers)*]); + + const DEP_KIND: rustc_middle::dep_graph::DepKind = dep_graph::DepKind::$name; + const HANDLE_CYCLE_ERROR: rustc_query_system::HandleCycleError = handle_cycle_error!([$($modifiers)*]); + + const HASH_RESULT: rustc_query_system::query::HashResult<QueryCtxt<'tcx>, Self> = hash_result!([$($modifiers)*]); })* #[allow(nonstandard_style)] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 52957ee0222..0b1ff5d709f 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -634,7 +634,7 @@ impl<K: DepKind> DepGraph<K> { if dep_node_debug.borrow().contains_key(&dep_node) { return; } - let debug_str = debug_str_gen(); + let debug_str = self.with_ignore(debug_str_gen); dep_node_debug.borrow_mut().insert(dep_node, debug_str); } @@ -829,7 +829,9 @@ impl<K: DepKind> DepGraph<K> { ); if !side_effects.is_empty() { - self.emit_side_effects(qcx, data, dep_node_index, side_effects); + self.with_query_deserialization(|| { + self.emit_side_effects(qcx, data, dep_node_index, side_effects) + }); } // ... and finally storing a "Green" entry in the color map. diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs index 24c960765df..8c0330e438d 100644 --- a/compiler/rustc_query_system/src/query/config.rs +++ b/compiler/rustc_query_system/src/query/config.rs @@ -1,7 +1,6 @@ //! Query configuration and description traits. -use crate::dep_graph::DepNode; -use crate::dep_graph::SerializedDepNodeIndex; +use crate::dep_graph::{DepNode, DepNodeParams, SerializedDepNodeIndex}; use crate::error::HandleCycleError; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; @@ -11,10 +10,16 @@ use rustc_data_structures::fingerprint::Fingerprint; use std::fmt::Debug; use std::hash::Hash; +pub type HashResult<Qcx, Q> = + Option<fn(&mut StableHashingContext<'_>, &<Q as QueryConfig<Qcx>>::Value) -> Fingerprint>; + +pub type TryLoadFromDisk<Qcx, Q> = + Option<fn(Qcx, SerializedDepNodeIndex) -> Option<<Q as QueryConfig<Qcx>>::Value>>; + pub trait QueryConfig<Qcx: QueryContext> { const NAME: &'static str; - type Key: Eq + Hash + Clone + Debug; + type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Clone + Debug; type Value: Debug; type Stored: Debug + Clone + std::borrow::Borrow<Self::Value>; @@ -30,39 +35,27 @@ pub trait QueryConfig<Qcx: QueryContext> { where Qcx: 'a; - // Don't use this method to compute query results, instead use the methods on TyCtxt - fn make_vtable(tcx: Qcx, key: &Self::Key) -> QueryVTable<Qcx, Self::Key, Self::Value>; - fn cache_on_disk(tcx: Qcx::DepContext, key: &Self::Key) -> bool; // Don't use this method to compute query results, instead use the methods on TyCtxt fn execute_query(tcx: Qcx::DepContext, k: Self::Key) -> Self::Stored; -} -#[derive(Copy, Clone)] -pub struct QueryVTable<Qcx: QueryContext, K, V> { - pub anon: bool, - pub dep_kind: Qcx::DepKind, - pub eval_always: bool, - pub depth_limit: bool, - pub feedable: bool, - - pub compute: fn(Qcx::DepContext, K) -> V, - pub hash_result: Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>, - pub handle_cycle_error: HandleCycleError, - // NOTE: this is also `None` if `cache_on_disk()` returns false, not just if it's unsupported by the query - pub try_load_from_disk: Option<fn(Qcx, SerializedDepNodeIndex) -> Option<V>>, -} + fn compute(tcx: Qcx, key: &Self::Key) -> fn(Qcx::DepContext, Self::Key) -> Self::Value; -impl<Qcx: QueryContext, K, V> QueryVTable<Qcx, K, V> { - pub(crate) fn to_dep_node(&self, tcx: Qcx::DepContext, key: &K) -> DepNode<Qcx::DepKind> - where - K: crate::dep_graph::DepNodeParams<Qcx::DepContext>, - { - DepNode::construct(tcx, self.dep_kind, key) - } + fn try_load_from_disk(qcx: Qcx, idx: &Self::Key) -> TryLoadFromDisk<Qcx, Self>; + + const ANON: bool; + const EVAL_ALWAYS: bool; + const DEPTH_LIMIT: bool; + const FEEDABLE: bool; + + const DEP_KIND: Qcx::DepKind; + const HANDLE_CYCLE_ERROR: HandleCycleError; + + const HASH_RESULT: HashResult<Qcx, Self>; - pub(crate) fn compute(&self, tcx: Qcx::DepContext, key: K) -> V { - (self.compute)(tcx, key) + // Just here for convernience and checking that the key matches the kind, don't override this. + fn construct_dep_node(tcx: Qcx::DepContext, key: &Self::Key) -> DepNode<Qcx::DepKind> { + DepNode::construct(tcx, Self::DEP_KIND, key) } } diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index ce9179ea832..d308af19207 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -12,7 +12,7 @@ pub use self::caches::{ }; mod config; -pub use self::config::{QueryConfig, QueryVTable}; +pub use self::config::{HashResult, QueryConfig, TryLoadFromDisk}; use crate::dep_graph::DepKind; use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 53844dab9db..da1ac6a5fb2 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -2,10 +2,9 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams}; +use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex}; use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; -use crate::query::config::QueryVTable; use crate::query::job::{report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo}; use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame}; use crate::values::Value; @@ -361,36 +360,34 @@ where }) } -fn try_execute_query<Qcx, C>( +fn try_execute_query<Q, Qcx>( qcx: Qcx, - state: &QueryState<C::Key, Qcx::DepKind>, - cache: &C, + state: &QueryState<Q::Key, Qcx::DepKind>, + cache: &Q::Cache, span: Span, - key: C::Key, + key: Q::Key, dep_node: Option<DepNode<Qcx::DepKind>>, - query: &QueryVTable<Qcx, C::Key, C::Value>, -) -> (C::Stored, Option<DepNodeIndex>) +) -> (Q::Stored, Option<DepNodeIndex>) where - C: QueryCache, - C::Key: Clone + DepNodeParams<Qcx::DepContext>, - C::Value: Value<Qcx::DepContext, Qcx::DepKind>, - C::Stored: Debug + std::borrow::Borrow<C::Value>, + Q: QueryConfig<Qcx>, Qcx: QueryContext, { - match JobOwner::<'_, C::Key, Qcx::DepKind>::try_start(&qcx, state, span, key.clone()) { + match JobOwner::<'_, Q::Key, Qcx::DepKind>::try_start(&qcx, state, span, key.clone()) { TryGetJob::NotYetStarted(job) => { - let (result, dep_node_index) = execute_job(qcx, key.clone(), dep_node, query, job.id); - if query.feedable { + let (result, dep_node_index) = + execute_job::<Q, Qcx>(qcx, key.clone(), dep_node, job.id); + if Q::FEEDABLE { // We may have put a value inside the cache from inside the execution. // Verify that it has the same hash as what we have now, to ensure consistency. let _ = cache.lookup(&key, |cached_result, _| { - let hasher = query.hash_result.expect("feedable forbids no_hash"); + let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash"); + let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, cached_result.borrow())); let new_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result)); debug_assert_eq!( old_hash, new_hash, "Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}", - query.dep_kind, key, result, cached_result, + Q::DEP_KIND, key, result, cached_result, ); }); } @@ -398,7 +395,7 @@ where (result, Some(dep_node_index)) } TryGetJob::Cycle(error) => { - let result = mk_cycle(qcx, error, query.handle_cycle_error, cache); + let result = mk_cycle(qcx, error, Q::HANDLE_CYCLE_ERROR, cache); (result, None) } #[cfg(parallel_compiler)] @@ -417,16 +414,14 @@ where } } -fn execute_job<Qcx, K, V>( +fn execute_job<Q, Qcx>( qcx: Qcx, - key: K, + key: Q::Key, mut dep_node_opt: Option<DepNode<Qcx::DepKind>>, - query: &QueryVTable<Qcx, K, V>, job_id: QueryJobId, -) -> (V, DepNodeIndex) +) -> (Q::Value, DepNodeIndex) where - K: Clone + DepNodeParams<Qcx::DepContext>, - V: Debug, + Q: QueryConfig<Qcx>, Qcx: QueryContext, { let dep_graph = qcx.dep_context().dep_graph(); @@ -434,23 +429,23 @@ where // Fast path for when incr. comp. is off. if !dep_graph.is_fully_enabled() { let prof_timer = qcx.dep_context().profiler().query_provider(); - let result = qcx.start_query(job_id, query.depth_limit, None, || { - query.compute(*qcx.dep_context(), key) + let result = qcx.start_query(job_id, Q::DEPTH_LIMIT, None, || { + Q::compute(qcx, &key)(*qcx.dep_context(), key) }); let dep_node_index = dep_graph.next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); return (result, dep_node_index); } - if !query.anon && !query.eval_always { + if !Q::ANON && !Q::EVAL_ALWAYS { // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.get_or_insert_with(|| query.to_dep_node(*qcx.dep_context(), &key)); + dep_node_opt.get_or_insert_with(|| Q::construct_dep_node(*qcx.dep_context(), &key)); // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. if let Some(ret) = qcx.start_query(job_id, false, None, || { - try_load_from_disk_and_cache_in_memory(qcx, &key, &dep_node, query) + try_load_from_disk_and_cache_in_memory::<Q, Qcx>(qcx, &key, &dep_node) }) { return ret; } @@ -460,18 +455,19 @@ where let diagnostics = Lock::new(ThinVec::new()); let (result, dep_node_index) = - qcx.start_query(job_id, query.depth_limit, Some(&diagnostics), || { - if query.anon { - return dep_graph.with_anon_task(*qcx.dep_context(), query.dep_kind, || { - query.compute(*qcx.dep_context(), key) + qcx.start_query(job_id, Q::DEPTH_LIMIT, Some(&diagnostics), || { + if Q::ANON { + return dep_graph.with_anon_task(*qcx.dep_context(), Q::DEP_KIND, || { + Q::compute(qcx, &key)(*qcx.dep_context(), key) }); } // `to_dep_node` is expensive for some `DepKind`s. let dep_node = - dep_node_opt.unwrap_or_else(|| query.to_dep_node(*qcx.dep_context(), &key)); + dep_node_opt.unwrap_or_else(|| Q::construct_dep_node(*qcx.dep_context(), &key)); - dep_graph.with_task(dep_node, *qcx.dep_context(), key, query.compute, query.hash_result) + let task = Q::compute(qcx, &key); + dep_graph.with_task(dep_node, *qcx.dep_context(), key, task, Q::HASH_RESULT) }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -480,7 +476,7 @@ where let side_effects = QuerySideEffects { diagnostics }; if std::intrinsics::unlikely(!side_effects.is_empty()) { - if query.anon { + if Q::ANON { qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { qcx.store_side_effects(dep_node_index, side_effects); @@ -490,16 +486,14 @@ where (result, dep_node_index) } -fn try_load_from_disk_and_cache_in_memory<Qcx, K, V>( +fn try_load_from_disk_and_cache_in_memory<Q, Qcx>( qcx: Qcx, - key: &K, + key: &Q::Key, dep_node: &DepNode<Qcx::DepKind>, - query: &QueryVTable<Qcx, K, V>, -) -> Option<(V, DepNodeIndex)> +) -> Option<(Q::Value, DepNodeIndex)> where - K: Clone, + Q: QueryConfig<Qcx>, Qcx: QueryContext, - V: Debug, { // Note this function can be called concurrently from the same query // We must ensure that this is handled correctly. @@ -511,7 +505,7 @@ where // First we try to load the result from the on-disk cache. // Some things are never cached on disk. - if let Some(try_load_from_disk) = query.try_load_from_disk { + if let Some(try_load_from_disk) = Q::try_load_from_disk(qcx, &key) { let prof_timer = qcx.dep_context().profiler().incr_cache_loading(); // The call to `with_query_deserialization` enforces that no new `DepNodes` @@ -545,7 +539,7 @@ where if std::intrinsics::unlikely( try_verify || qcx.dep_context().sess().opts.unstable_opts.incremental_verify_ich, ) { - incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query.hash_result); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, Q::HASH_RESULT); } return Some((result, dep_node_index)); @@ -565,7 +559,7 @@ where let prof_timer = qcx.dep_context().profiler().query_provider(); // The dep-graph for this computation is already in-place. - let result = dep_graph.with_ignore(|| query.compute(*qcx.dep_context(), key.clone())); + let result = dep_graph.with_ignore(|| Q::compute(qcx, key)(*qcx.dep_context(), key.clone())); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -578,7 +572,7 @@ where // // See issue #82920 for an example of a miscompilation that would get turned into // an ICE by this check - incremental_verify_ich(*qcx.dep_context(), &result, dep_node, query.hash_result); + incremental_verify_ich(*qcx.dep_context(), &result, dep_node, Q::HASH_RESULT); Some((result, dep_node_index)) } @@ -699,23 +693,19 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: /// /// Note: The optimization is only available during incr. comp. #[inline(never)] -fn ensure_must_run<Qcx, K, V>( - qcx: Qcx, - key: &K, - query: &QueryVTable<Qcx, K, V>, -) -> (bool, Option<DepNode<Qcx::DepKind>>) +fn ensure_must_run<Q, Qcx>(qcx: Qcx, key: &Q::Key) -> (bool, Option<DepNode<Qcx::DepKind>>) where - K: crate::dep_graph::DepNodeParams<Qcx::DepContext>, + Q: QueryConfig<Qcx>, Qcx: QueryContext, { - if query.eval_always { + if Q::EVAL_ALWAYS { return (true, None); } // Ensuring an anonymous query makes no sense - assert!(!query.anon); + assert!(!Q::ANON); - let dep_node = query.to_dep_node(*qcx.dep_context(), key); + let dep_node = Q::construct_dep_node(*qcx.dep_context(), key); let dep_graph = qcx.dep_context().dep_graph(); match dep_graph.try_mark_green(qcx, &dep_node) { @@ -746,13 +736,11 @@ pub fn get_query<Q, Qcx, D>(qcx: Qcx, span: Span, key: Q::Key, mode: QueryMode) where D: DepKind, Q: QueryConfig<Qcx>, - Q::Key: DepNodeParams<Qcx::DepContext>, Q::Value: Value<Qcx::DepContext, D>, Qcx: QueryContext, { - let query = Q::make_vtable(qcx, &key); let dep_node = if let QueryMode::Ensure = mode { - let (must_run, dep_node) = ensure_must_run(qcx, &key, &query); + let (must_run, dep_node) = ensure_must_run::<Q, _>(qcx, &key); if !must_run { return None; } @@ -761,14 +749,13 @@ where None }; - let (result, dep_node_index) = try_execute_query( + let (result, dep_node_index) = try_execute_query::<Q, Qcx>( qcx, Q::query_state(qcx), Q::query_cache(qcx), span, key, dep_node, - &query, ); if let Some(dep_node_index) = dep_node_index { qcx.dep_context().dep_graph().read_index(dep_node_index) @@ -780,7 +767,6 @@ pub fn force_query<Q, Qcx, D>(qcx: Qcx, key: Q::Key, dep_node: DepNode<Qcx::DepK where D: DepKind, Q: QueryConfig<Qcx>, - Q::Key: DepNodeParams<Qcx::DepContext>, Q::Value: Value<Qcx::DepContext, D>, Qcx: QueryContext, { @@ -798,9 +784,8 @@ where Err(()) => {} } - let query = Q::make_vtable(qcx, &key); let state = Q::query_state(qcx); - debug_assert!(!query.anon); + debug_assert!(!Q::ANON); - try_execute_query(qcx, state, cache, DUMMY_SP, key, Some(dep_node), &query); + try_execute_query::<Q, _>(qcx, state, cache, DUMMY_SP, key, Some(dep_node)); } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5b7a00101e9..c44635b85f8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,7 +16,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; -use rustc_errors::{DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; +use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -536,6 +536,9 @@ struct DiagnosticMetadata<'ast> { in_assignment: Option<&'ast Expr>, is_assign_rhs: bool, + /// Used to detect possible `.` -> `..` typo when calling methods. + in_range: Option<(&'ast Expr, &'ast Expr)>, + /// If we are currently in a trait object definition. Used to point at the bounds when /// encountering a struct or enum. current_trait_object: Option<&'ast [ast::GenericBound]>, @@ -648,7 +651,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { let prev = self.diagnostic_metadata.current_trait_object; let prev_ty = self.diagnostic_metadata.current_type_path; match ty.kind { - TyKind::Rptr(None, _) => { + TyKind::Ref(None, _) => { // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with // NodeId `ty.id`. // This span will be used in case of elision failure. @@ -2001,7 +2004,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { impl<'a> Visitor<'a> for SelfVisitor<'_, '_> { fn visit_ty(&mut self, ty: &'a Ty) { trace!("SelfVisitor considering ty={:?}", ty); - if let TyKind::Rptr(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) { + if let TyKind::Ref(lt, ref mt) = ty.kind && self.is_self_ty(&mt.ty) { let lt_id = if let Some(lt) = lt { lt.id } else { @@ -3320,6 +3323,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); } + #[instrument(level = "debug", skip(self))] fn smart_resolve_path_fragment( &mut self, qself: &Option<P<QSelf>>, @@ -3327,10 +3331,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { source: PathSource<'ast>, finalize: Finalize, ) -> PartialRes { - debug!( - "smart_resolve_path_fragment(qself={:?}, path={:?}, finalize={:?})", - qself, path, finalize, - ); let ns = source.namespace(); let Finalize { node_id, path_span, .. } = finalize; @@ -3341,8 +3341,28 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let def_id = this.parent_scope.module.nearest_parent_mod(); let instead = res.is_some(); - let suggestion = - if res.is_none() { this.report_missing_type_error(path) } else { None }; + let suggestion = if let Some((start, end)) = this.diagnostic_metadata.in_range + && path[0].ident.span.lo() == end.span.lo() + { + let mut sugg = "."; + let mut span = start.span.between(end.span); + if span.lo() + BytePos(2) == span.hi() { + // There's no space between the start, the range op and the end, suggest + // removal which will look better. + span = span.with_lo(span.lo() + BytePos(1)); + sugg = ""; + } + Some(( + span, + "you might have meant to write `.` instead of `..`", + sugg.to_string(), + Applicability::MaybeIncorrect, + )) + } else if res.is_none() { + this.report_missing_type_error(path) + } else { + None + }; this.r.use_injections.push(UseError { err, @@ -4005,6 +4025,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.visit_expr(rhs); self.diagnostic_metadata.is_assign_rhs = false; } + ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => { + self.diagnostic_metadata.in_range = Some((start, end)); + self.resolve_expr(start, Some(expr)); + self.resolve_expr(end, Some(expr)); + self.diagnostic_metadata.in_range = None; + } _ => { visit::walk_expr(self, expr); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 600308b6508..74522f18542 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1554,7 +1554,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn extract_node_id(t: &Ty) -> Option<NodeId> { match t.kind { TyKind::Path(None, _) => Some(t.id), - TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty), + TyKind::Ref(_, ref mut_ty) => extract_node_id(&mut_ty.ty), // This doesn't handle the remaining `Ty` variants as they are not // that commonly the self_type, it might be interesting to provide // support for those in future. @@ -2189,7 +2189,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { Some(LifetimeUseSet::One { use_span, use_ctxt }) => { debug!(?param.ident, ?param.ident.span, ?use_span); - let elidable = matches!(use_ctxt, LifetimeCtxt::Rptr); + let elidable = matches!(use_ctxt, LifetimeCtxt::Ref); let deletion_span = deletion_span(); self.r.lint_buffer.buffer_lint_with_diagnostic( diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 9197a28c188..5a1bcb8fdc8 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -165,7 +165,7 @@ impl<'hir> Sig for hir::Ty<'hir> { let text = format!("{}{}", prefix, nested.text); Ok(replace_text(nested, text)) } - hir::TyKind::Rptr(ref lifetime, ref mt) => { + hir::TyKind::Ref(ref lifetime, ref mt) => { let mut prefix = "&".to_owned(); prefix.push_str(&lifetime.ident.to_string()); prefix.push(' '); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3bafd3730bd..02e3992a6a9 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -787,6 +787,12 @@ impl Options { pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) } + + #[allow(rustc::bad_opt_access)] + pub fn incremental_relative_spans(&self) -> bool { + self.unstable_opts.incremental_relative_spans + || (self.unstable_features.is_nightly_build() && self.incremental.is_some()) + } } impl UnstableOptions { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 40bc669707a..9bf581ff73d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1214,7 +1214,6 @@ options! { "only allow the listed language features to be enabled in code (space separated)"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata (default: no)"), - #[rustc_lint_opt_deny_field_access("use `Session::asm_comments` instead of this field")] asm_comments: bool = (false, parse_bool, [TRACKED], "generate comments into the assembly (may change behavior) (default: no)"), assert_incr_state: Option<String> = (None, parse_opt_string, [UNTRACKED], @@ -1333,11 +1332,12 @@ options! { "generate human-readable, predictable names for codegen units (default: no)"), identify_regions: bool = (false, parse_bool, [UNTRACKED], "display unnamed regions as `'<id>`, using a non-ident unique id (default: no)"), - incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED], + incremental_ignore_spans: bool = (false, parse_bool, [TRACKED], "ignore spans during ICH computation -- used for testing (default: no)"), incremental_info: bool = (false, parse_bool, [UNTRACKED], "print high-level information about incremental reuse (or the lack thereof) \ (default: no)"), + #[rustc_lint_opt_deny_field_access("use `Session::incremental_relative_spans` instead of this field")] incremental_relative_spans: bool = (false, parse_bool, [TRACKED], "hash spans relative to their parent item for incr. comp. (default: no)"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], @@ -1363,7 +1363,6 @@ options! { `=except-unused-generics` `=except-unused-functions` `=off` (default)"), - #[rustc_lint_opt_deny_field_access("use `Session::instrument_mcount` instead of this field")] instrument_mcount: bool = (false, parse_bool, [TRACKED], "insert function instrument code for mcount-based tracing (default: no)"), keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED], @@ -1392,7 +1391,6 @@ options! { merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED], "control the operation of the MergeFunctions LLVM pass, taking \ the same values as the target option of the same name"), - #[rustc_lint_opt_deny_field_access("use `Session::meta_stats` instead of this field")] meta_stats: bool = (false, parse_bool, [UNTRACKED], "gather metadata statistics (default: no)"), mir_emit_retag: bool = (false, parse_bool, [TRACKED], @@ -1469,7 +1467,6 @@ options! { See #77382 and #74551."), print_fuel: Option<String> = (None, parse_opt_string, [TRACKED], "make rustc print the total optimization fuel used by a crate"), - #[rustc_lint_opt_deny_field_access("use `Session::print_llvm_passes` instead of this field")] print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "print the LLVM optimization passes being run (default: no)"), print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED], @@ -1583,10 +1580,8 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")] threads: usize = (1, parse_threads, [UNTRACKED], "use a thread pool with N threads"), - #[rustc_lint_opt_deny_field_access("use `Session::time_llvm_passes` instead of this field")] time_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each LLVM pass (default: no)"), - #[rustc_lint_opt_deny_field_access("use `Session::time_passes` instead of this field")] time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass (default: no)"), #[rustc_lint_opt_deny_field_access("use `Session::tls_model` instead of this field")] diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 01a9b100088..4a3d29414d6 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -976,34 +976,10 @@ impl Session { self.opts.unstable_opts.verbose } - pub fn instrument_mcount(&self) -> bool { - self.opts.unstable_opts.instrument_mcount - } - - pub fn time_passes(&self) -> bool { - self.opts.unstable_opts.time_passes - } - - pub fn time_llvm_passes(&self) -> bool { - self.opts.unstable_opts.time_llvm_passes - } - - pub fn meta_stats(&self) -> bool { - self.opts.unstable_opts.meta_stats - } - - pub fn asm_comments(&self) -> bool { - self.opts.unstable_opts.asm_comments - } - pub fn verify_llvm_ir(&self) -> bool { self.opts.unstable_opts.verify_llvm_ir || option_env!("RUSTC_VERIFY_LLVM_IR").is_some() } - pub fn print_llvm_passes(&self) -> bool { - self.opts.unstable_opts.print_llvm_passes - } - pub fn binary_dep_depinfo(&self) -> bool { self.opts.unstable_opts.binary_dep_depinfo } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index c2d8287f243..4e70dfb6147 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -104,6 +104,10 @@ fn assert_default_hashing_controls<CTX: HashStableContext>(ctx: &CTX, msg: &str) // `-Z incremental-ignore-spans` option. Normally, this option is disabled, // which will cause us to require that this method always be called with `Span` hashing // enabled. + // + // Span hashing can also be disabled without `-Z incremental-ignore-spans`. + // This is the case for instance when building a hash for name mangling. + // Such configuration must not be used for metadata. HashingControls { hash_spans } if hash_spans == !ctx.unstable_opts_incremental_ignore_spans() => {} other => panic!("Attempted hashing of {msg} with non-default HashingControls: {:?}", other), @@ -316,6 +320,7 @@ impl ExpnId { // Stop going up the backtrace once include! is encountered if expn_data.is_root() || expn_data.kind == ExpnKind::Macro(MacroKind::Bang, sym::include) + || expn_data.kind == ExpnKind::Inlined { break; } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 2181c090027..bee4b0a2332 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -796,6 +796,9 @@ impl Span { /// Returns a `Span` that would enclose both `self` and `end`. /// + /// Note that this can also be used to extend the span "backwards": + /// `start.to(end)` and `end.to(start)` return the same `Span`. + /// /// ```text /// ____ ___ /// self lorem ipsum end diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index d9c87ac0ba8..fa09b4faa44 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -964,45 +964,40 @@ impl SourceMap { /// Finds the width of the character, either before or after the end of provided span, /// depending on the `forwards` parameter. + #[instrument(skip(self, sp))] fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 { let sp = sp.data(); if sp.lo == sp.hi && !forwards { - debug!("find_width_of_character_at_span: early return empty span"); + debug!("early return empty span"); return 1; } let local_begin = self.lookup_byte_offset(sp.lo); let local_end = self.lookup_byte_offset(sp.hi); - debug!( - "find_width_of_character_at_span: local_begin=`{:?}`, local_end=`{:?}`", - local_begin, local_end - ); + debug!("local_begin=`{:?}`, local_end=`{:?}`", local_begin, local_end); if local_begin.sf.start_pos != local_end.sf.start_pos { - debug!("find_width_of_character_at_span: begin and end are in different files"); + debug!("begin and end are in different files"); return 1; } let start_index = local_begin.pos.to_usize(); let end_index = local_end.pos.to_usize(); - debug!( - "find_width_of_character_at_span: start_index=`{:?}`, end_index=`{:?}`", - start_index, end_index - ); + debug!("start_index=`{:?}`, end_index=`{:?}`", start_index, end_index); // Disregard indexes that are at the start or end of their spans, they can't fit bigger // characters. if (!forwards && end_index == usize::MIN) || (forwards && start_index == usize::MAX) { - debug!("find_width_of_character_at_span: start or end of span, cannot be multibyte"); + debug!("start or end of span, cannot be multibyte"); return 1; } let source_len = (local_begin.sf.end_pos - local_begin.sf.start_pos).to_usize(); - debug!("find_width_of_character_at_span: source_len=`{:?}`", source_len); + debug!("source_len=`{:?}`", source_len); // Ensure indexes are also not malformed. if start_index > end_index || end_index > source_len - 1 { - debug!("find_width_of_character_at_span: source indexes are malformed"); + debug!("source indexes are malformed"); return 1; } @@ -1017,10 +1012,10 @@ impl SourceMap { } else { return 1; }; - debug!("find_width_of_character_at_span: snippet=`{:?}`", snippet); + debug!("snippet=`{:?}`", snippet); let mut target = if forwards { end_index + 1 } else { end_index - 1 }; - debug!("find_width_of_character_at_span: initial target=`{:?}`", target); + debug!("initial target=`{:?}`", target); while !snippet.is_char_boundary(target - start_index) && target < source_len { target = if forwards { @@ -1033,9 +1028,9 @@ impl SourceMap { } } }; - debug!("find_width_of_character_at_span: target=`{:?}`", target); + debug!("target=`{:?}`", target); } - debug!("find_width_of_character_at_span: final target=`{:?}`", target); + debug!("final target=`{:?}`", target); if forwards { (target - end_index) as u32 } else { (end_index - target) as u32 } } diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index f0e91e5a6a9..d48c4f7e5a8 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -4,7 +4,7 @@ // The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd. // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28 -use crate::def_id::LocalDefId; +use crate::def_id::{DefIndex, LocalDefId}; use crate::hygiene::SyntaxContext; use crate::SPAN_TRACK; use crate::{BytePos, SpanData}; @@ -13,8 +13,8 @@ use rustc_data_structures::fx::FxIndexSet; /// A compressed span. /// -/// Whereas [`SpanData`] is 12 bytes, which is a bit too big to stick everywhere, `Span` -/// is a form that only takes up 8 bytes, with less space for the length and +/// Whereas [`SpanData`] is 16 bytes, which is a bit too big to stick everywhere, `Span` +/// is a form that only takes up 8 bytes, with less space for the length, parent and /// context. The vast majority (99.9%+) of `SpanData` instances will fit within /// those 8 bytes; any `SpanData` whose fields don't fit into a `Span` are /// stored in a separate interner table, and the `Span` will index into that @@ -25,7 +25,7 @@ use rustc_data_structures::fx::FxIndexSet; /// slower because only 80--90% of spans could be stored inline (even less in /// very large crates) and so the interner was used a lot more. /// -/// Inline (compressed) format: +/// Inline (compressed) format with no parent: /// - `span.base_or_index == span_data.lo` /// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`) /// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`) @@ -35,6 +35,12 @@ use rustc_data_structures::fx::FxIndexSet; /// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero) /// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`) /// +/// Inline (compressed) format with root context: +/// - `span.base_or_index == span_data.lo` +/// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`) +/// - `span.len_or_tag` has top bit (`PARENT_MASK`) set +/// - `span.ctxt == span_data.parent` (must be `<= MAX_CTXT`) +/// /// Interned format: /// - `span.base_or_index == index` (indexes into the interner table) /// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero) @@ -73,7 +79,8 @@ pub struct Span { ctxt_or_tag: u16, } -const LEN_TAG: u16 = 0b1000_0000_0000_0000; +const LEN_TAG: u16 = 0b1111_1111_1111_1111; +const PARENT_MASK: u16 = 0b1000_0000_0000_0000; const MAX_LEN: u32 = 0b0111_1111_1111_1111; const CTXT_TAG: u32 = 0b1111_1111_1111_1111; const MAX_CTXT: u32 = CTXT_TAG - 1; @@ -95,16 +102,32 @@ impl Span { let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32()); - if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent.is_none() { - // Inline format. - Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_tag: ctxt2 as u16 } - } else { - // Interned format. - let index = - with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent })); - let ctxt_or_tag = if ctxt2 <= MAX_CTXT { ctxt2 } else { CTXT_TAG } as u16; - Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_tag } + if len <= MAX_LEN && ctxt2 <= MAX_CTXT { + let len_or_tag = len as u16; + debug_assert_eq!(len_or_tag & PARENT_MASK, 0); + + if let Some(parent) = parent { + // Inline format with parent. + let len_or_tag = len_or_tag | PARENT_MASK; + let parent2 = parent.local_def_index.as_u32(); + if ctxt2 == SyntaxContext::root().as_u32() && parent2 <= MAX_CTXT { + return Span { base_or_index: base, len_or_tag, ctxt_or_tag: parent2 as u16 }; + } + } else { + // Inline format with ctxt. + return Span { + base_or_index: base, + len_or_tag: len as u16, + ctxt_or_tag: ctxt2 as u16, + }; + } } + + // Interned format. + let index = + with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent })); + let ctxt_or_tag = if ctxt2 <= MAX_CTXT { ctxt2 } else { CTXT_TAG } as u16; + Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_tag } } #[inline] @@ -122,12 +145,25 @@ impl Span { pub fn data_untracked(self) -> SpanData { if self.len_or_tag != LEN_TAG { // Inline format. - debug_assert!(self.len_or_tag as u32 <= MAX_LEN); - SpanData { - lo: BytePos(self.base_or_index), - hi: BytePos(self.base_or_index + self.len_or_tag as u32), - ctxt: SyntaxContext::from_u32(self.ctxt_or_tag as u32), - parent: None, + if self.len_or_tag & PARENT_MASK == 0 { + debug_assert!(self.len_or_tag as u32 <= MAX_LEN); + SpanData { + lo: BytePos(self.base_or_index), + hi: BytePos(self.base_or_index + self.len_or_tag as u32), + ctxt: SyntaxContext::from_u32(self.ctxt_or_tag as u32), + parent: None, + } + } else { + let len = self.len_or_tag & !PARENT_MASK; + debug_assert!(len as u32 <= MAX_LEN); + let parent = + LocalDefId { local_def_index: DefIndex::from_u32(self.ctxt_or_tag as u32) }; + SpanData { + lo: BytePos(self.base_or_index), + hi: BytePos(self.base_or_index + len as u32), + ctxt: SyntaxContext::root(), + parent: Some(parent), + } } } else { // Interned format. @@ -141,8 +177,14 @@ impl Span { pub fn ctxt(self) -> SyntaxContext { let ctxt_or_tag = self.ctxt_or_tag as u32; if ctxt_or_tag <= MAX_CTXT { - // Inline format or interned format with inline ctxt. - SyntaxContext::from_u32(ctxt_or_tag) + if self.len_or_tag == LEN_TAG || self.len_or_tag & PARENT_MASK == 0 { + // Inline format or interned format with inline ctxt. + SyntaxContext::from_u32(ctxt_or_tag) + } else { + // Inline format or interned format with inline parent. + // We know that the SyntaxContext is root. + SyntaxContext::root() + } } else { // Interned format. let index = self.base_or_index; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e8026634713..85510fa2c66 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -213,6 +213,7 @@ symbols! { Is, ItemContext, Iterator, + IteratorItem, Layout, Left, LinkedList, @@ -1041,6 +1042,7 @@ symbols! { panic_2021, panic_abort, panic_bounds_check, + panic_cannot_unwind, panic_display, panic_fmt, panic_handler, @@ -1048,7 +1050,7 @@ symbols! { panic_implementation, panic_info, panic_location, - panic_no_unwind, + panic_nounwind, panic_runtime, panic_str, panic_unwind, diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 493e31a688f..e9b85705086 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -164,6 +164,7 @@ fn encode_const<'tcx>( /// Encodes a FnSig using the Itanium C++ ABI with vendor extended type qualifiers and types for /// Rust types that are not used at the FFI boundary. +#[instrument(level = "trace", skip(tcx, dict))] fn encode_fnsig<'tcx>( tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>, @@ -653,6 +654,7 @@ fn encode_ty<'tcx>( // Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all // c_void types into unit types unconditionally, and generalizes all pointers if // TransformTyOptions::GENERALIZE_POINTERS option is set. +#[instrument(level = "trace", skip(tcx))] fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptions) -> Ty<'tcx> { let mut ty = ty; @@ -698,7 +700,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio !is_zst }); if let Some(field) = field { - let ty0 = tcx.type_of(field.did); + let ty0 = tcx.bound_type_of(field.did).subst(tcx, substs); // Generalize any repr(transparent) user-defined type that is either a pointer // or reference, and either references itself or any other type that contains or // references itself, to avoid a reference cycle. @@ -827,6 +829,7 @@ fn transform_substs<'tcx>( /// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor /// extended type qualifiers and types for Rust types that are not used at the FFI boundary. +#[instrument(level = "trace", skip(tcx))] pub fn typeid_for_fnabi<'tcx>( tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 988cd401f40..4512db49403 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2291,7 +2291,7 @@ impl Target { } else { return Some(Err(format!( "'{}' is not a valid value for lld-flavor. \ - Use 'darwin', 'gnu', 'link' or 'wasm.", + Use 'darwin', 'gnu', 'link' or 'wasm'.", s))) } Some(Ok(())) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 8f317beaa77..8a08c7533aa 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2771,7 +2771,7 @@ impl<'v> Visitor<'v> for FindTypeParam { // and suggest `T: ?Sized` regardless of their obligations. This is fine because the errors // in that case should make what happened clear enough. match ty.kind { - hir::TyKind::Ptr(_) | hir::TyKind::Rptr(..) | hir::TyKind::TraitObject(..) => {} + hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {} hir::TyKind::Path(hir::QPath::Resolved(None, path)) if path.segments.len() == 1 && path.segments[0].ident.name == self.param => { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 9656bfbf4ec..7c21a1047bc 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1291,29 +1291,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives() { let hir = self.tcx.hir(); - if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) { - if let hir::Node::Expr(expr) = node { - // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` - // and if not maybe suggest doing something else? If we kept the expression around we - // could also check if it is an fn call (very likely) and suggest changing *that*, if - // it is from the local crate. - err.span_suggestion( - span, - "remove the `.await`", - "", - Applicability::MachineApplicable, - ); - // FIXME: account for associated `async fn`s. - if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr { - if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = - obligation.predicate.kind().skip_binder() - { - err.span_label( - *span, - &format!("this call returns `{}`", pred.self_ty()), - ); - } - if let Some(typeck_results) = &self.typeck_results + if let Some(hir::Node::Expr(expr)) = hir_id.and_then(|hir_id| hir.find(hir_id)) { + // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` + // and if not maybe suggest doing something else? If we kept the expression around we + // could also check if it is an fn call (very likely) and suggest changing *that*, if + // it is from the local crate. + err.span_suggestion( + span, + "remove the `.await`", + "", + Applicability::MachineApplicable, + ); + // FIXME: account for associated `async fn`s. + if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr { + if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = + obligation.predicate.kind().skip_binder() + { + err.span_label(*span, &format!("this call returns `{}`", pred.self_ty())); + } + if let Some(typeck_results) = &self.typeck_results && let ty = typeck_results.expr_ty_adjusted(base) && let ty::FnDef(def_id, _substs) = ty.kind() && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) = @@ -1339,7 +1335,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } } - } } } } @@ -2519,6 +2514,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ObligationCauseCode::VariableType(hir_id) => { let parent_node = self.tcx.hir().get_parent_node(hir_id); match self.tcx.hir().find(parent_node) { + Some(Node::Local(hir::Local { ty: Some(ty), .. })) => { + err.span_suggestion_verbose( + ty.span.shrink_to_lo(), + "consider borrowing here", + "&", + Applicability::MachineApplicable, + ); + err.note("all local variables must have a statically known size"); + } Some(Node::Local(hir::Local { init: Some(hir::Expr { kind: hir::ExprKind::Index(_, _), span, .. }), .. @@ -2688,7 +2692,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Don't print the tuple of capture types 'print: { if !is_upvar_tys_infer_tuple { - let msg = format!("required because it appears within the type `{}`", ty); + let msg = with_forced_trimmed_paths!(format!( + "required because it appears within the type `{ty}`", + )); match ty.kind() { ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) { Some(ident) => err.span_note(ident.span, &msg), @@ -2729,7 +2735,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut msg = "required because it captures the following types: ".to_owned(); for ty in bound_tys.skip_binder() { - write!(msg, "`{}`, ", ty).unwrap(); + with_forced_trimmed_paths!(write!(msg, "`{}`, ", ty).unwrap()); } err.note(msg.trim_end_matches(", ")) } @@ -2740,7 +2746,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let kind = tcx.generator_kind(def_id).unwrap().descr(); err.span_note( sp, - &format!("required because it's used within this {}", kind), + with_forced_trimmed_paths!(&format!( + "required because it's used within this {kind}", + )), ) } ty::Closure(def_id, _) => err.span_note( @@ -2964,7 +2972,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty)); err.span_label( expr_span, - format!("return type was inferred to be `{expr_ty}` here"), + with_forced_trimmed_paths!(format!( + "return type was inferred to be `{expr_ty}` here", + )), ); } } @@ -3227,7 +3237,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { })) = call_node { if Some(rcvr.span) == err.span.primary_span() { - err.replace_span_with(path.ident.span); + err.replace_span_with(path.ident.span, true); } } if let Some(Node::Expr(hir::Expr { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5276da2e49c..f7614997585 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2284,7 +2284,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( obligation.param_env, cause.clone(), obligation.recursion_depth + 1, - tcx.bound_trait_impl_trait_tys(impl_fn_def_id) + tcx.bound_return_position_impl_trait_in_trait_tys(impl_fn_def_id) .map_bound(|tys| { tys.map_or_else(|_| tcx.ty_error(), |tys| tys[&obligation.predicate.def_id]) }) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f6fe71fbd4f..466641ea6df 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -12,8 +12,8 @@ use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::{ - self, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, - ToPolyTraitRef, ToPredicate, Ty, TyCtxt, + self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, + ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, }; use rustc_span::def_id::DefId; @@ -98,8 +98,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Future(vtable_future) } - FnPointerCandidate { .. } => { - let data = self.confirm_fn_pointer_candidate(obligation)?; + FnPointerCandidate { is_const } => { + let data = self.confirm_fn_pointer_candidate(obligation, is_const)?; ImplSource::FnPointer(data) } @@ -597,17 +597,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_fn_pointer_candidate( &mut self, obligation: &TraitObligation<'tcx>, + is_const: bool, ) -> Result<ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); + let tcx = self.tcx(); let self_ty = self .infcx .shallow_resolve(obligation.self_ty().no_bound_vars()) .expect("fn pointer should not capture bound vars from predicate"); - let sig = self_ty.fn_sig(self.tcx()); + let sig = self_ty.fn_sig(tcx); let trait_ref = closure_trait_ref_and_return_type( - self.tcx(), + tcx, obligation.predicate.def_id(), self_ty, sig, @@ -616,9 +618,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_bound(|(trait_ref, _)| trait_ref); let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + let cause = obligation.derived_cause(BuiltinDerivedObligation); + + if obligation.is_const() && !is_const { + // function is a trait method + if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) { + let trait_ref = TraitRef::from_method(tcx, trait_id, *substs); + let poly_trait_pred = Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst); + let obligation = Obligation::new(tcx, cause.clone(), obligation.param_env, poly_trait_pred); + nested.push(obligation); + } + } // Confirm the `type Output: Sized;` bound that is present on `FnOnce` - let cause = obligation.derived_cause(BuiltinDerivedObligation); let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output()); let output_ty = normalize_with_depth_to( self, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 81e8f9e914c..760b4585f4e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1374,6 +1374,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { FutureCandidate => {} // FnDef where the function is const FnPointerCandidate { is_const: true } => {} + FnPointerCandidate { is_const: false } => { + if let ty::FnDef(def_id, _) = obligation.self_ty().skip_binder().kind() && tcx.trait_of_item(*def_id).is_some() { + // Trait methods are not seen as const unless the trait is implemented as const. + // We do not filter that out in here, but nested obligations will be needed to confirm this. + } else { + continue + } + } ConstDestructCandidate(_) => {} _ => { // reject all other types of candidates diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index f3ca6a6c779..b5df583e3f4 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,6 +1,5 @@ use rustc_errors::Diagnostic; use rustc_span::Span; -use smallvec::smallvec; use smallvec::SmallVec; use rustc_data_structures::fx::FxHashSet; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index d644cbccea1..73d2d278f93 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -273,9 +273,11 @@ fn adjust_for_rust_scalar<'tcx>( | PointerKind::UniqueBorrowed | PointerKind::UniqueBorrowedPinned => false, PointerKind::UniqueOwned => noalias_for_box, - PointerKind::Frozen => !is_return, + PointerKind::Frozen => true, }; - if no_alias { + // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics + // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>). + if no_alias && !is_return { attrs.set(ArgAttribute::NoAlias); } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 2da98d33429..8d46ba320fc 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -194,7 +194,7 @@ fn resolve_associated_item<'tcx>( && trait_item_id != leaf_def.item.def_id && let Some(leaf_def_item) = leaf_def.item.def_id.as_local() { - tcx.compare_assoc_const_impl_item_with_trait_item(( + tcx.compare_impl_const(( leaf_def_item, trait_item_id, ))?; diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index e5fbfc55761..a2fdec6fbfe 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -23,7 +23,7 @@ extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute // (the code expanding that attribute macro generates those functions), or to call - // the default implementations in libstd (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) + // the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) // otherwise. // The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them // like `malloc`, `realloc`, and `free`, respectively. @@ -404,19 +404,6 @@ pub mod __alloc_error_handler { pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { panic!("memory allocation of {size} bytes failed") } - - #[cfg(bootstrap)] - #[rustc_std_internal_symbol] - pub unsafe fn __rg_oom(size: usize, align: usize) -> ! { - use crate::alloc::Layout; - - let layout = unsafe { Layout::from_size_align_unchecked(size, align) }; - extern "Rust" { - #[lang = "oom"] - fn oom_impl(layout: Layout) -> !; - } - unsafe { oom_impl(layout) } - } } /// Specialize clones into pre-allocated, uninitialized memory. diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index b154688fb08..a563b258723 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -158,7 +158,6 @@ use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] use core::iter::FromIterator; use core::iter::{FusedIterator, Iterator}; -#[cfg(not(bootstrap))] use core::marker::Tuple; use core::marker::{Destruct, Unpin, Unsize}; use core::mem; @@ -954,7 +953,7 @@ impl<T: ?Sized> Box<T> { /// [`Layout`]: crate::Layout #[stable(feature = "box_raw", since = "1.4.0")] #[inline] - #[must_use = "call `drop(from_raw(ptr))` if you intend to drop the `Box`"] + #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"] pub unsafe fn from_raw(raw: *mut T) -> Self { unsafe { Self::from_raw_in(raw, Global) } } @@ -1981,17 +1980,6 @@ impl<I: ExactSizeIterator + ?Sized, A: Allocator> ExactSizeIterator for Box<I, A #[stable(feature = "fused", since = "1.26.0")] impl<I: FusedIterator + ?Sized, A: Allocator> FusedIterator for Box<I, A> {} -#[cfg(bootstrap)] -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<Args, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> { - type Output = <F as FnOnce<Args>>::Output; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output { - <F as FnOnce<Args>>::call_once(*self, args) - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F, A> { type Output = <F as FnOnce<Args>>::Output; @@ -2001,15 +1989,6 @@ impl<Args: Tuple, F: FnOnce<Args> + ?Sized, A: Allocator> FnOnce<Args> for Box<F } } -#[cfg(bootstrap)] -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<Args, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> { - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { - <F as FnMut<Args>>::call_mut(self, args) - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args: Tuple, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, A> { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { @@ -2017,15 +1996,6 @@ impl<Args: Tuple, F: FnMut<Args> + ?Sized, A: Allocator> FnMut<Args> for Box<F, } } -#[cfg(bootstrap)] -#[stable(feature = "boxed_closure_impls", since = "1.35.0")] -impl<Args, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> { - extern "rust-call" fn call(&self, args: Args) -> Self::Output { - <F as Fn<Args>>::call(self, args) - } -} - -#[cfg(not(bootstrap))] #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl<Args: Tuple, F: Fn<Args> + ?Sized, A: Allocator> Fn<Args> for Box<F, A> { extern "rust-call" fn call(&self, args: Args) -> Self::Output { diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs index 5a05215aeed..fe08e0e10e8 100644 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ b/library/alloc/src/collections/binary_heap/tests.rs @@ -1,8 +1,8 @@ use super::*; use crate::boxed::Box; +use crate::testing::crash_test::{CrashTestDummy, Panic}; use std::iter::TrustedLen; use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::sync::atomic::{AtomicU32, Ordering}; #[test] fn test_iterator() { @@ -291,33 +291,83 @@ fn test_drain_sorted() { #[test] fn test_drain_sorted_leak() { - static DROPS: AtomicU32 = AtomicU32::new(0); - - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] - struct D(u32, bool); - - impl Drop for D { - fn drop(&mut self) { - DROPS.fetch_add(1, Ordering::SeqCst); - - if self.1 { - panic!("panic in `drop`"); - } - } - } - + let d0 = CrashTestDummy::new(0); + let d1 = CrashTestDummy::new(1); + let d2 = CrashTestDummy::new(2); + let d3 = CrashTestDummy::new(3); + let d4 = CrashTestDummy::new(4); + let d5 = CrashTestDummy::new(5); let mut q = BinaryHeap::from(vec![ - D(0, false), - D(1, false), - D(2, false), - D(3, true), - D(4, false), - D(5, false), + d0.spawn(Panic::Never), + d1.spawn(Panic::Never), + d2.spawn(Panic::Never), + d3.spawn(Panic::InDrop), + d4.spawn(Panic::Never), + d5.spawn(Panic::Never), ]); - catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok(); + catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).unwrap_err(); + + assert_eq!(d0.dropped(), 1); + assert_eq!(d1.dropped(), 1); + assert_eq!(d2.dropped(), 1); + assert_eq!(d3.dropped(), 1); + assert_eq!(d4.dropped(), 1); + assert_eq!(d5.dropped(), 1); + assert!(q.is_empty()); +} - assert_eq!(DROPS.load(Ordering::SeqCst), 6); +#[test] +fn test_drain_forget() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut q = + BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); + + catch_unwind(AssertUnwindSafe(|| { + let mut it = q.drain(); + it.next(); + mem::forget(it); + })) + .unwrap(); + // Behaviour after leaking is explicitly unspecified and order is arbitrary, + // so it's fine if these start failing, but probably worth knowing. + assert!(q.is_empty()); + assert_eq!(a.dropped() + b.dropped() + c.dropped(), 1); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); + drop(q); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); +} + +#[test] +fn test_drain_sorted_forget() { + let a = CrashTestDummy::new(0); + let b = CrashTestDummy::new(1); + let c = CrashTestDummy::new(2); + let mut q = + BinaryHeap::from(vec![a.spawn(Panic::Never), b.spawn(Panic::Never), c.spawn(Panic::Never)]); + + catch_unwind(AssertUnwindSafe(|| { + let mut it = q.drain_sorted(); + it.next(); + mem::forget(it); + })) + .unwrap(); + // Behaviour after leaking is explicitly unspecified, + // so it's fine if these start failing, but probably worth knowing. + assert_eq!(q.len(), 2); + assert_eq!(a.dropped(), 0); + assert_eq!(b.dropped(), 0); + assert_eq!(c.dropped(), 1); + drop(q); + assert_eq!(a.dropped(), 1); + assert_eq!(b.dropped(), 1); + assert_eq!(c.dropped(), 1); } #[test] diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 4c372b1d60a..700b1463bfd 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1,12 +1,12 @@ -use super::super::testing::crash_test::{CrashTestDummy, Panic}; -use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor}; -use super::super::testing::rng::DeterministicRng; use super::Entry::{Occupied, Vacant}; use super::*; use crate::boxed::Box; use crate::fmt::Debug; use crate::rc::Rc; use crate::string::{String, ToString}; +use crate::testing::crash_test::{CrashTestDummy, Panic}; +use crate::testing::ord_chaos::{Cyclic3, Governed, Governor}; +use crate::testing::rng::DeterministicRng; use crate::vec::Vec; use std::cmp::Ordering; use std::convert::TryFrom; diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index 9d43ac5c5be..7552f2fc04c 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -21,6 +21,3 @@ trait Recover<Q: ?Sized> { fn take(&mut self, key: &Q) -> Option<Self::Key>; fn replace(&mut self, key: Self::Key) -> Option<Self::Key>; } - -#[cfg(test)] -mod testing; diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index da766b67a32..6912466448f 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -318,7 +318,10 @@ impl<BorrowType: marker::BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> pub fn ascend( self, ) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> { - let _ = BorrowType::TRAVERSAL_PERMIT; + const { + assert!(BorrowType::TRAVERSAL_PERMIT); + } + // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. let leaf_ptr: *const _ = Self::as_leaf_ptr(&self); @@ -1003,7 +1006,10 @@ impl<BorrowType: marker::BorrowType, K, V> /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should /// both, upon success, do nothing. pub fn descend(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> { - let _ = BorrowType::TRAVERSAL_PERMIT; + const { + assert!(BorrowType::TRAVERSAL_PERMIT); + } + // We need to use raw pointers to nodes because, if BorrowType is // marker::ValMut, there might be outstanding mutable references to // values that we must not invalidate. There's no worry accessing the @@ -1666,17 +1672,17 @@ pub mod marker { pub struct ValMut<'a>(PhantomData<&'a mut ()>); pub trait BorrowType { - // If node references of this borrow type allow traversing to other - // nodes in the tree, this constant can be evaluated. Thus reading it - // serves as a compile-time assertion. - const TRAVERSAL_PERMIT: () = (); + /// If node references of this borrow type allow traversing to other + /// nodes in the tree, this constant is set to `true`. It can be used + /// for a compile-time assertion. + const TRAVERSAL_PERMIT: bool = true; } impl BorrowType for Owned { - // Reject evaluation, because traversal isn't needed. Instead traversal - // happens using the result of `borrow_mut`. - // By disabling traversal, and only creating new references to roots, - // we know that every reference of the `Owned` type is to a root node. - const TRAVERSAL_PERMIT: () = panic!(); + /// Reject traversal, because it isn't needed. Instead traversal + /// happens using the result of `borrow_mut`. + /// By disabling traversal, and only creating new references to roots, + /// we know that every reference of the `Owned` type is to a root node. + const TRAVERSAL_PERMIT: bool = false; } impl BorrowType for Dying {} impl<'a> BorrowType for Immut<'a> {} diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 502d3e1d126..7b8d41a6031 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -1,6 +1,6 @@ -use super::super::testing::crash_test::{CrashTestDummy, Panic}; -use super::super::testing::rng::DeterministicRng; use super::*; +use crate::testing::crash_test::{CrashTestDummy, Panic}; +use crate::testing::rng::DeterministicRng; use crate::vec::Vec; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs index f8fbfa1bfbc..5d5af22bb29 100644 --- a/library/alloc/src/collections/linked_list/tests.rs +++ b/library/alloc/src/collections/linked_list/tests.rs @@ -1,4 +1,5 @@ use super::*; +use crate::testing::crash_test::{CrashTestDummy, Panic}; use crate::vec::Vec; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -984,35 +985,34 @@ fn drain_filter_complex() { #[test] fn drain_filter_drop_panic_leak() { - static mut DROPS: i32 = 0; - - struct D(bool); - - impl Drop for D { - fn drop(&mut self) { - unsafe { - DROPS += 1; - } - - if self.0 { - panic!("panic in `drop`"); - } - } - } - + let d0 = CrashTestDummy::new(0); + let d1 = CrashTestDummy::new(1); + let d2 = CrashTestDummy::new(2); + let d3 = CrashTestDummy::new(3); + let d4 = CrashTestDummy::new(4); + let d5 = CrashTestDummy::new(5); + let d6 = CrashTestDummy::new(6); + let d7 = CrashTestDummy::new(7); let mut q = LinkedList::new(); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_back(D(false)); - q.push_front(D(false)); - q.push_front(D(true)); - q.push_front(D(false)); - - catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok(); - - assert_eq!(unsafe { DROPS }, 8); + q.push_back(d3.spawn(Panic::Never)); + q.push_back(d4.spawn(Panic::Never)); + q.push_back(d5.spawn(Panic::Never)); + q.push_back(d6.spawn(Panic::Never)); + q.push_back(d7.spawn(Panic::Never)); + q.push_front(d2.spawn(Panic::Never)); + q.push_front(d1.spawn(Panic::InDrop)); + q.push_front(d0.spawn(Panic::Never)); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).unwrap_err(); + + assert_eq!(d0.dropped(), 1); + assert_eq!(d1.dropped(), 1); + assert_eq!(d2.dropped(), 1); + assert_eq!(d3.dropped(), 1); + assert_eq!(d4.dropped(), 1); + assert_eq!(d5.dropped(), 1); + assert_eq!(d6.dropped(), 1); + assert_eq!(d7.dropped(), 1); assert!(q.is_empty()); } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 96960d43f58..9857f0516ba 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -3,7 +3,7 @@ //! This library provides smart pointers and collections for managing //! heap-allocated values. //! -//! This library, like libcore, normally doesn’t need to be used directly +//! This library, like core, normally doesn’t need to be used directly //! since its contents are re-exported in the [`std` crate](../std/index.html). //! Crates that use the `#![no_std]` attribute however will typically //! not depend on `std`, so they’d use this crate instead. @@ -75,7 +75,7 @@ ))] #![no_std] #![needs_allocator] -// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be +// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no affect there. #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] @@ -122,6 +122,7 @@ #![feature(fmt_internals)] #![feature(fn_traits)] #![feature(hasher_prefixfree_extras)] +#![feature(inline_const)] #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] @@ -152,7 +153,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] -#![cfg_attr(not(bootstrap), feature(tuple_trait))] +#![feature(tuple_trait)] #![feature(unchecked_math)] #![feature(unicode_internals)] #![feature(unsize)] @@ -206,6 +207,8 @@ extern crate std; #[cfg(test)] extern crate test; +#[cfg(test)] +mod testing; // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 1b61ede3476..4cfb2def098 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -653,7 +653,7 @@ impl [u8] { /// /// ```error /// error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predica -/// --> src/liballoc/slice.rs:608:6 +/// --> library/alloc/src/slice.rs:608:6 /// | /// 608 | impl<T: Clone, V: Borrow<[T]>> Concat for [V] { /// | ^ unconstrained type parameter diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 7a8e6f088f3..24f1b3a1c87 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -363,7 +363,7 @@ use crate::vec::Vec; /// [`as_str()`]: String::as_str #[derive(PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(all(not(bootstrap), not(test)), lang = "String")] +#[cfg_attr(not(test), lang = "String")] pub struct String { vec: Vec<u8>, } @@ -2678,7 +2678,7 @@ impl From<&String> for String { } } -// note: test pulls in libstd, which causes errors here +// note: test pulls in std, which causes errors here #[cfg(not(test))] #[stable(feature = "string_from_box", since = "1.18.0")] impl From<Box<str>> for String { diff --git a/library/alloc/src/collections/btree/testing/crash_test.rs b/library/alloc/src/testing/crash_test.rs index bcf5f5f7251..bcf5f5f7251 100644 --- a/library/alloc/src/collections/btree/testing/crash_test.rs +++ b/library/alloc/src/testing/crash_test.rs diff --git a/library/alloc/src/collections/btree/testing/mod.rs b/library/alloc/src/testing/mod.rs index 7a094f8a595..7a094f8a595 100644 --- a/library/alloc/src/collections/btree/testing/mod.rs +++ b/library/alloc/src/testing/mod.rs diff --git a/library/alloc/src/collections/btree/testing/ord_chaos.rs b/library/alloc/src/testing/ord_chaos.rs index 96ce7c15790..96ce7c15790 100644 --- a/library/alloc/src/collections/btree/testing/ord_chaos.rs +++ b/library/alloc/src/testing/ord_chaos.rs diff --git a/library/alloc/src/collections/btree/testing/rng.rs b/library/alloc/src/testing/rng.rs index ecf543bee03..ecf543bee03 100644 --- a/library/alloc/src/collections/btree/testing/rng.rs +++ b/library/alloc/src/testing/rng.rs diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ba34ab6800f..1da73862d4a 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -166,7 +166,7 @@ mod spec_extend; /// vec[0] = 7; /// assert_eq!(vec[0], 7); /// -/// vec.extend([1, 2, 3].iter().copied()); +/// vec.extend([1, 2, 3]); /// /// for x in &vec { /// println!("{x}"); @@ -3191,7 +3191,7 @@ where } } -// note: test pulls in libstd, which causes errors here +// note: test pulls in std, which causes errors here #[cfg(not(test))] #[stable(feature = "vec_from_box", since = "1.18.0")] impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> { @@ -3209,7 +3209,7 @@ impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> { } } -// note: test pulls in libstd, which causes errors here +// note: test pulls in std, which causes errors here #[cfg(not(no_global_oom_handling))] #[cfg(not(test))] #[stable(feature = "box_from_vec", since = "1.20.0")] diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs index 8ff5f0abe73..879e32b3fa3 100644 --- a/library/alloc/tests/autotraits.rs +++ b/library/alloc/tests/autotraits.rs @@ -32,7 +32,7 @@ fn test_btree_map() { // spawn(f()); // } // - // where with some unintentionally overconstrained Send impls in liballoc's + // where with some unintentionally overconstrained Send impls in alloc's // internals, the future might incorrectly not be Send even though every // single type involved in the program is Send and Sync. require_send_sync(async { diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 7ebed0d5ca6..87adcead8f6 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -7,7 +7,9 @@ use std::borrow::Cow; use std::cell::Cell; use std::collections::TryReserveErrorKind::*; use std::fmt::Debug; +use std::hint; use std::iter::InPlaceIterable; +use std::mem; use std::mem::{size_of, swap}; use std::ops::Bound::*; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -1107,8 +1109,31 @@ fn test_into_iter_drop_allocator() { #[test] fn test_into_iter_zst() { - for _ in vec![[0u64; 0]].into_iter() {} - for _ in vec![[0u64; 0]; 5].into_iter().rev() {} + #[derive(Debug, Clone)] + struct AlignedZstWithDrop([u64; 0]); + impl Drop for AlignedZstWithDrop { + fn drop(&mut self) { + let addr = self as *mut _ as usize; + assert!(hint::black_box(addr) % mem::align_of::<u64>() == 0); + } + } + + const C: AlignedZstWithDrop = AlignedZstWithDrop([0u64; 0]); + + for _ in vec![C].into_iter() {} + for _ in vec![C; 5].into_iter().rev() {} + + let mut it = vec![C, C].into_iter(); + it.advance_by(1).unwrap(); + drop(it); + + let mut it = vec![C, C].into_iter(); + it.next_chunk::<1>().unwrap(); + drop(it); + + let mut it = vec![C, C].into_iter(); + it.next_chunk::<4>().unwrap_err(); + drop(it); } #[test] diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 1a379ecc11c..9ca4947ed8f 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -148,7 +148,7 @@ //! ``` //! //! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then -//! the `get_context_ref` call will return a reference to `obj.some_string` with type `&String`. +//! the `get_context_by_ref` call will return a reference to `obj.some_string` with type `&String`. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index b4e173ce03d..129213fde74 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -807,7 +807,8 @@ impl<T> RefCell<T> { /// /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently borrowed, or + /// if `self` and `other` point to the same `RefCell`. /// /// # Examples /// @@ -1193,7 +1194,7 @@ impl<T: Default> Default for RefCell<T> { impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn eq(&self, other: &RefCell<T>) -> bool { *self.borrow() == *other.borrow() @@ -1207,7 +1208,7 @@ impl<T: ?Sized + Eq> Eq for RefCell<T> {} impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn partial_cmp(&self, other: &RefCell<T>) -> Option<Ordering> { self.borrow().partial_cmp(&*other.borrow()) @@ -1215,7 +1216,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn lt(&self, other: &RefCell<T>) -> bool { *self.borrow() < *other.borrow() @@ -1223,7 +1224,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn le(&self, other: &RefCell<T>) -> bool { *self.borrow() <= *other.borrow() @@ -1231,7 +1232,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn gt(&self, other: &RefCell<T>) -> bool { *self.borrow() > *other.borrow() @@ -1239,7 +1240,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn ge(&self, other: &RefCell<T>) -> bool { *self.borrow() >= *other.borrow() @@ -1250,7 +1251,7 @@ impl<T: ?Sized + PartialOrd> PartialOrd for RefCell<T> { impl<T: ?Sized + Ord> Ord for RefCell<T> { /// # Panics /// - /// Panics if the value in either `RefCell` is currently borrowed. + /// Panics if the value in either `RefCell` is currently mutably borrowed. #[inline] fn cmp(&self, other: &RefCell<T>) -> Ordering { self.borrow().cmp(&*other.borrow()) @@ -1783,7 +1784,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> { /// until the reference expires. As a special exception, given an `&T`, any part of it that is /// inside an `UnsafeCell<_>` may be deallocated during the lifetime of the reference, after the /// last time the reference is used (dereferenced or reborrowed). Since you cannot deallocate a part -/// of what a reference points to, this means the memory an `&T` points to can be deallocted only if +/// of what a reference points to, this means the memory an `&T` points to can be deallocated only if /// *every part of it* (including padding) is inside an `UnsafeCell`. /// /// However, whenever a `&UnsafeCell<T>` is constructed or dereferenced, it must still point to @@ -1993,7 +1994,7 @@ impl<T: ?Sized> UnsafeCell<T> { #[rustc_const_stable(feature = "const_unsafecell_get", since = "1.32.0")] pub const fn get(&self) -> *mut T { // We can just cast the pointer from `UnsafeCell<T>` to `T` because of - // #[repr(transparent)]. This exploits libstd's special status, there is + // #[repr(transparent)]. This exploits std's special status, there is // no guarantee for user code that this will work in future versions of the compiler! self as *const UnsafeCell<T> as *const T as *mut T } @@ -2051,7 +2052,7 @@ impl<T: ?Sized> UnsafeCell<T> { #[rustc_const_stable(feature = "unsafe_cell_raw_get", since = "1.56.0")] pub const fn raw_get(this: *const Self) -> *mut T { // We can just cast the pointer from `UnsafeCell<T>` to `T` because of - // #[repr(transparent)]. This exploits libstd's special status, there is + // #[repr(transparent)]. This exploits std's special status, there is // no guarantee for user code that this will work in future versions of the compiler! this as *const T as *mut T } diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index b355d94ce49..65d12c25c51 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -35,7 +35,7 @@ pub struct LazyCell<T, F = fn() -> T> { init: Cell<Option<F>>, } -impl<T, F> LazyCell<T, F> { +impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// Creates a new lazy value with the given initializing function. /// /// # Examples @@ -51,13 +51,12 @@ impl<T, F> LazyCell<T, F> { /// /// assert_eq!(&*lazy, "HELLO, WORLD!"); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(init: F) -> LazyCell<T, F> { LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) } } -} -impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// Forces the evaluation of this lazy value and returns a reference to /// the result. /// @@ -75,6 +74,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { /// assert_eq!(LazyCell::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &LazyCell<T, F>) -> &T { this.cell.get_or_init(|| match this.init.take() { @@ -87,6 +87,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { type Target = T; + #[inline] fn deref(&self) -> &T { LazyCell::force(self) } @@ -95,6 +96,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Default> Default for LazyCell<T> { /// Creates a new lazy value using `Default` as the initializing function. + #[inline] fn default() -> LazyCell<T> { LazyCell::new(T::default) } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 8c01643c7ac..7757068a4f2 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -37,8 +37,9 @@ pub struct OnceCell<T> { impl<T> OnceCell<T> { /// Creates a new empty cell. - #[unstable(feature = "once_cell", issue = "74465")] + #[inline] #[must_use] + #[unstable(feature = "once_cell", issue = "74465")] pub const fn new() -> OnceCell<T> { OnceCell { inner: UnsafeCell::new(None) } } @@ -46,6 +47,7 @@ impl<T> OnceCell<T> { /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is empty. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get(&self) -> Option<&T> { // SAFETY: Safe due to `inner`'s invariant @@ -55,6 +57,7 @@ impl<T> OnceCell<T> { /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_mut(&mut self) -> Option<&mut T> { self.inner.get_mut().as_mut() @@ -82,6 +85,7 @@ impl<T> OnceCell<T> { /// /// assert!(cell.get().is_some()); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn set(&self, value: T) -> Result<(), T> { // SAFETY: Safe because we cannot have overlapping mutable borrows @@ -123,6 +127,7 @@ impl<T> OnceCell<T> { /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_init<F>(&self, f: F) -> &T where @@ -205,6 +210,7 @@ impl<T> OnceCell<T> { /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn into_inner(self) -> Option<T> { // Because `into_inner` takes `self` by value, the compiler statically verifies @@ -233,6 +239,7 @@ impl<T> OnceCell<T> { /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn take(&mut self) -> Option<T> { mem::take(self).into_inner() @@ -241,6 +248,7 @@ impl<T> OnceCell<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T> Default for OnceCell<T> { + #[inline] fn default() -> Self { Self::new() } @@ -258,6 +266,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceCell<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Clone> Clone for OnceCell<T> { + #[inline] fn clone(&self) -> OnceCell<T> { let res = OnceCell::new(); if let Some(value) = self.get() { @@ -272,6 +281,7 @@ impl<T: Clone> Clone for OnceCell<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: PartialEq> PartialEq for OnceCell<T> { + #[inline] fn eq(&self, other: &Self) -> bool { self.get() == other.get() } @@ -283,6 +293,7 @@ impl<T: Eq> Eq for OnceCell<T> {} #[unstable(feature = "once_cell", issue = "74465")] impl<T> const From<T> for OnceCell<T> { /// Creates a new `OnceCell<T>` which already contains the given `value`. + #[inline] fn from(value: T) -> Self { OnceCell { inner: UnsafeCell::new(Some(value)) } } diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs index 11f1c30f6d5..eeb08803040 100644 --- a/library/core/src/char/decode.rs +++ b/library/core/src/char/decode.rs @@ -67,7 +67,7 @@ impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> { } // all ok, so lets decode it. - let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000; + let c = (((u & 0x3ff) as u32) << 10 | (u2 & 0x3ff) as u32) + 0x1_0000; // SAFETY: we checked that it's a legal unicode value Some(Ok(unsafe { from_u32_unchecked(c) })) } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index c05b68e30bc..3e7383b4cd1 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -140,7 +140,7 @@ impl char { /// assert_eq!(None, c); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] - #[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_u32(i: u32) -> Option<char> { @@ -241,7 +241,7 @@ impl char { /// let _c = char::from_digit(1, 37); /// ``` #[stable(feature = "assoc_char_funcs", since = "1.52.0")] - #[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_digit(num: u32, radix: u32) -> Option<char> { @@ -338,7 +338,7 @@ impl char { /// let _ = '1'.to_digit(37); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 55552376280..af98059cf42 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -110,7 +110,7 @@ pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::Into /// Converts a `u32` to a `char`. Use [`char::from_u32`] instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_u32(i: u32) -> Option<char> { @@ -130,7 +130,7 @@ pub const unsafe fn from_u32_unchecked(i: u32) -> char { /// Converts a digit in the given radix to a `char`. Use [`char::from_digit`] instead. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "const_char_convert", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_char_convert", since = "1.67.0")] #[must_use] #[inline] pub const fn from_digit(num: u32, radix: u32) -> Option<char> { diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 949896e5748..ebf5baa3c02 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -24,8 +24,6 @@ use crate::const_closure::ConstFnMutClosure; use crate::marker::Destruct; -#[cfg(bootstrap)] -use crate::marker::StructuralPartialEq; use self::Ordering::*; @@ -333,7 +331,7 @@ pub struct AssertParamIsEq<T: Eq + ?Sized> { /// assert_eq!(Ordering::Greater, result); /// ``` #[derive(Clone, Copy, Eq, Debug, Hash)] -#[cfg_attr(not(bootstrap), derive_const(PartialOrd, Ord, PartialEq))] +#[derive_const(PartialOrd, Ord, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] #[repr(i8)] pub enum Ordering { @@ -800,9 +798,12 @@ pub trait Ord: Eq + PartialOrd<Self> { Self: Sized, Self: ~const Destruct, { - // HACK(fee1-dead): go back to using `self.max_by(other, Ord::cmp)` - // when trait methods are allowed to be used when a const closure is - // expected. + #[cfg(not(bootstrap))] + { + max_by(self, other, Ord::cmp) + } + + #[cfg(bootstrap)] match self.cmp(&other) { Ordering::Less | Ordering::Equal => other, Ordering::Greater => self, @@ -827,9 +828,12 @@ pub trait Ord: Eq + PartialOrd<Self> { Self: Sized, Self: ~const Destruct, { - // HACK(fee1-dead): go back to using `self.min_by(other, Ord::cmp)` - // when trait methods are allowed to be used when a const closure is - // expected. + #[cfg(not(bootstrap))] + { + min_by(self, other, Ord::cmp) + } + + #[cfg(bootstrap)] match self.cmp(&other) { Ordering::Less | Ordering::Equal => self, Ordering::Greater => other, @@ -879,40 +883,6 @@ pub macro Ord($item:item) { /* compiler built-in */ } -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg(bootstrap)] -impl StructuralPartialEq for Ordering {} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -#[cfg(bootstrap)] -impl const PartialEq for Ordering { - #[inline] - fn eq(&self, other: &Self) -> bool { - (*self as i32).eq(&(*other as i32)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -#[cfg(bootstrap)] -impl const Ord for Ordering { - #[inline] - fn cmp(&self, other: &Ordering) -> Ordering { - (*self as i32).cmp(&(*other as i32)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] -#[cfg(bootstrap)] -impl const PartialOrd for Ordering { - #[inline] - fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> { - (*self as i32).partial_cmp(&(*other as i32)) - } -} - /// Trait for types that form a [partial order](https://en.wikipedia.org/wiki/Partial_order). /// /// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs index 920c31233c1..97900a4862f 100644 --- a/library/core/src/const_closure.rs +++ b/library/core/src/const_closure.rs @@ -1,5 +1,4 @@ use crate::marker::Destruct; -#[cfg(not(bootstrap))] use crate::marker::Tuple; /// Struct representing a closure with mutably borrowed data. @@ -46,33 +45,6 @@ impl<'a, CapturedData: ?Sized, Function> ConstFnMutClosure<&'a mut CapturedData, macro_rules! impl_fn_mut_tuple { ($($var:ident)*) => { - #[cfg(bootstrap)] - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const - FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue + ~const Destruct, - { - type Output = ClosureReturnValue; - - extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output { - self.call_mut(args) - } - } - #[cfg(bootstrap)] - #[allow(unused_parens)] - impl<'a, $($var,)* ClosureArguments, Function, ClosureReturnValue> const - FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> - where - Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue + ~const Destruct, - { - extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output { - #[allow(non_snake_case)] - let ($($var),*) = &mut self.data; - (self.func)(($($var),*), args) - } - } - #[cfg(not(bootstrap))] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> @@ -85,7 +57,6 @@ macro_rules! impl_fn_mut_tuple { self.call_mut(args) } } - #[cfg(not(bootstrap))] #[allow(unused_parens)] impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function> diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 5f4a666de92..51e6a76cea8 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -558,7 +558,7 @@ impl Display for Arguments<'_> { /// /// Derived `Debug` formats are not stable, and so may change with future Rust /// versions. Additionally, `Debug` implementations of types provided by the -/// standard library (`libstd`, `libcore`, `liballoc`, etc.) are not stable, and +/// standard library (`std`, `core`, `alloc`, etc.) are not stable, and /// may also change with future Rust versions. /// /// # Examples diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index f2b961d62e0..5bfe001de46 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -44,7 +44,7 @@ pub use poll_fn::{poll_fn, PollFn}; /// non-Send/Sync as well, and we don't want that. /// /// It also simplifies the HIR lowering of `.await`. -#[cfg_attr(not(bootstrap), lang = "ResumeTy")] +#[lang = "ResumeTy"] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[derive(Debug, Copy, Clone)] @@ -61,7 +61,6 @@ unsafe impl Sync for ResumeTy {} /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). // This is `const` to avoid extra errors after we recover from `const async fn` -#[cfg_attr(bootstrap, lang = "from_generator")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[rustc_const_unstable(feature = "gen_future", issue = "50547")] @@ -113,10 +112,10 @@ pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> { unsafe { &mut *cx.0.as_ptr().cast() } } -#[cfg_attr(not(bootstrap), lang = "identity_future")] #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] #[inline] +#[lang = "identity_future"] pub const fn identity_future<O, Fut: Future<Output = O>>(f: Fut) -> Fut { f } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index a521905a9e7..a315a28fb0d 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -55,7 +55,6 @@ #![allow(missing_docs)] use crate::marker::DiscriminantKind; -#[cfg(not(bootstrap))] use crate::marker::Tuple; use crate::mem; @@ -2175,66 +2174,6 @@ extern "rust-intrinsic" { /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, /// which violates the principle that a `const fn` must behave the same at /// compile-time and at run-time. The unsafe code in crate B is fine. - #[cfg(bootstrap)] - #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] - pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET - where - G: FnOnce<ARG, Output = RET>, - F: FnOnce<ARG, Output = RET>; - - /// Selects which function to call depending on the context. - /// - /// If this function is evaluated at compile-time, then a call to this - /// intrinsic will be replaced with a call to `called_in_const`. It gets - /// replaced with a call to `called_at_rt` otherwise. - /// - /// # Type Requirements - /// - /// The two functions must be both function items. They cannot be function - /// pointers or closures. The first function must be a `const fn`. - /// - /// `arg` will be the tupled arguments that will be passed to either one of - /// the two functions, therefore, both functions must accept the same type of - /// arguments. Both functions must return RET. - /// - /// # Safety - /// - /// The two functions must behave observably equivalent. Safe code in other - /// crates may assume that calling a `const fn` at compile-time and at run-time - /// produces the same result. A function that produces a different result when - /// evaluated at run-time, or has any other observable side-effects, is - /// *unsound*. - /// - /// Here is an example of how this could cause a problem: - /// ```no_run - /// #![feature(const_eval_select)] - /// #![feature(core_intrinsics)] - /// use std::hint::unreachable_unchecked; - /// use std::intrinsics::const_eval_select; - /// - /// // Crate A - /// pub const fn inconsistent() -> i32 { - /// fn runtime() -> i32 { 1 } - /// const fn compiletime() -> i32 { 2 } - /// - /// unsafe { - // // âš This code violates the required equivalence of `compiletime` - /// // and `runtime`. - /// const_eval_select((), compiletime, runtime) - /// } - /// } - /// - /// // Crate B - /// const X: i32 = inconsistent(); - /// let x = inconsistent(); - /// if x != X { unsafe { unreachable_unchecked(); }} - /// ``` - /// - /// This code causes Undefined Behavior when being run, since the - /// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, - /// which violates the principle that a `const fn` must behave the same at - /// compile-time and at run-time. The unsafe code in crate B is fine. - #[cfg(not(bootstrap))] #[rustc_const_unstable(feature = "const_eval_select", issue = "none")] pub fn const_eval_select<ARG: Tuple, F, G, RET>( arg: ARG, @@ -2281,7 +2220,7 @@ macro_rules! assert_unsafe_precondition { fn runtime$(<$($tt)*>)?($($i:$ty),*) { if !$e { // don't unwind to reduce impact on code size - ::core::panicking::panic_str_nounwind( + ::core::panicking::panic_nounwind( concat!("unsafe precondition(s) violated: ", $name) ); } diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 9e7099ddfd1..399d54f18c5 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -60,7 +60,8 @@ //! //! # Examples //! -//! ```rust +#![cfg_attr(bootstrap, doc = "```rust,compile_fail")] +#![cfg_attr(not(bootstrap), doc = "```rust")] //! #![feature(core_intrinsics, custom_mir)] //! //! extern crate core; @@ -291,7 +292,8 @@ define!( /// /// # Examples /// - /// ```rust + #[cfg_attr(bootstrap, doc = "```rust,compile_fail")] + #[cfg_attr(not(bootstrap), doc = "```rust")] /// #![feature(custom_mir, core_intrinsics)] /// /// extern crate core; diff --git a/library/core/src/iter/sources/empty.rs b/library/core/src/iter/sources/empty.rs index 98734c527f2..617dfd12383 100644 --- a/library/core/src/iter/sources/empty.rs +++ b/library/core/src/iter/sources/empty.rs @@ -22,17 +22,12 @@ pub const fn empty<T>() -> Empty<T> { Empty(marker::PhantomData) } -// Newtype for use in `PhantomData` to avoid -// > error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]` -// in `const fn empty<T>()` above. -struct FnReturning<T>(fn() -> T); - /// An iterator that yields nothing. /// /// This `struct` is created by the [`empty()`] function. See its documentation for more. #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "iter_empty", since = "1.2.0")] -pub struct Empty<T>(marker::PhantomData<FnReturning<T>>); +pub struct Empty<T>(marker::PhantomData<fn() -> T>); #[stable(feature = "core_impl_debug", since = "1.9.0")] impl<T> fmt::Debug for Empty<T> { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index bac836292f8..fc4d4bff24f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -66,6 +66,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {} #[must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator { /// The type of the elements being iterated over. + #[rustc_diagnostic_item = "IteratorItem"] #[stable(feature = "rust1", since = "1.0.0")] type Item; @@ -803,7 +804,7 @@ pub trait Iterator { /// (0..5).map(|x| x * 2 + 1) /// .for_each(move |x| tx.send(x).unwrap()); /// - /// let v: Vec<_> = rx.iter().collect(); + /// let v: Vec<_> = rx.iter().collect(); /// assert_eq!(v, vec![1, 3, 5, 7, 9]); /// ``` /// @@ -1380,8 +1381,8 @@ pub trait Iterator { Take::new(self, n) } - /// An iterator adapter similar to [`fold`] that holds internal state and - /// produces a new iterator. + /// An iterator adapter which, like [`fold`], holds internal state, but + /// unlike [`fold`], produces a new iterator. /// /// [`fold`]: Iterator::fold /// @@ -1393,20 +1394,25 @@ pub trait Iterator { /// /// On iteration, the closure will be applied to each element of the /// iterator and the return value from the closure, an [`Option`], is - /// yielded by the iterator. + /// returned by the `next` method. Thus the closure can return + /// `Some(value)` to yield `value`, or `None` to end the iteration. /// /// # Examples /// /// Basic usage: /// /// ``` - /// let a = [1, 2, 3]; + /// let a = [1, 2, 3, 4]; /// /// let mut iter = a.iter().scan(1, |state, &x| { - /// // each iteration, we'll multiply the state by the element + /// // each iteration, we'll multiply the state by the element ... /// *state = *state * x; /// - /// // then, we'll yield the negation of the state + /// // ... and terminate if the state exceeds 6 + /// if *state > 6 { + /// return None; + /// } + /// // ... else yield the negation of the state /// Some(-*state) /// }); /// @@ -2653,7 +2659,10 @@ pub trait Iterator { /// argument is a double reference. You can see this effect in the /// examples below, with `&&x`. /// + /// If you need the index of the element, see [`position()`]. + /// /// [`Some(element)`]: Some + /// [`position()`]: Iterator::position /// /// # Examples /// diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1823fd30062..0e3fef4ead3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -38,18 +38,18 @@ //! which do not trigger a panic can be assured that this function is never //! called. The `lang` attribute is called `eh_personality`. -// Since libcore defines many fundamental lang items, all tests live in a -// separate crate, libcoretest, to avoid bizarre issues. +// Since core defines many fundamental lang items, all tests live in a +// separate crate, libcoretest (library/core/tests), to avoid bizarre issues. // // Here we explicitly #[cfg]-out this whole crate when testing. If we don't do // this, both the generated test artifact and the linked libtest (which -// transitively includes libcore) will both define the same set of lang items, +// transitively includes core) will both define the same set of lang items, // and this will cause the E0152 "found duplicate lang item" error. See // discussion in #50466 for details. // // This cfg won't affect doc tests. #![cfg(not(test))] -// To run libcore tests without x.py without ending up with two copies of libcore, Miri needs to be +// To run core tests without x.py without ending up with two copies of core, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no affect there. #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] @@ -194,7 +194,7 @@ #![feature(const_refs_to_cell)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] -#![cfg_attr(not(bootstrap), feature(derive_const))] +#![feature(derive_const)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] #![feature(rustdoc_internals)] @@ -309,7 +309,7 @@ pub mod f64; #[macro_use] pub mod num; -/* The libcore prelude, not as all-encompassing as the libstd prelude */ +/* The core prelude, not as all-encompassing as the std prelude */ pub mod prelude; @@ -376,12 +376,12 @@ mod const_closure; #[stable(feature = "core_primitive", since = "1.43.0")] pub mod primitive; -// Pull in the `core_arch` crate directly into libcore. The contents of +// Pull in the `core_arch` crate directly into core. The contents of // `core_arch` are in a different repository: rust-lang/stdarch. // -// `core_arch` depends on libcore, but the contents of this module are +// `core_arch` depends on core, but the contents of this module are // set up in such a way that directly pulling it here works such that the -// crate uses the this crate as its libcore. +// crate uses the this crate as its core. #[path = "../../stdarch/crates/core_arch/src/mod.rs"] #[allow( missing_docs, @@ -400,12 +400,12 @@ mod core_arch; #[stable(feature = "simd_arch", since = "1.27.0")] pub mod arch; -// Pull in the `core_simd` crate directly into libcore. The contents of +// Pull in the `core_simd` crate directly into core. The contents of // `core_simd` are in a different repository: rust-lang/portable-simd. // -// `core_simd` depends on libcore, but the contents of this module are +// `core_simd` depends on core, but the contents of this module are // set up in such a way that directly pulling it here works such that the -// crate uses this crate as its libcore. +// crate uses this crate as its core. #[path = "../../portable-simd/crates/core_simd/src/mod.rs"] #[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] #[allow(rustdoc::bare_urls)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index f29cd357d6b..cfc1cabe229 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1461,7 +1461,6 @@ pub(crate) mod builtin { /// [the reference]: ../../../reference/attributes/derive.html #[unstable(feature = "derive_const", issue = "none")] #[rustc_builtin_macro] - #[cfg(not(bootstrap))] pub macro derive_const($item:item) { /* compiler built-in */ } @@ -1516,7 +1515,6 @@ pub(crate) mod builtin { /// Attribute macro applied to a function to register it as a handler for allocation failure. /// /// See also [`std::alloc::handle_alloc_error`](../../../std/alloc/fn.handle_alloc_error.html). - #[cfg(not(bootstrap))] #[unstable(feature = "alloc_error_handler", issue = "51540")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] @@ -1553,7 +1551,6 @@ pub(crate) mod builtin { issue = "23416", reason = "placeholder syntax for type ascription" )] - #[cfg(not(bootstrap))] pub macro type_ascribe($expr:expr, $ty:ty) { /* compiler built-in */ } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 4b85c1112b9..c0fb954ce2d 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -96,7 +96,7 @@ unsafe impl<T: Sync + ?Sized> Send for &T {} )] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable #[rustc_specialization_trait] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Sized { // Empty. } @@ -128,7 +128,7 @@ pub trait Sized { /// [nomicon-coerce]: ../../nomicon/coercions.html #[unstable(feature = "unsize", issue = "18598")] #[lang = "unsize"] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Unsize<T: ?Sized> { // Empty. } @@ -695,7 +695,7 @@ impl<T: ?Sized> StructuralEq for PhantomData<T> {} reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead" )] #[lang = "discriminant_kind"] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait DiscriminantKind { /// The type of the discriminant, which must satisfy the trait /// bounds required by `mem::Discriminant`. @@ -796,7 +796,7 @@ impl<T: ?Sized> Unpin for *mut T {} #[lang = "destruct"] #[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)] #[const_trait] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Destruct {} /// A marker for tuple types. @@ -806,12 +806,12 @@ pub trait Destruct {} #[unstable(feature = "tuple_trait", issue = "none")] #[lang = "tuple_trait"] #[rustc_on_unimplemented(message = "`{Self}` is not a tuple")] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Tuple {} /// A marker for things #[unstable(feature = "pointer_sized_trait", issue = "none")] -#[cfg_attr(not(bootstrap), lang = "pointer_sized")] +#[lang = "pointer_sized"] #[rustc_on_unimplemented( message = "`{Self}` needs to be a pointer-sized type", label = "`{Self}` needs to be a pointer-sized type" diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 2c6a0ba64f2..1308b0770b8 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -428,7 +428,7 @@ impl f32 { self != self } - // FIXME(#50145): `abs` is publicly unavailable in libcore due to + // FIXME(#50145): `abs` is publicly unavailable in core due to // concerns about portability, so this implementation is for // private use internally. #[inline] diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index fd3c18ce29b..2a22c4302b9 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -427,7 +427,7 @@ impl f64 { self != self } - // FIXME(#50145): `abs` is publicly unavailable in libcore due to + // FIXME(#50145): `abs` is publicly unavailable in core due to // concerns about portability, so this implementation is for // private use internally. #[inline] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index e1ab7ac5ff0..57096f43974 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2290,8 +2290,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2313,8 +2313,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2335,8 +2335,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2360,8 +2360,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2396,8 +2396,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2420,8 +2420,8 @@ macro_rules! int_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 6a339b338d9..fbda8f82b1b 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -462,8 +462,8 @@ macro_rules! nonzero_unsigned_operations { #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -486,8 +486,8 @@ macro_rules! nonzero_unsigned_operations { #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1253,7 +1253,7 @@ macro_rules! nonzero_bits { /// #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] /// ``` - #[stable(feature = "nonzero_bits", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "nonzero_bits", since = "1.67.0")] pub const BITS: u32 = <$Int>::BITS; } )+ diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index af74faa90b1..1c97c468628 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -703,8 +703,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".ilog(5), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -726,8 +726,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".ilog2(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -748,8 +748,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".ilog10(), 1);")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[rustc_allow_const_fn_unstable(const_option)] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -773,8 +773,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_ilog(5), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -809,8 +809,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".checked_ilog2(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -831,8 +831,8 @@ macro_rules! uint_impl { /// ``` #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".checked_ilog10(), Some(1));")] /// ``` - #[stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "int_log", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "int_log", since = "1.67.0")] + #[rustc_const_stable(feature = "int_log", since = "1.67.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index 127b047db91..b7e1aee9d84 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -1,4 +1,3 @@ -#[cfg(not(bootstrap))] use crate::marker::Tuple; /// The version of the call operator that takes an immutable receiver. @@ -54,87 +53,6 @@ use crate::marker::Tuple; /// let double = |x| x * 2; /// assert_eq!(call_with_one(double), 2); /// ``` -#[cfg(bootstrap)] -#[lang = "fn"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[rustc_on_unimplemented( - on( - Args = "()", - note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" - ), - on( - _Self = "unsafe fn", - note = "unsafe function cannot be called generically without an unsafe block", - // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string - label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" - ), - message = "expected a `{Fn}<{Args}>` closure, found `{Self}`", - label = "expected an `Fn<{Args}>` closure, found `{Self}`" -)] -#[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] -pub trait Fn<Args>: FnMut<Args> { - /// Performs the call operation. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call(&self, args: Args) -> Self::Output; -} - -/// The version of the call operator that takes an immutable receiver. -/// -/// Instances of `Fn` can be called repeatedly without mutating state. -/// -/// *This trait (`Fn`) is not to be confused with [function pointers] -/// (`fn`).* -/// -/// `Fn` is implemented automatically by closures which only take immutable -/// references to captured variables or don't capture anything at all, as well -/// as (safe) [function pointers] (with some caveats, see their documentation -/// for more details). Additionally, for any type `F` that implements `Fn`, `&F` -/// implements `Fn`, too. -/// -/// Since both [`FnMut`] and [`FnOnce`] are supertraits of `Fn`, any -/// instance of `Fn` can be used as a parameter where a [`FnMut`] or [`FnOnce`] -/// is expected. -/// -/// Use `Fn` as a bound when you want to accept a parameter of function-like -/// type and need to call it repeatedly and without mutating state (e.g., when -/// calling it concurrently). If you do not need such strict requirements, use -/// [`FnMut`] or [`FnOnce`] as bounds. -/// -/// See the [chapter on closures in *The Rust Programming Language*][book] for -/// some more information on this topic. -/// -/// Also of note is the special syntax for `Fn` traits (e.g. -/// `Fn(usize, bool) -> usize`). Those interested in the technical details of -/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. -/// -/// [book]: ../../book/ch13-01-closures.html -/// [function pointers]: fn -/// [nomicon]: ../../nomicon/hrtb.html -/// -/// # Examples -/// -/// ## Calling a closure -/// -/// ``` -/// let square = |x| x * x; -/// assert_eq!(square(5), 25); -/// ``` -/// -/// ## Using a `Fn` parameter -/// -/// ``` -/// fn call_with_one<F>(func: F) -> usize -/// where F: Fn(usize) -> usize { -/// func(1) -/// } -/// -/// let double = |x| x * 2; -/// assert_eq!(call_with_one(double), 2); -/// ``` -#[cfg(not(bootstrap))] #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -222,95 +140,6 @@ pub trait Fn<Args: Tuple>: FnMut<Args> { /// /// assert_eq!(x, 5); /// ``` -#[cfg(bootstrap)] -#[lang = "fn_mut"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[rustc_on_unimplemented( - on( - Args = "()", - note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" - ), - on( - _Self = "unsafe fn", - note = "unsafe function cannot be called generically without an unsafe block", - // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string - label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" - ), - message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`", - label = "expected an `FnMut<{Args}>` closure, found `{Self}`" -)] -#[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] -pub trait FnMut<Args>: FnOnce<Args> { - /// Performs the call operation. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; -} - -/// The version of the call operator that takes a mutable receiver. -/// -/// Instances of `FnMut` can be called repeatedly and may mutate state. -/// -/// `FnMut` is implemented automatically by closures which take mutable -/// references to captured variables, as well as all types that implement -/// [`Fn`], e.g., (safe) [function pointers] (since `FnMut` is a supertrait of -/// [`Fn`]). Additionally, for any type `F` that implements `FnMut`, `&mut F` -/// implements `FnMut`, too. -/// -/// Since [`FnOnce`] is a supertrait of `FnMut`, any instance of `FnMut` can be -/// used where a [`FnOnce`] is expected, and since [`Fn`] is a subtrait of -/// `FnMut`, any instance of [`Fn`] can be used where `FnMut` is expected. -/// -/// Use `FnMut` as a bound when you want to accept a parameter of function-like -/// type and need to call it repeatedly, while allowing it to mutate state. -/// If you don't want the parameter to mutate state, use [`Fn`] as a -/// bound; if you don't need to call it repeatedly, use [`FnOnce`]. -/// -/// See the [chapter on closures in *The Rust Programming Language*][book] for -/// some more information on this topic. -/// -/// Also of note is the special syntax for `Fn` traits (e.g. -/// `Fn(usize, bool) -> usize`). Those interested in the technical details of -/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. -/// -/// [book]: ../../book/ch13-01-closures.html -/// [function pointers]: fn -/// [nomicon]: ../../nomicon/hrtb.html -/// -/// # Examples -/// -/// ## Calling a mutably capturing closure -/// -/// ``` -/// let mut x = 5; -/// { -/// let mut square_x = || x *= x; -/// square_x(); -/// } -/// assert_eq!(x, 25); -/// ``` -/// -/// ## Using a `FnMut` parameter -/// -/// ``` -/// fn do_twice<F>(mut func: F) -/// where F: FnMut() -/// { -/// func(); -/// func(); -/// } -/// -/// let mut x: usize = 1; -/// { -/// let add_two_to_x = || x += 2; -/// do_twice(add_two_to_x); -/// } -/// -/// assert_eq!(x, 5); -/// ``` -#[cfg(not(bootstrap))] #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -390,92 +219,6 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> { /// /// // `consume_and_return_x` can no longer be invoked at this point /// ``` -#[cfg(bootstrap)] -#[lang = "fn_once"] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_paren_sugar] -#[rustc_on_unimplemented( - on( - Args = "()", - note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`" - ), - on( - _Self = "unsafe fn", - note = "unsafe function cannot be called generically without an unsafe block", - // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string - label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" - ), - message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`", - label = "expected an `FnOnce<{Args}>` closure, found `{Self}`" -)] -#[fundamental] // so that regex can rely that `&str: !FnMut` -#[must_use = "closures are lazy and do nothing unless called"] -#[const_trait] -pub trait FnOnce<Args> { - /// The returned type after the call operator is used. - #[lang = "fn_once_output"] - #[stable(feature = "fn_once_output", since = "1.12.0")] - type Output; - - /// Performs the call operation. - #[unstable(feature = "fn_traits", issue = "29625")] - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} - -/// The version of the call operator that takes a by-value receiver. -/// -/// Instances of `FnOnce` can be called, but might not be callable multiple -/// times. Because of this, if the only thing known about a type is that it -/// implements `FnOnce`, it can only be called once. -/// -/// `FnOnce` is implemented automatically by closures that might consume captured -/// variables, as well as all types that implement [`FnMut`], e.g., (safe) -/// [function pointers] (since `FnOnce` is a supertrait of [`FnMut`]). -/// -/// Since both [`Fn`] and [`FnMut`] are subtraits of `FnOnce`, any instance of -/// [`Fn`] or [`FnMut`] can be used where a `FnOnce` is expected. -/// -/// Use `FnOnce` as a bound when you want to accept a parameter of function-like -/// type and only need to call it once. If you need to call the parameter -/// repeatedly, use [`FnMut`] as a bound; if you also need it to not mutate -/// state, use [`Fn`]. -/// -/// See the [chapter on closures in *The Rust Programming Language*][book] for -/// some more information on this topic. -/// -/// Also of note is the special syntax for `Fn` traits (e.g. -/// `Fn(usize, bool) -> usize`). Those interested in the technical details of -/// this can refer to [the relevant section in the *Rustonomicon*][nomicon]. -/// -/// [book]: ../../book/ch13-01-closures.html -/// [function pointers]: fn -/// [nomicon]: ../../nomicon/hrtb.html -/// -/// # Examples -/// -/// ## Using a `FnOnce` parameter -/// -/// ``` -/// fn consume_with_relish<F>(func: F) -/// where F: FnOnce() -> String -/// { -/// // `func` consumes its captured variables, so it cannot be run more -/// // than once. -/// println!("Consumed: {}", func()); -/// -/// println!("Delicious!"); -/// -/// // Attempting to invoke `func()` again will throw a `use of moved -/// // value` error for `func`. -/// } -/// -/// let x = String::from("x"); -/// let consume_and_return_x = move || x; -/// consume_with_relish(consume_and_return_x); -/// -/// // `consume_and_return_x` can no longer be invoked at this point -/// ``` -#[cfg(not(bootstrap))] #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -507,68 +250,6 @@ pub trait FnOnce<Args: Tuple> { extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } -#[cfg(bootstrap)] -mod impls { - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const Fn<A> for &F - where - F: ~const Fn<A>, - { - extern "rust-call" fn call(&self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnMut<A> for &F - where - F: ~const Fn<A>, - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (**self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnOnce<A> for &F - where - F: ~const Fn<A>, - { - type Output = F::Output; - - extern "rust-call" fn call_once(self, args: A) -> F::Output { - (*self).call(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnMut<A> for &mut F - where - F: ~const FnMut<A>, - { - extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output { - (*self).call_mut(args) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")] - impl<A, F: ?Sized> const FnOnce<A> for &mut F - where - F: ~const FnMut<A>, - { - type Output = F::Output; - extern "rust-call" fn call_once(self, args: A) -> F::Output { - (*self).call_mut(args) - } - } -} - -#[cfg(not(bootstrap))] mod impls { use crate::marker::Tuple; diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 461b70c32f3..8338a5d7e5a 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -90,14 +90,14 @@ pub macro unreachable_2021 { ), } -/// An internal trait used by libstd to pass data from libstd to `panic_unwind` -/// and other panic runtimes. Not intended to be stabilized any time soon, do -/// not use. +/// An internal trait used by std to pass data from std to `panic_unwind` and +/// other panic runtimes. Not intended to be stabilized any time soon, do not +/// use. #[unstable(feature = "std_internals", issue = "none")] #[doc(hidden)] pub unsafe trait BoxMeUp { /// Take full ownership of the contents. - /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in libcore. + /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in core. /// /// After this method got called, only some dummy default value is left in `self`. /// Calling this method twice, or calling `get` after calling this method, is an error. diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 1923155ebc1..0d385c9d187 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -157,7 +157,7 @@ impl fmt::Display for PanicInfo<'_> { write!(formatter, "'{}', ", payload)? } // NOTE: we cannot use downcast_ref::<String>() here - // since String is not available in libcore! + // since String is not available in core! // The payload is a String when `std::panic!` is called with multiple arguments, // but in that case the message is also available. diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index a704a00faaa..0146a3c2fbf 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -1,8 +1,8 @@ -//! Panic support for libcore +//! Panic support for core //! //! The core library cannot define panicking, but it does *declare* panicking. This -//! means that the functions inside of libcore are allowed to panic, but to be -//! useful an upstream crate must define panicking for libcore to use. The current +//! means that the functions inside of core are allowed to panic, but to be +//! useful an upstream crate must define panicking for core to use. The current //! interface for panicking is: //! //! ``` @@ -13,7 +13,7 @@ //! This definition allows for panicking with any general message, but it does not //! allow for failing with a `Box<Any>` value. (`PanicInfo` just contains a `&(dyn Any + Send)`, //! for which we fill in a dummy value in `PanicInfo::internal_constructor`.) -//! The reason for this is that libcore is not allowed to allocate. +//! The reason for this is that core is not allowed to allocate. //! //! This module contains a few other panicking functions, but these are just the //! necessary lang items for the compiler. All panics are funneled through this @@ -64,12 +64,13 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { unsafe { panic_impl(&pi) } } -/// Like panic_fmt, but without unwinding and track_caller to reduce the impact on codesize. -/// Also just works on `str`, as a `fmt::Arguments` needs more space to be passed. +/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize. +/// (No `fmt` variant as a `fmt::Arguments` needs more space to be passed.) #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics #[rustc_nounwind] -pub fn panic_str_nounwind(msg: &'static str) -> ! { +pub fn panic_nounwind(msg: &'static str) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } @@ -93,7 +94,7 @@ pub fn panic_str_nounwind(msg: &'static str) -> ! { // Next we define a bunch of higher-level wrappers that all bottom out in the two core functions // above. -/// The underlying implementation of libcore's `panic!` macro when no formatting is used. +/// The underlying implementation of core's `panic!` macro when no formatting is used. // never inline unless panic_immediate_abort to avoid code // bloat at the call sites as much as possible #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] @@ -153,10 +154,11 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { /// any extra arguments (including those synthesized by track_caller). #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] -#[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function +#[cfg_attr(bootstrap, lang = "panic_no_unwind")] // needed by codegen for panic in nounwind function +#[cfg_attr(not(bootstrap), lang = "panic_cannot_unwind")] // needed by codegen for panic in nounwind function #[rustc_nounwind] -fn panic_no_unwind() -> ! { - panic_str_nounwind("panic in a function that cannot unwind") +fn panic_cannot_unwind() -> ! { + panic_nounwind("panic in a function that cannot unwind") } /// This function is used instead of panic_fmt in const eval. diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index 3cd3a3b780e..12f762ef193 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -1,8 +1,8 @@ -//! The libcore prelude +//! The core prelude //! -//! This module is intended for users of libcore which do not link to libstd as -//! well. This module is imported by default when `#![no_std]` is used in the -//! same manner as the standard library's prelude. +//! This module is intended for users of core which do not link to std as well. +//! This module is imported by default when `#![no_std]` is used in the same +//! manner as the standard library's prelude. #![stable(feature = "core_prelude", since = "1.4.0")] diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 2d67d742c68..10525a16f3a 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -75,14 +75,12 @@ pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use crate::macros::builtin::alloc_error_handler; -#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; +pub use crate::macros::builtin::{ + alloc_error_handler, bench, derive, global_allocator, test, test_case, +}; #[unstable(feature = "derive_const", issue = "none")] -#[cfg(not(bootstrap))] pub use crate::macros::builtin::derive_const; #[unstable( @@ -104,5 +102,4 @@ pub use crate::macros::builtin::cfg_eval; issue = "23416", reason = "placeholder syntax for type ascription" )] -#[cfg(not(bootstrap))] pub use crate::macros::builtin::type_ascribe; diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 64a5290c3a2..2123147c7e4 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -10,8 +10,7 @@ use crate::{cmp, fmt, hash, mem, num}; /// are likely not to be supported by actual allocators and linkers. #[unstable(feature = "ptr_alignment_type", issue = "102070")] #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(transparent)] pub struct Alignment(AlignmentEnum); @@ -203,8 +202,7 @@ type AlignmentEnum = AlignmentEnum32; type AlignmentEnum = AlignmentEnum64; #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(u16)] enum AlignmentEnum16 { _Align1Shl0 = 1 << 0, @@ -226,8 +224,7 @@ enum AlignmentEnum16 { } #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(u32)] enum AlignmentEnum32 { _Align1Shl0 = 1 << 0, @@ -265,8 +262,7 @@ enum AlignmentEnum32 { } #[derive(Copy, Clone, Eq)] -#[cfg_attr(bootstrap, derive(PartialEq))] -#[cfg_attr(not(bootstrap), derive_const(PartialEq))] +#[derive_const(PartialEq)] #[repr(u64)] enum AlignmentEnum64 { _Align1Shl0 = 1 << 0, diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index b6373beac5f..0a74c03d70f 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1,6 +1,6 @@ use super::*; use crate::cmp::Ordering::{self, Equal, Greater, Less}; -use crate::intrinsics; +use crate::intrinsics::{self, const_eval_select}; use crate::mem; use crate::slice::{self, SliceIndex}; @@ -34,12 +34,23 @@ impl<T: ?Sized> *const T { #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const fn is_null(self) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. - match (self as *const u8).guaranteed_eq(null()) { - None => false, - Some(res) => res, + #[inline] + fn runtime_impl(ptr: *const u8) -> bool { + ptr.addr() == 0 } + + #[inline] + const fn const_impl(ptr: *const u8) -> bool { + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. + match (ptr).guaranteed_eq(null_mut()) { + None => false, + Some(res) => res, + } + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self as *const u8,), const_impl, runtime_impl) } } /// Casts to a pointer of another type. @@ -1350,26 +1361,6 @@ impl<T: ?Sized> *const T { panic!("align_offset: align is not a power-of-two"); } - #[cfg(bootstrap)] - { - fn rt_impl<T>(p: *const T, align: usize) -> usize { - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(p, align) } - } - - const fn ctfe_impl<T>(_: *const T, _: usize) -> usize { - usize::MAX - } - - // SAFETY: - // It is permissible for `align_offset` to always return `usize::MAX`, - // algorithm correctness can not depend on `align_offset` returning non-max values. - // - // As such the behaviour can't change after replacing `align_offset` with `usize::MAX`, only performance can. - unsafe { intrinsics::const_eval_select((self, align), ctfe_impl, rt_impl) } - } - - #[cfg(not(bootstrap))] { // SAFETY: `align` has been checked to be a power of 2 above unsafe { align_offset(self, align) } @@ -1406,8 +1397,7 @@ impl<T: ?Sized> *const T { /// is never aligned if cast to a type with a stricter alignment than the reference's /// underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1433,8 +1423,7 @@ impl<T: ?Sized> *const T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1460,8 +1449,7 @@ impl<T: ?Sized> *const T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1537,8 +1525,7 @@ impl<T: ?Sized> *const T { /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer /// cannot be stricter aligned than the reference's underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1563,8 +1550,7 @@ impl<T: ?Sized> *const T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1588,8 +1574,7 @@ impl<T: ?Sized> *const T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1613,11 +1598,22 @@ impl<T: ?Sized> *const T { panic!("is_aligned_to: align is not a power-of-two"); } - // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. - // The cast to `()` is used to - // 1. deal with fat pointers; and - // 2. ensure that `align_offset` doesn't actually try to compute an offset. - self.cast::<()>().align_offset(align) == 0 + #[inline] + fn runtime_impl(ptr: *const (), align: usize) -> bool { + ptr.addr() & (align - 1) == 0 + } + + #[inline] + const fn const_impl(ptr: *const (), align: usize) -> bool { + // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. + // The cast to `()` is used to + // 1. deal with fat pointers; and + // 2. ensure that `align_offset` doesn't actually try to compute an offset. + ptr.align_offset(align) == 0 + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) } } } diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index a8604843e96..2ea032d4aff 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -50,7 +50,7 @@ use crate::hash::{Hash, Hasher}; /// /// [`to_raw_parts`]: *const::to_raw_parts #[lang = "pointee_trait"] -#[cfg_attr(not(bootstrap), rustc_deny_explicit_impl)] +#[rustc_deny_explicit_impl] pub trait Pointee { /// The type for metadata in pointers and references to `Self`. #[lang = "metadata_type"] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 48b2e88da28..5f30029eaa0 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -516,6 +516,27 @@ pub const fn null<T: ?Sized + Thin>() -> *const T { from_raw_parts(invalid(0), ()) } +/// Creates a null mutable raw pointer. +/// +/// # Examples +/// +/// ``` +/// use std::ptr; +/// +/// let p: *mut i32 = ptr::null_mut(); +/// assert!(p.is_null()); +/// ``` +#[inline(always)] +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_promotable] +#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] +#[rustc_allow_const_fn_unstable(ptr_metadata)] +#[rustc_diagnostic_item = "ptr_null_mut"] +pub const fn null_mut<T: ?Sized + Thin>() -> *mut T { + from_raw_parts_mut(invalid_mut(0), ()) +} + /// Creates an invalid pointer with the given address. /// /// This is different from `addr as *const T`, which creates a pointer that picks up a previously @@ -663,25 +684,26 @@ where addr as *mut T } -/// Creates a null mutable raw pointer. +/// Convert a reference to a raw pointer. /// -/// # Examples -/// -/// ``` -/// use std::ptr; +/// This is equivalent to `r as *const T`, but is a bit safer since it will never silently change +/// type or mutability, in particular if the code is refactored. +#[inline(always)] +#[must_use] +#[unstable(feature = "ptr_from_ref", issue = "106116")] +pub fn from_ref<T: ?Sized>(r: &T) -> *const T { + r +} + +/// Convert a mutable reference to a raw pointer. /// -/// let p: *mut i32 = ptr::null_mut(); -/// assert!(p.is_null()); -/// ``` +/// This is equivalent to `r as *mut T`, but is a bit safer since it will never silently change +/// type or mutability, in particular if the code is refactored. #[inline(always)] #[must_use] -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_promotable] -#[rustc_const_stable(feature = "const_ptr_null", since = "1.24.0")] -#[rustc_allow_const_fn_unstable(ptr_metadata)] -#[rustc_diagnostic_item = "ptr_null_mut"] -pub const fn null_mut<T: ?Sized + Thin>() -> *mut T { - from_raw_parts_mut(invalid_mut(0), ()) +#[unstable(feature = "ptr_from_ref", issue = "106116")] +pub fn from_mut<T: ?Sized>(r: &mut T) -> *mut T { + r } /// Forms a raw slice from a pointer and a length. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 7a5d9a70594..d70fb70c79f 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1,6 +1,6 @@ use super::*; use crate::cmp::Ordering::{self, Equal, Greater, Less}; -use crate::intrinsics; +use crate::intrinsics::{self, const_eval_select}; use crate::slice::{self, SliceIndex}; impl<T: ?Sized> *mut T { @@ -33,12 +33,23 @@ impl<T: ?Sized> *mut T { #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] #[inline] pub const fn is_null(self) -> bool { - // Compare via a cast to a thin pointer, so fat pointers are only - // considering their "data" part for null-ness. - match (self as *mut u8).guaranteed_eq(null_mut()) { - None => false, - Some(res) => res, + #[inline] + fn runtime_impl(ptr: *mut u8) -> bool { + ptr.addr() == 0 } + + #[inline] + const fn const_impl(ptr: *mut u8) -> bool { + // Compare via a cast to a thin pointer, so fat pointers are only + // considering their "data" part for null-ness. + match (ptr).guaranteed_eq(null_mut()) { + None => false, + Some(res) => res, + } + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self as *mut u8,), const_impl, runtime_impl) } } /// Casts to a pointer of another type. @@ -1618,26 +1629,6 @@ impl<T: ?Sized> *mut T { panic!("align_offset: align is not a power-of-two"); } - #[cfg(bootstrap)] - { - fn rt_impl<T>(p: *mut T, align: usize) -> usize { - // SAFETY: `align` has been checked to be a power of 2 above - unsafe { align_offset(p, align) } - } - - const fn ctfe_impl<T>(_: *mut T, _: usize) -> usize { - usize::MAX - } - - // SAFETY: - // It is permissible for `align_offset` to always return `usize::MAX`, - // algorithm correctness can not depend on `align_offset` returning non-max values. - // - // As such the behaviour can't change after replacing `align_offset` with `usize::MAX`, only performance can. - unsafe { intrinsics::const_eval_select((self, align), ctfe_impl, rt_impl) } - } - - #[cfg(not(bootstrap))] { // SAFETY: `align` has been checked to be a power of 2 above unsafe { align_offset(self, align) } @@ -1674,8 +1665,7 @@ impl<T: ?Sized> *mut T { /// is never aligned if cast to a type with a stricter alignment than the reference's /// underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// #![feature(const_mut_refs)] @@ -1702,8 +1692,7 @@ impl<T: ?Sized> *mut T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1730,8 +1719,7 @@ impl<T: ?Sized> *mut T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1807,8 +1795,7 @@ impl<T: ?Sized> *mut T { /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer /// cannot be stricter aligned than the reference's underlying allocation. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// #![feature(const_mut_refs)] @@ -1834,8 +1821,7 @@ impl<T: ?Sized> *mut T { /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime /// pointer is aligned, even if the compiletime pointer wasn't aligned. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1860,8 +1846,7 @@ impl<T: ?Sized> *mut T { /// If a pointer is created from a fixed address, this function behaves the same during /// runtime and compiletime. /// - #[cfg_attr(bootstrap, doc = "```ignore")] - #[cfg_attr(not(bootstrap), doc = "```")] + /// ``` /// #![feature(pointer_is_aligned)] /// #![feature(const_pointer_is_aligned)] /// @@ -1885,11 +1870,22 @@ impl<T: ?Sized> *mut T { panic!("is_aligned_to: align is not a power-of-two"); } - // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. - // The cast to `()` is used to - // 1. deal with fat pointers; and - // 2. ensure that `align_offset` doesn't actually try to compute an offset. - self.cast::<()>().align_offset(align) == 0 + #[inline] + fn runtime_impl(ptr: *mut (), align: usize) -> bool { + ptr.addr() & (align - 1) == 0 + } + + #[inline] + const fn const_impl(ptr: *mut (), align: usize) -> bool { + // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead. + // The cast to `()` is used to + // 1. deal with fat pointers; and + // 2. ensure that `align_offset` doesn't actually try to compute an offset. + ptr.align_offset(align) == 0 + } + + // SAFETY: The two versions are equivalent at runtime. + unsafe { const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl) } } } diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 87f77b7f21d..b8c0c3fd949 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -3,7 +3,7 @@ //! This module contains a sorting algorithm based on Orson Peters' pattern-defeating quicksort, //! published at: <https://github.com/orlp/pdqsort> //! -//! Unstable sorting is compatible with libcore because it doesn't allocate memory, unlike our +//! Unstable sorting is compatible with core because it doesn't allocate memory, unlike our //! stable sorting implementation. use crate::cmp; diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 863ded5e5ec..ab2f8520ecb 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -368,7 +368,7 @@ impl str { #[inline(always)] pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` - // has the same layout as `&[u8]` (only libstd can make this guarantee). + // has the same layout as `&[u8]` (only std can make this guarantee). // The pointer dereference is safe since it comes from a mutable reference which // is guaranteed to be valid for writes. unsafe { &mut *(self as *mut str as *mut [u8]) } diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index f1dc4f7b575..25b61c0e666 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -9,7 +9,7 @@ use crate::task::Ready; /// scheduled to receive a wakeup instead. #[must_use = "this `Poll` may be a `Pending` variant, which should be handled"] #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -#[cfg_attr(not(bootstrap), lang = "Poll")] +#[lang = "Poll"] #[stable(feature = "futures_api", since = "1.36.0")] pub enum Poll<T> { /// Represents that a value is immediately ready. diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 1b7578376b4..a4425fd234a 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -181,6 +181,9 @@ pub struct Context<'a> { // are contravariant while return-position lifetimes are // covariant). _marker: PhantomData<fn(&'a ()) -> &'a ()>, + // Ensure `Context` is `!Send` and `!Sync` in order to allow + // for future `!Send` and / or `!Sync` fields. + _marker2: PhantomData<*mut ()>, } impl<'a> Context<'a> { @@ -190,7 +193,7 @@ impl<'a> Context<'a> { #[must_use] #[inline] pub const fn from_waker(waker: &'a Waker) -> Self { - Context { waker, _marker: PhantomData } + Context { waker, _marker: PhantomData, _marker2: PhantomData } } /// Returns a reference to the [`Waker`] for the current task. diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 72fa059b787..e1faa407d54 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -17,7 +17,7 @@ mod unicode_data; #[stable(feature = "unicode_version", since = "1.45.0")] pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; -// For use in liballoc, not re-exported in libstd. +// For use in alloc, not re-exported in std. pub use unicode_data::{ case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions, }; diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index e98dac8d12e..a8f6b7ebb92 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -131,7 +131,6 @@ fn distinct_type_names() { assert_ne!(type_name_of_val(Velocity), type_name_of_val(Velocity(0.0, -9.8)),); } -#[cfg(not(bootstrap))] #[test] fn dyn_type_name() { trait Foo { diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs index 8542e5c70d4..ac0b2ca168b 100644 --- a/library/core/tests/char.rs +++ b/library/core/tests/char.rs @@ -306,6 +306,10 @@ fn test_decode_utf16() { } check(&[0xD800, 0x41, 0x42], &[Err(0xD800), Ok('A'), Ok('B')]); check(&[0xD800, 0], &[Err(0xD800), Ok('\0')]); + check(&[0xD800], &[Err(0xD800)]); + check(&[0xD840, 0xDC00], &[Ok('\u{20000}')]); + check(&[0xD840, 0xD840, 0xDC00], &[Err(0xD840), Ok('\u{20000}')]); + check(&[0xDC00, 0xD840], &[Err(0xDC00), Err(0xD840)]); } #[test] diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index 70fcc6d2d4b..c7c3c479b71 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -106,6 +106,12 @@ fn lazy_new() { assert_eq!(called.get(), 1); } +// Check that we can infer `T` from closure's type. +#[test] +fn lazy_type_inference() { + let _ = LazyCell::new(|| ()); +} + #[test] fn aliasing_in_get() { let x = OnceCell::new(); diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 1cfb4fd9fd1..f7740a114e7 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -77,7 +77,6 @@ fn align_of_val_basic() { } #[test] -#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails fn align_of_val_raw_packed() { #[repr(C, packed)] struct B { diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 90bc8351080..80d30f14c66 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -359,7 +359,6 @@ fn align_offset_zst() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_zst_const() { const { // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at @@ -397,7 +396,6 @@ fn align_offset_stride_one() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_stride_one_const() { const { // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to @@ -493,7 +491,6 @@ fn align_offset_various_strides() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_various_strides_const() { const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) { let mut expected = usize::MAX; @@ -561,7 +558,6 @@ fn align_offset_various_strides_const() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_with_provenance_const() { const { // On some platforms (e.g. msp430-none-elf), the alignment of `i32` is less than 4. @@ -681,7 +677,6 @@ fn align_offset_issue_103361() { } #[test] -#[cfg(not(bootstrap))] fn align_offset_issue_103361_const() { #[cfg(target_pointer_width = "64")] const SIZE: usize = 1 << 47; @@ -715,7 +710,6 @@ fn is_aligned() { } #[test] -#[cfg(not(bootstrap))] fn is_aligned_const() { const { let data = 42; @@ -735,18 +729,6 @@ fn is_aligned_const() { } #[test] -#[cfg(bootstrap)] -fn is_aligned_const() { - const { - let data = 42; - let ptr: *const i32 = &data; - // The bootstrap compiler always returns false for is_aligned. - assert!(!ptr.is_aligned()); - assert!(!ptr.is_aligned_to(1)); - } -} - -#[test] fn offset_from() { let mut a = [0; 5]; let ptr1: *mut i32 = &mut a[1]; @@ -825,7 +807,7 @@ fn ptr_metadata_bounds() { } // "Synthetic" trait impls generated by the compiler like those of `Pointee` // are not checked for bounds of associated type. - // So with a buggy libcore we could have both: + // So with a buggy core we could have both: // * `<dyn Display as Pointee>::Metadata == DynMetadata` // * `DynMetadata: !PartialEq` // … and cause an ICE here: diff --git a/library/core/tests/str.rs b/library/core/tests/str.rs index ed939ca7139..f5066343af2 100644 --- a/library/core/tests/str.rs +++ b/library/core/tests/str.rs @@ -1 +1 @@ -// All `str` tests live in liballoc/tests +// All `str` tests live in library/alloc/tests/str.rs diff --git a/library/core/tests/task.rs b/library/core/tests/task.rs index 56be30e9282..163b34c9648 100644 --- a/library/core/tests/task.rs +++ b/library/core/tests/task.rs @@ -1,4 +1,4 @@ -use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; +use core::task::{Poll, RawWaker, RawWakerVTable, Waker}; #[test] fn poll_const() { @@ -21,9 +21,5 @@ fn waker_const() { static WAKER: Waker = unsafe { Waker::from_raw(VOID_WAKER) }; - static CONTEXT: Context<'static> = Context::from_waker(&WAKER); - - static WAKER_REF: &'static Waker = CONTEXT.waker(); - - WAKER_REF.wake_by_ref(); + WAKER.wake_by_ref(); } diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index cba8ef25db6..a3cebf99c53 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -61,7 +61,7 @@ pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail // - // Note: this is the same implementation as in libstd's `abort_internal` + // Note: this is the same implementation as in std's `abort_internal` unsafe fn abort() -> ! { #[allow(unused)] const FAST_FAIL_FATAL_APP_EXIT: usize = 7; @@ -89,7 +89,7 @@ pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // This... is a bit of an oddity. The tl;dr; is that this is required to link // correctly, the longer explanation is below. // -// Right now the binaries of libcore/libstd that we ship are all compiled with +// Right now the binaries of core/std that we ship are all compiled with // `-C panic=unwind`. This is done to ensure that the binaries are maximally // compatible with as many situations as possible. The compiler, however, // requires a "personality function" for all functions compiled with `-C @@ -109,7 +109,7 @@ pub unsafe fn __rust_start_panic(_payload: *mut &mut dyn BoxMeUp) -> u32 { // library just defines this symbol so there's at least some personality // somewhere. // -// Essentially this symbol is just defined to get wired up to libcore/libstd +// Essentially this symbol is just defined to get wired up to core/std // binaries, but it should never be called as we don't link in an unwinding // runtime at all. pub mod personalities { diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 7e7180a38e2..ea3c9a7a663 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -82,11 +82,11 @@ cfg_if::cfg_if! { } extern "C" { - /// Handler in libstd called when a panic object is dropped outside of + /// Handler in std called when a panic object is dropped outside of /// `catch_unwind`. fn __rust_drop_panic() -> !; - /// Handler in libstd called when a foreign exception is caught. + /// Handler in std called when a foreign exception is caught. fn __rust_foreign_exception() -> !; } diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 506b2a773cc..52a08cad911 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -356,7 +356,7 @@ impl<I, O> Clone for Client<I, O> { fn maybe_install_panic_hook(force_show_panics: bool) { // Hide the default panic output within `proc_macro` expansions. - // NB. the server can't do this because it may use a different libstd. + // NB. the server can't do this because it may use a different std. static HIDE_PANICS_DURING_EXPANSION: Once = Once::new(); HIDE_PANICS_DURING_EXPANSION.call_once(|| { let prev = panic::take_hook(); diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs index 4b1e412e24b..17bd0a1b336 100644 --- a/library/proc_macro/src/bridge/fxhash.rs +++ b/library/proc_macro/src/bridge/fxhash.rs @@ -15,9 +15,9 @@ use std::ops::BitXor; /// Type alias for a hashmap using the `fx` hash algorithm. pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>; -/// A speedy hash algorithm for use within rustc. The hashmap in liballoc -/// by default uses SipHash which isn't quite as speedy as we want. In the -/// compiler we're not really worried about DOS attempts, so we use a fast +/// A speedy hash algorithm for use within rustc. The hashmap in alloc by +/// default uses SipHash which isn't quite as speedy as we want. In the compiler +/// we're not really worried about DOS attempts, so we use a fast /// non-cryptographic hash. /// /// This is the same as the algorithm used by Firefox -- which is a homespun diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 8202c40d631..2ea87d866ff 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -112,7 +112,7 @@ macro_rules! define_dispatcher_impl { $name::$method(server, $($arg),*) }; // HACK(eddyb) don't use `panic::catch_unwind` in a panic. - // If client and server happen to use the same `libstd`, + // If client and server happen to use the same `std`, // `catch_unwind` asserts that the panic counter was 0, // even when the closure passed to it didn't panic. let r = if thread::panicking() { diff --git a/library/rustc-std-workspace-alloc/lib.rs b/library/rustc-std-workspace-alloc/lib.rs index c38a8d2f204..87db7af44ae 100644 --- a/library/rustc-std-workspace-alloc/lib.rs +++ b/library/rustc-std-workspace-alloc/lib.rs @@ -3,7 +3,7 @@ // See rustc-std-workspace-core for why this crate is needed. -// Rename the crate to avoid conflicting with the alloc module in liballoc. +// Rename the crate to avoid conflicting with the alloc module in alloc. extern crate alloc as foo; pub use foo::*; diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 9cb74f951dd..7543ffadd41 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -23,10 +23,10 @@ //! //! ## Platform support //! -//! Not all platforms that libstd compiles for support capturing backtraces. -//! Some platforms simply do nothing when capturing a backtrace. To check -//! whether the platform supports capturing backtraces you can consult the -//! `BacktraceStatus` enum as a result of `Backtrace::status`. +//! Not all platforms that std compiles for support capturing backtraces. Some +//! platforms simply do nothing when capturing a backtrace. To check whether the +//! platform supports capturing backtraces you can consult the `BacktraceStatus` +//! enum as a result of `Backtrace::status`. //! //! Like above with accuracy platform support is done on a best effort basis. //! Sometimes libraries might not be available at runtime or something may go diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 781ae03ad45..601c01c2128 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -166,7 +166,7 @@ impl Repr { // `new_unchecked` is safe. let res = Self(unsafe { NonNull::new_unchecked(tagged) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will - // only run in libstd's tests, unless the user uses -Zbuild-std) + // only run in std's tests, unless the user uses -Zbuild-std) debug_assert!(matches!(res.data(), ErrorData::Custom(_)), "repr(custom) encoding failed"); res } @@ -177,7 +177,7 @@ impl Repr { // Safety: `TAG_OS` is not zero, so the result of the `|` is not 0. let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will - // only run in libstd's tests, unless the user uses -Zbuild-std) + // only run in std's tests, unless the user uses -Zbuild-std) debug_assert!( matches!(res.data(), ErrorData::Os(c) if c == code), "repr(os) encoding failed for {code}" @@ -191,7 +191,7 @@ impl Repr { // Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0. let res = Self(unsafe { NonNull::new_unchecked(ptr::invalid_mut(utagged)) }, PhantomData); // quickly smoke-check we encoded the right thing (This generally will - // only run in libstd's tests, unless the user uses -Zbuild-std) + // only run in std's tests, unless the user uses -Zbuild-std) debug_assert!( matches!(res.data(), ErrorData::Simple(k) if k == kind), "repr(simple) encoding failed {:?}", @@ -348,7 +348,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> { // that our encoding relies on for correctness and soundness. (Some of these are // a bit overly thorough/cautious, admittedly) // -// If any of these are hit on a platform that libstd supports, we should likely +// If any of these are hit on a platform that std supports, we should likely // just use `repr_unpacked.rs` there instead (unless the fix is easy). macro_rules! static_assert { ($condition:expr) => { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 23a13523fc2..de528e85368 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2137,8 +2137,10 @@ pub trait BufRead: Read { } /// Read all bytes until a newline (the `0xA` byte) is reached, and append - /// them to the provided buffer. You do not need to clear the buffer before - /// appending. + /// them to the provided `String` buffer. + /// + /// Previous content of the buffer will be preserved. To avoid appending to + /// the buffer, you need to [`clear`] it first. /// /// This function will read bytes from the underlying stream until the /// newline delimiter (the `0xA` byte) or EOF is found. Once found, all bytes @@ -2151,9 +2153,11 @@ pub trait BufRead: Read { /// /// This function is blocking and should be used carefully: it is possible for /// an attacker to continuously send bytes without ever sending a newline - /// or EOF. + /// or EOF. You can use [`take`] to limit the maximum number of bytes read. /// /// [`Ok(0)`]: Ok + /// [`clear`]: String::clear + /// [`take`]: crate::io::Read::take /// /// # Errors /// diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 1141a957d87..14bfef4c7aa 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -10,9 +10,8 @@ use crate::fmt; use crate::fs::File; use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines}; use crate::sync::atomic::{AtomicBool, Ordering}; -use crate::sync::{Arc, Mutex, MutexGuard, OnceLock}; +use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard}; use crate::sys::stdio; -use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; type LocalStream = Arc<Mutex<Vec<u8>>>; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 65d4c3c891e..13dfd41abbf 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -202,7 +202,7 @@ no_global_oom_handling, not(no_global_oom_handling) ))] -// To run libstd tests without x.py without ending up with two copies of libstd, Miri needs to be +// To run std tests without x.py without ending up with two copies of std, Miri needs to be // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>. // rustc itself never sets the feature, so this line has no affect there. #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] @@ -532,7 +532,7 @@ pub mod process; pub mod sync; pub mod time; -// Pull in `std_float` crate into libstd. The contents of +// Pull in `std_float` crate into std. The contents of // `std_float` are in a different repository: rust-lang/portable-simd. #[path = "../../portable-simd/crates/std_float/src/lib.rs"] #[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] @@ -602,7 +602,7 @@ mod personality; #[allow(dead_code, unused_attributes, fuzzy_provenance_casts)] mod backtrace_rs; -// Re-export macros defined in libcore. +// Re-export macros defined in core. #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::{ @@ -610,7 +610,7 @@ pub use core::{ unimplemented, unreachable, write, writeln, }; -// Re-export built-in macros defined through libcore. +// Re-export built-in macros defined through core. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow(deprecated)] pub use core::{ diff --git a/library/std/src/net/ip_addr.rs b/library/std/src/net/ip_addr.rs index 5453853e138..07f08c1b586 100644 --- a/library/std/src/net/ip_addr.rs +++ b/library/std/src/net/ip_addr.rs @@ -1195,6 +1195,9 @@ impl Ipv6Addr { /// An IPv6 address representing localhost: `::1`. /// + /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other + /// languages. + /// /// # Examples /// /// ``` @@ -1203,11 +1206,15 @@ impl Ipv6Addr { /// let addr = Ipv6Addr::LOCALHOST; /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); /// ``` + #[doc(alias = "IN6ADDR_LOOPBACK_INIT")] + #[doc(alias = "in6addr_loopback")] #[stable(feature = "ip_constructors", since = "1.30.0")] pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); /// An IPv6 address representing the unspecified address: `::` /// + /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages. + /// /// # Examples /// /// ``` @@ -1216,6 +1223,8 @@ impl Ipv6Addr { /// let addr = Ipv6Addr::UNSPECIFIED; /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); /// ``` + #[doc(alias = "IN6ADDR_ANY_INIT")] + #[doc(alias = "in6addr_any")] #[stable(feature = "ip_constructors", since = "1.30.0")] pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0); diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index c4f022de021..9fa8f5702a8 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -114,6 +114,9 @@ where /// aborting the process as well. This function *only* catches unwinding panics, /// not those that abort the process. /// +/// Note that if a custom panic hook has been set, it will be invoked before +/// the panic is caught, before unwinding. +/// /// Also note that unwinding into Rust code with a foreign exception (e.g. /// an exception thrown from C++ code) is undefined behavior. /// diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 1039835bbbd..b30dd8eecd8 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -517,7 +517,7 @@ pub fn panicking() -> bool { !panic_count::count_is_zero() } -/// Entry point of panics from the libcore crate (`panic_impl` lang item). +/// Entry point of panics from the core crate (`panic_impl` lang item). #[cfg(not(test))] #[panic_handler] pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { @@ -699,7 +699,11 @@ fn rust_panic_with_hook( // have limited options. Currently our preference is to // just abort. In the future we may consider resuming // unwinding or otherwise exiting the thread cleanly. - rtprintpanic!("thread panicked while panicking. aborting.\n"); + if !can_unwind { + rtprintpanic!("thread caused non-unwinding panic. aborting.\n"); + } else { + rtprintpanic!("thread panicked while panicking. aborting.\n"); + } crate::sys::abort_internal(); } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 73b5056e932..19d8f1edaf4 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -306,7 +306,7 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr { // This casts are safe as OsStr is internally a wrapper around [u8] on all // platforms. // - // Note that currently this relies on the special knowledge that libstd has; + // Note that currently this relies on the special knowledge that std has; // these types are single-element structs but are not marked // repr(transparent) or repr(C) which would make these casts not allowable // outside std. @@ -1246,6 +1246,9 @@ impl PathBuf { /// and `path` is not empty, the new path is normalized: all references /// to `.` and `..` are removed. /// + /// Consider using [`Path::join`] if you need a new `PathBuf` instead of + /// using this function on a cloned `PathBuf`. + /// /// # Examples /// /// Pushing a relative path extends the existing path: @@ -1411,7 +1414,8 @@ impl PathBuf { self.push(file_name); } - /// Updates [`self.extension`] to `extension`. + /// Updates [`self.extension`] to `Some(extension)` or to `None` if + /// `extension` is empty. /// /// Returns `false` and does nothing if [`self.file_name`] is [`None`], /// returns `true` and updates the extension otherwise. @@ -1419,6 +1423,20 @@ impl PathBuf { /// If [`self.extension`] is [`None`], the extension is added; otherwise /// it is replaced. /// + /// If `extension` is the empty string, [`self.extension`] will be [`None`] + /// afterwards, not `Some("")`. + /// + /// # Caveats + /// + /// The new `extension` may contain dots and will be used in its entirety, + /// but only the part after the final dot will be reflected in + /// [`self.extension`]. + /// + /// If the file stem contains internal dots and `extension` is empty, part + /// of the old file stem will be considered the new [`self.extension`]. + /// + /// See the examples below. + /// /// [`self.file_name`]: Path::file_name /// [`self.extension`]: Path::extension /// @@ -1432,8 +1450,20 @@ impl PathBuf { /// p.set_extension("force"); /// assert_eq!(Path::new("/feel/the.force"), p.as_path()); /// - /// p.set_extension("dark_side"); - /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path()); + /// p.set_extension("dark.side"); + /// assert_eq!(Path::new("/feel/the.dark.side"), p.as_path()); + /// + /// p.set_extension("cookie"); + /// assert_eq!(Path::new("/feel/the.dark.cookie"), p.as_path()); + /// + /// p.set_extension(""); + /// assert_eq!(Path::new("/feel/the.dark"), p.as_path()); + /// + /// p.set_extension(""); + /// assert_eq!(Path::new("/feel/the"), p.as_path()); + /// + /// p.set_extension(""); + /// assert_eq!(Path::new("/feel/the"), p.as_path()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool { diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index a5a798078eb..2aefd7c513d 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -59,14 +59,12 @@ pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; // Do not `doc(no_inline)` so that they become doc items on their own // (no public module for them to be re-exported from). -#[cfg(not(bootstrap))] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use core::prelude::v1::alloc_error_handler; -#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; +pub use core::prelude::v1::{ + alloc_error_handler, bench, derive, global_allocator, test, test_case, +}; #[unstable(feature = "derive_const", issue = "none")] -#[cfg(not(bootstrap))] pub use core::prelude::v1::derive_const; // Do not `doc(no_inline)` either. @@ -91,7 +89,6 @@ pub use core::prelude::v1::cfg_eval; issue = "23416", reason = "placeholder syntax for type ascription" )] -#[cfg(not(bootstrap))] pub use core::prelude::v1::type_ascribe; // The file so far is equivalent to src/libcore/prelude/v1.rs, diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 17aff342c15..62ce2cb33dc 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1038,6 +1038,15 @@ impl fmt::Debug for Command { /// Format the program and arguments of a Command for display. Any /// non-utf8 data is lossily converted using the utf8 replacement /// character. + /// + /// The default format approximates a shell invocation of the program along with its + /// arguments. It does not include most of the other command properties. The output is not guaranteed to work + /// (e.g. due to lack of shell-escaping or differences in path resolution) + /// On some platforms you can use [the alternate syntax] to show more fields. + /// + /// Note that the debug implementation is platform-specific. + /// + /// [the alternate syntax]: fmt#sign0 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } @@ -2155,18 +2164,11 @@ pub fn id() -> u32 { /// to provide similar functionality. #[cfg_attr(not(test), lang = "termination")] #[stable(feature = "termination_trait_lib", since = "1.61.0")] -#[rustc_on_unimplemented( - on( - all(not(bootstrap), cause = "MainFunctionType"), - message = "`main` has invalid return type `{Self}`", - label = "`main` can only return types that implement `{Termination}`" - ), - on( - bootstrap, - message = "`main` has invalid return type `{Self}`", - label = "`main` can only return types that implement `{Termination}`" - ) -)] +#[rustc_on_unimplemented(on( + cause = "MainFunctionType", + message = "`main` has invalid return type `{Self}`", + label = "`main` can only return types that implement `{Termination}`" +))] pub trait Termination { /// Is called to get the representation of the value as status code. /// This status code is returned to the operating system. diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index 955ad68916c..b4f6cc2daba 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -417,6 +417,100 @@ fn env_empty() { assert!(p.is_ok()); } +#[test] +#[cfg(not(windows))] +#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)] +fn main() { + const PIDFD: &'static str = + if cfg!(target_os = "linux") { " create_pidfd: false,\n" } else { "" }; + + let mut command = Command::new("some-boring-name"); + + assert_eq!(format!("{command:?}"), format!(r#""some-boring-name""#)); + + assert_eq!( + format!("{command:#?}"), + format!( + r#"Command {{ + program: "some-boring-name", + args: [ + "some-boring-name", + ], +{PIDFD}}}"# + ) + ); + + command.args(&["1", "2", "3"]); + + assert_eq!(format!("{command:?}"), format!(r#""some-boring-name" "1" "2" "3""#)); + + assert_eq!( + format!("{command:#?}"), + format!( + r#"Command {{ + program: "some-boring-name", + args: [ + "some-boring-name", + "1", + "2", + "3", + ], +{PIDFD}}}"# + ) + ); + + crate::os::unix::process::CommandExt::arg0(&mut command, "exciting-name"); + + assert_eq!( + format!("{command:?}"), + format!(r#"["some-boring-name"] "exciting-name" "1" "2" "3""#) + ); + + assert_eq!( + format!("{command:#?}"), + format!( + r#"Command {{ + program: "some-boring-name", + args: [ + "exciting-name", + "1", + "2", + "3", + ], +{PIDFD}}}"# + ) + ); + + let mut command_with_env_and_cwd = Command::new("boring-name"); + command_with_env_and_cwd.current_dir("/some/path").env("FOO", "bar"); + assert_eq!( + format!("{command_with_env_and_cwd:?}"), + r#"cd "/some/path" && FOO="bar" "boring-name""# + ); + assert_eq!( + format!("{command_with_env_and_cwd:#?}"), + format!( + r#"Command {{ + program: "boring-name", + args: [ + "boring-name", + ], + env: CommandEnv {{ + clear: false, + vars: {{ + "FOO": Some( + "bar", + ), + }}, + }}, + cwd: Some( + "/some/path", + ), +{PIDFD}}}"# + ) + ); +} + // See issue #91991 #[test] #[cfg(windows)] diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs index 9c2f0c1dd3e..f1eeb75be7c 100644 --- a/library/std/src/rt.rs +++ b/library/std/src/rt.rs @@ -139,9 +139,9 @@ fn lang_start_internal( // mechanism itself. // // There are a couple of instances where unwinding can begin. First is inside of the - // `rt::init`, `rt::cleanup` and similar functions controlled by libstd. In those instances a - // panic is a libstd implementation bug. A quite likely one too, as there isn't any way to - // prevent libstd from accidentally introducing a panic to these functions. Another is from + // `rt::init`, `rt::cleanup` and similar functions controlled by bstd. In those instances a + // panic is a std implementation bug. A quite likely one too, as there isn't any way to + // prevent std from accidentally introducing a panic to these functions. Another is from // user code from `main` or, more nefariously, as described in e.g. issue #86030. // SAFETY: Only called once during runtime initialization. panic::catch_unwind(move || unsafe { init(argc, argv, sigpipe) }).map_err(rt_abort)?; diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index c8d3289ca4a..4a15305301d 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -46,17 +46,15 @@ pub struct LazyLock<T, F = fn() -> T> { cell: OnceLock<T>, init: Cell<Option<F>>, } - -impl<T, F> LazyLock<T, F> { +impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// Creates a new lazy value with the given initializing /// function. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub const fn new(f: F) -> LazyLock<T, F> { LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) } } -} -impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// Forces the evaluation of this lazy value and /// returns a reference to result. This is equivalent /// to the `Deref` impl, but is explicit. @@ -73,6 +71,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { /// assert_eq!(LazyLock::force(&lazy), &92); /// assert_eq!(&*lazy, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn force(this: &LazyLock<T, F>) -> &T { this.cell.get_or_init(|| match this.init.take() { @@ -85,6 +84,8 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> { type Target = T; + + #[inline] fn deref(&self) -> &T { LazyLock::force(self) } @@ -93,6 +94,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Default> Default for LazyLock<T> { /// Creates a new lazy value using `Default` as the initializing function. + #[inline] fn default() -> LazyLock<T> { LazyLock::new(T::default) } diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs index f11b66bfca5..a5d4e25c596 100644 --- a/library/std/src/sync/lazy_lock/tests.rs +++ b/library/std/src/sync/lazy_lock/tests.rs @@ -136,6 +136,12 @@ fn sync_lazy_poisoning() { } } +// Check that we can infer `T` from closure's type. +#[test] +fn lazy_type_inference() { + let _ = LazyCell::new(|| ()); +} + #[test] fn is_sync_send() { fn assert_traits<T: Send + Sync>() {} diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 4fee8d3e92f..ba20bab87a4 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -177,6 +177,8 @@ pub use self::lazy_lock::LazyLock; #[unstable(feature = "once_cell", issue = "74465")] pub use self::once_lock::OnceLock; +pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard}; + pub mod mpsc; mod barrier; @@ -187,4 +189,5 @@ mod mutex; mod once; mod once_lock; mod poison; +mod remutex; mod rwlock; diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs index d0904b4b94c..e030c55ce8f 100644 --- a/library/std/src/sync/mpmc/utils.rs +++ b/library/std/src/sync/mpmc/utils.rs @@ -136,7 +136,7 @@ impl Backoff { } } - /// Returns `true` if exponential backoff has completed and blocking the thread is advised. + /// Returns `true` if quadratic backoff has completed and blocking the thread is advised. #[inline] pub fn is_completed(&self) -> bool { self.step.get() > YIELD_LIMIT diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 16d1fd2a576..ed339ca5df6 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -61,8 +61,9 @@ pub struct OnceLock<T> { impl<T> OnceLock<T> { /// Creates a new empty cell. - #[unstable(feature = "once_cell", issue = "74465")] + #[inline] #[must_use] + #[unstable(feature = "once_cell", issue = "74465")] pub const fn new() -> OnceLock<T> { OnceLock { once: Once::new(), @@ -75,6 +76,7 @@ impl<T> OnceLock<T> { /// /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get(&self) -> Option<&T> { if self.is_initialized() { @@ -88,6 +90,7 @@ impl<T> OnceLock<T> { /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is empty. This method never blocks. + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_mut(&mut self) -> Option<&mut T> { if self.is_initialized() { @@ -125,6 +128,7 @@ impl<T> OnceLock<T> { /// assert_eq!(CELL.get(), Some(&92)); /// } /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn set(&self, value: T) -> Result<(), T> { let mut value = Some(value); @@ -164,6 +168,7 @@ impl<T> OnceLock<T> { /// let value = cell.get_or_init(|| unreachable!()); /// assert_eq!(value, &92); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_init<F>(&self, f: F) -> &T where @@ -203,6 +208,7 @@ impl<T> OnceLock<T> { /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E> where @@ -241,6 +247,7 @@ impl<T> OnceLock<T> { /// cell.set("hello".to_string()).unwrap(); /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn into_inner(mut self) -> Option<T> { self.take() @@ -267,6 +274,7 @@ impl<T> OnceLock<T> { /// assert_eq!(cell.take(), Some("hello".to_string())); /// assert_eq!(cell.get(), None); /// ``` + #[inline] #[unstable(feature = "once_cell", issue = "74465")] pub fn take(&mut self) -> Option<T> { if self.is_initialized() { @@ -315,6 +323,7 @@ impl<T> OnceLock<T> { /// # Safety /// /// The value must be initialized + #[inline] unsafe fn get_unchecked(&self) -> &T { debug_assert!(self.is_initialized()); (&*self.value.get()).assume_init_ref() @@ -323,6 +332,7 @@ impl<T> OnceLock<T> { /// # Safety /// /// The value must be initialized + #[inline] unsafe fn get_unchecked_mut(&mut self) -> &mut T { debug_assert!(self.is_initialized()); (&mut *self.value.get()).assume_init_mut() @@ -360,6 +370,7 @@ impl<T> const Default for OnceLock<T> { /// assert_eq!(OnceLock::<()>::new(), OnceLock::default()); /// } /// ``` + #[inline] fn default() -> OnceLock<T> { OnceLock::new() } @@ -377,6 +388,7 @@ impl<T: fmt::Debug> fmt::Debug for OnceLock<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: Clone> Clone for OnceLock<T> { + #[inline] fn clone(&self) -> OnceLock<T> { let cell = Self::new(); if let Some(value) = self.get() { @@ -408,6 +420,7 @@ impl<T> From<T> for OnceLock<T> { /// Ok(()) /// # } /// ``` + #[inline] fn from(value: T) -> Self { let cell = Self::new(); match cell.set(value) { @@ -419,6 +432,7 @@ impl<T> From<T> for OnceLock<T> { #[unstable(feature = "once_cell", issue = "74465")] impl<T: PartialEq> PartialEq for OnceLock<T> { + #[inline] fn eq(&self, other: &OnceLock<T>) -> bool { self.get() == other.get() } @@ -429,6 +443,7 @@ impl<T: Eq> Eq for OnceLock<T> {} #[unstable(feature = "once_cell", issue = "74465")] unsafe impl<#[may_dangle] T> Drop for OnceLock<T> { + #[inline] fn drop(&mut self) { if self.is_initialized() { // SAFETY: The cell is initialized and being dropped, so it can't diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sync/remutex.rs index 4c054da6471..4c054da6471 100644 --- a/library/std/src/sys_common/remutex.rs +++ b/library/std/src/sync/remutex.rs diff --git a/library/std/src/sys_common/remutex/tests.rs b/library/std/src/sync/remutex/tests.rs index 8e97ce11c34..fc553081d42 100644 --- a/library/std/src/sys_common/remutex/tests.rs +++ b/library/std/src/sync/remutex/tests.rs @@ -1,6 +1,6 @@ +use super::{ReentrantMutex, ReentrantMutexGuard}; use crate::cell::RefCell; use crate::sync::Arc; -use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use crate::thread; #[test] diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index c2b36680872..535703be33f 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -119,7 +119,7 @@ impl Thread { let old_lifecycle = inner .lifecycle - .swap(LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE, Ordering::Release); + .swap(LIFECYCLE_EXITED_OR_FINISHED_OR_JOIN_FINALIZE, Ordering::AcqRel); match old_lifecycle { LIFECYCLE_DETACHED => { @@ -129,9 +129,9 @@ impl Thread { // In this case, `*p_inner`'s ownership has been moved to // us, and we are responsible for dropping it. The acquire - // ordering is not necessary because the parent thread made - // no memory access needing synchronization since the call - // to `acre_tsk`. + // ordering ensures that the swap operation that wrote + // `LIFECYCLE_DETACHED` happens-before `Box::from_raw( + // p_inner)`. // Safety: See above. let _ = unsafe { Box::from_raw(p_inner) }; @@ -151,6 +151,9 @@ impl Thread { // Since the parent might drop `*inner` and terminate us as // soon as it sees `JOIN_FINALIZE`, the release ordering // must be used in the above `swap` call. + // + // To make the task referred to by `parent_tid` visible, we + // must use the acquire ordering in the above `swap` call. // [JOINING → JOIN_FINALIZE] // Wake up the parent task. @@ -218,11 +221,15 @@ impl Thread { let current_task = current_task as usize; - match inner.lifecycle.swap(current_task, Ordering::Acquire) { + match inner.lifecycle.swap(current_task, Ordering::AcqRel) { LIFECYCLE_INIT => { // [INIT → JOINING] // The child task will transition the state to `JOIN_FINALIZE` // and wake us up. + // + // To make the task referred to by `current_task` visible from + // the child task's point of view, we must use the release + // ordering in the above `swap` call. loop { expect_success_aborting(unsafe { abi::slp_tsk() }, &"slp_tsk"); // To synchronize with the child task's memory accesses to @@ -267,15 +274,15 @@ impl Drop for Thread { let inner = unsafe { self.p_inner.as_ref() }; // Detach the thread. - match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) { + match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::AcqRel) { LIFECYCLE_INIT => { // [INIT → DETACHED] // When the time comes, the child will figure out that no // one will ever join it. // The ownership of `*p_inner` is moved to the child thread. - // However, the release ordering is not necessary because we - // made no memory access needing synchronization since the call - // to `acre_tsk`. + // The release ordering ensures that the above swap operation on + // `lifecycle` happens-before the child thread's + // `Box::from_raw(p_inner)`. } LIFECYCLE_FINISHED => { // [FINISHED → JOINED] diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index 63e070207cd..9865a945bad 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -34,7 +34,7 @@ pub mod process; pub mod stdio; pub mod thread; pub mod thread_local_key; -pub mod thread_parker; +pub mod thread_parking; pub mod time; mod condvar; diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs index 579f758c6cc..1608b8cb642 100644 --- a/library/std/src/sys/sgx/thread.rs +++ b/library/std/src/sys/sgx/thread.rs @@ -65,9 +65,9 @@ mod task_queue { /// execution. The signal is sent once all TLS destructors have finished at /// which point no new thread locals should be created. pub mod wait_notify { - use super::super::thread_parker::Parker; use crate::pin::Pin; use crate::sync::Arc; + use crate::sys_common::thread_parking::Parker; pub struct Notifier(Arc<Parker>); @@ -87,14 +87,14 @@ pub mod wait_notify { /// called, this will return immediately, otherwise the current thread /// is blocked until notified. pub fn wait(self) { - // This is not actually `unsafe`, but it uses the `Parker` API, - // which needs `unsafe` on some platforms. + // SAFETY: + // This is only ever called on one thread. unsafe { Pin::new(&*self.0).park() } } } pub fn new() -> (Notifier, Waiter) { - let inner = Arc::new(Parker::new_internal()); + let inner = Arc::new(Parker::new()); (Notifier(inner.clone()), Waiter(inner)) } } diff --git a/library/std/src/sys/sgx/thread_parker.rs b/library/std/src/sys/sgx/thread_parker.rs deleted file mode 100644 index 1c55bcffb1e..00000000000 --- a/library/std/src/sys/sgx/thread_parker.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! Thread parking based on SGX events. - -use super::abi::{thread, usercalls}; -use crate::io::ErrorKind; -use crate::pin::Pin; -use crate::ptr::{self, NonNull}; -use crate::sync::atomic::AtomicPtr; -use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release}; -use crate::time::Duration; -use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE}; - -// The TCS structure must be page-aligned (this is checked by EENTER), so these cannot -// be valid pointers -const EMPTY: *mut u8 = ptr::invalid_mut(1); -const NOTIFIED: *mut u8 = ptr::invalid_mut(2); - -pub struct Parker { - /// The park state. One of EMPTY, NOTIFIED or a TCS address. - /// A state change to NOTIFIED must be done with release ordering - /// and be observed with acquire ordering so that operations after - /// `thread::park` returns will not occur before the unpark message - /// was sent. - state: AtomicPtr<u8>, -} - -impl Parker { - /// Construct the thread parker. The UNIX parker implementation - /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { - unsafe { parker.write(Parker::new_internal()) } - } - - pub(super) fn new_internal() -> Parker { - Parker { state: AtomicPtr::new(EMPTY) } - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park(self: Pin<&Self>) { - if self.state.load(Acquire) != NOTIFIED { - let mut prev = EMPTY; - loop { - // Guard against changing TCS addresses by always setting the state to - // the current value. - let tcs = thread::current().as_ptr(); - if self.state.compare_exchange(prev, tcs, Relaxed, Acquire).is_ok() { - let event = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap(); - assert!(event & EV_UNPARK == EV_UNPARK); - prev = tcs; - } else { - // The state was definitely changed by another thread at this point. - // The only time this occurs is when the state is changed to NOTIFIED. - // We observed this change with acquire ordering, so we can simply - // change the state to EMPTY with a relaxed store. - break; - } - } - } - - // At this point, the token was definately read with acquire ordering, - // so this can be a relaxed store. - self.state.store(EMPTY, Relaxed); - } - - // This implementation doesn't require `unsafe` and `Pin`, but other implementations do. - pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { - let timeout = u128::min(dur.as_nanos(), WAIT_INDEFINITE as u128 - 1) as u64; - let tcs = thread::current().as_ptr(); - - if self.state.load(Acquire) != NOTIFIED { - if self.state.compare_exchange(EMPTY, tcs, Relaxed, Acquire).is_ok() { - match usercalls::wait(EV_UNPARK, timeout) { - Ok(event) => assert!(event & EV_UNPARK == EV_UNPARK), - Err(e) => { - assert!(matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock)) - } - } - - // Swap to provide acquire ordering even if the timeout occurred - // before the token was set. This situation can result in spurious - // wakeups on the next call to `park_timeout`, but it is better to let - // those be handled by the user than do some perhaps unnecessary, but - // always expensive guarding. - self.state.swap(EMPTY, Acquire); - return; - } - } - - // The token was already read with `acquire` ordering, this can be a store. - self.state.store(EMPTY, Relaxed); - } - - // This implementation doesn't require `Pin`, but other implementations do. - pub fn unpark(self: Pin<&Self>) { - let state = self.state.swap(NOTIFIED, Release); - - if !matches!(state, EMPTY | NOTIFIED) { - // There is a thread waiting, wake it up. - let tcs = NonNull::new(state).unwrap(); - // This will fail if the thread has already terminated or its TCS is destroyed - // by the time the signal is sent, but that is fine. If another thread receives - // the same TCS, it will receive this notification as a spurious wakeup, but - // all users of `wait` should and (internally) do guard against those where - // necessary. - let _ = usercalls::send(EV_UNPARK, Some(tcs)); - } - } -} diff --git a/library/std/src/sys/sgx/thread_parking.rs b/library/std/src/sys/sgx/thread_parking.rs new file mode 100644 index 00000000000..0006cd4f1be --- /dev/null +++ b/library/std/src/sys/sgx/thread_parking.rs @@ -0,0 +1,23 @@ +use super::abi::usercalls; +use crate::io::ErrorKind; +use crate::time::Duration; +use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE}; + +pub type ThreadId = fortanix_sgx_abi::Tcs; + +pub use super::abi::thread::current; + +pub fn park(_hint: usize) { + usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap(); +} + +pub fn park_timeout(dur: Duration, _hint: usize) { + let timeout = u128::min(dur.as_nanos(), WAIT_INDEFINITE as u128 - 1) as u64; + if let Err(e) = usercalls::wait(EV_UNPARK, timeout) { + assert!(matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock)) + } +} + +pub fn unpark(tid: ThreadId, _hint: usize) { + let _ = usercalls::send(EV_UNPARK, Some(tid)); +} diff --git a/library/std/src/sys/unix/android.rs b/library/std/src/sys/unix/android.rs index 73ff10ab8a2..0f704994f55 100644 --- a/library/std/src/sys/unix/android.rs +++ b/library/std/src/sys/unix/android.rs @@ -1,7 +1,7 @@ //! Android ABI-compatibility module //! -//! The ABI of Android has changed quite a bit over time, and libstd attempts to -//! be both forwards and backwards compatible as much as possible. We want to +//! The ABI of Android has changed quite a bit over time, and std attempts to be +//! both forwards and backwards compatible as much as possible. We want to //! always work with the most recent version of Android, but we also want to //! work with older versions of Android for whenever projects need to. //! diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index d5f50d77911..aea0c26ee8b 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1754,11 +1754,11 @@ mod remove_dir_impl { use crate::sys::{cvt, cvt_r}; #[cfg(not(any( - target_os = "linux", + all(target_os = "linux", target_env = "gnu"), all(target_os = "macos", not(target_arch = "aarch64")) )))] use libc::{fdopendir, openat, unlinkat}; - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::{fdopendir, openat64 as openat, unlinkat}; #[cfg(all(target_os = "macos", not(target_arch = "aarch64")))] use macos_weak::{fdopendir, openat, unlinkat}; diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 6fa85e859c0..0f7107122b7 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -61,9 +61,9 @@ use crate::ptr; use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use crate::sys::cvt; use crate::sys::weak::syscall; -#[cfg(not(target_os = "linux"))] +#[cfg(not(all(target_os = "linux", target_env = "gnu")))] use libc::sendfile as sendfile64; -#[cfg(target_os = "linux")] +#[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::sendfile64; use libc::{EBADF, EINVAL, ENOSYS, EOPNOTSUPP, EOVERFLOW, EPERM, EXDEV}; diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 3d60941e84e..30a96be1430 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -40,7 +40,7 @@ pub mod stdio; pub mod thread; pub mod thread_local_dtor; pub mod thread_local_key; -pub mod thread_parker; +pub mod thread_parking; pub mod time; #[cfg(target_os = "espidf")] @@ -95,9 +95,9 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { )))] 'poll: { use crate::sys::os::errno; - #[cfg(not(target_os = "linux"))] + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] use libc::open as open64; - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::open64; let pfds: &mut [_] = &mut [ libc::pollfd { fd: 0, events: 0, revents: 0 }, @@ -143,9 +143,9 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { )))] { use crate::sys::os::errno; - #[cfg(not(target_os = "linux"))] + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] use libc::open as open64; - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::open64; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { @@ -164,7 +164,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) { #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))] { - // We don't want to add this as a public type to libstd, nor do we + // We don't want to add this as a public type to std, nor do we // want to `include!` a file from the compiler (which would break // Miri and xargo for example), so we choose to duplicate these // constants from `compiler/rustc_session/src/config/sigpipe.rs`. @@ -184,12 +184,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { sigpipe::SIG_DFL => (true, Some(libc::SIG_DFL)), _ => unreachable!(), }; - // The bootstrap compiler doesn't know about sigpipe::DEFAULT, and always passes in - // SIG_IGN. This causes some tests to fail because they expect SIGPIPE to be reset to - // default on process spawning (which doesn't happen if #[unix_sigpipe] is specified). - // Since we can't differentiate between the cases here, treat SIG_IGN as DEFAULT - // unconditionally. - if sigpipe_attr_specified && !(cfg!(bootstrap) && sigpipe == sigpipe::SIG_IGN) { + if sigpipe_attr_specified { UNIX_SIGPIPE_ATTR_SPECIFIED.store(true, crate::sync::atomic::Ordering::Relaxed); } if let Some(handler) = handler { diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index b84bf8f9264..c86f80972a6 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -512,7 +512,7 @@ impl FromRawFd for Socket { // A workaround for this bug is to call the res_init libc function, to clear // the cached configs. Unfortunately, while we believe glibc's implementation // of res_init is thread-safe, we know that other implementations are not -// (https://github.com/rust-lang/rust/issues/43592). Code here in libstd could +// (https://github.com/rust-lang/rust/issues/43592). Code here in std could // try to synchronize its res_init calls with a Mutex, but that wouldn't // protect programs that call into libc in other ways. So instead of calling // res_init unconditionally, we call it only when we detect we're linking diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 848adca78c0..afd03d79c0b 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -144,6 +144,7 @@ pub enum ChildStdio { Null, } +#[derive(Debug)] pub enum Stdio { Inherit, Null, @@ -510,16 +511,68 @@ impl ChildStdio { } impl fmt::Debug for Command { + // show all attributes but `self.closures` which does not implement `Debug` + // and `self.argv` which is not useful for debugging fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.program != self.args[0] { - write!(f, "[{:?}] ", self.program)?; - } - write!(f, "{:?}", self.args[0])?; + if f.alternate() { + let mut debug_command = f.debug_struct("Command"); + debug_command.field("program", &self.program).field("args", &self.args); + if !self.env.is_unchanged() { + debug_command.field("env", &self.env); + } + + if self.cwd.is_some() { + debug_command.field("cwd", &self.cwd); + } + if self.uid.is_some() { + debug_command.field("uid", &self.uid); + } + if self.gid.is_some() { + debug_command.field("gid", &self.gid); + } + + if self.groups.is_some() { + debug_command.field("groups", &self.groups); + } + + if self.stdin.is_some() { + debug_command.field("stdin", &self.stdin); + } + if self.stdout.is_some() { + debug_command.field("stdout", &self.stdout); + } + if self.stderr.is_some() { + debug_command.field("stderr", &self.stderr); + } + if self.pgroup.is_some() { + debug_command.field("pgroup", &self.pgroup); + } + + #[cfg(target_os = "linux")] + { + debug_command.field("create_pidfd", &self.create_pidfd); + } - for arg in &self.args[1..] { - write!(f, " {:?}", arg)?; + debug_command.finish() + } else { + if let Some(ref cwd) = self.cwd { + write!(f, "cd {cwd:?} && ")?; + } + for (key, value_opt) in self.get_envs() { + if let Some(value) = value_opt { + write!(f, "{}={value:?} ", key.to_string_lossy())?; + } + } + if self.program != self.args[0] { + write!(f, "[{:?}] ", self.program)?; + } + write!(f, "{:?}", self.args[0])?; + + for arg in &self.args[1..] { + write!(f, " {:?}", arg)?; + } + Ok(()) } - Ok(()) } } diff --git a/library/std/src/sys/unix/stack_overflow.rs b/library/std/src/sys/unix/stack_overflow.rs index 957e086798f..b59d4ba26af 100644 --- a/library/std/src/sys/unix/stack_overflow.rs +++ b/library/std/src/sys/unix/stack_overflow.rs @@ -45,9 +45,9 @@ mod imp { use crate::thread; use libc::MAP_FAILED; - #[cfg(not(target_os = "linux"))] + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] use libc::{mmap as mmap64, munmap}; - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::{mmap64, munmap}; use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL}; use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE}; diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index d454a2a717c..b251949bda2 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -505,7 +505,7 @@ mod cgroups { let limit = raw_quota.next()?; let period = raw_quota.next()?; match (limit.parse::<usize>(), period.parse::<usize>()) { - (Ok(limit), Ok(period)) => { + (Ok(limit), Ok(period)) if period > 0 => { quota = quota.min(limit / period); } _ => {} @@ -565,7 +565,7 @@ mod cgroups { let period = parse_file("cpu.cfs_period_us"); match (limit, period) { - (Some(limit), Some(period)) => quota = quota.min(limit / period), + (Some(limit), Some(period)) if period > 0 => quota = quota.min(limit / period), _ => {} } @@ -653,9 +653,9 @@ pub mod guard { ))] #[cfg_attr(test, allow(dead_code))] pub mod guard { - #[cfg(not(target_os = "linux"))] + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] use libc::{mmap as mmap64, mprotect}; - #[cfg(target_os = "linux")] + #[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::{mmap64, mprotect}; use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE}; diff --git a/library/std/src/sys/unix/thread_parker/netbsd.rs b/library/std/src/sys/unix/thread_parker/netbsd.rs deleted file mode 100644 index 7657605b52f..00000000000 --- a/library/std/src/sys/unix/thread_parker/netbsd.rs +++ /dev/null @@ -1,113 +0,0 @@ -use crate::ffi::{c_int, c_void}; -use crate::pin::Pin; -use crate::ptr::{null, null_mut}; -use crate::sync::atomic::{ - AtomicU64, - Ordering::{Acquire, Relaxed, Release}, -}; -use crate::time::Duration; -use libc::{_lwp_self, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC}; - -extern "C" { - fn ___lwp_park60( - clock_id: clockid_t, - flags: c_int, - ts: *mut timespec, - unpark: lwpid_t, - hint: *const c_void, - unparkhint: *const c_void, - ) -> c_int; - fn _lwp_unpark(lwp: lwpid_t, hint: *const c_void) -> c_int; -} - -/// The thread is not parked and the token is not available. -/// -/// Zero cannot be a valid LWP id, since it is used as empty value for the unpark -/// argument in _lwp_park. -const EMPTY: u64 = 0; -/// The token is available. Do not park anymore. -const NOTIFIED: u64 = u64::MAX; - -pub struct Parker { - /// The parker state. Contains either one of the two state values above or the LWP - /// id of the parked thread. - state: AtomicU64, -} - -impl Parker { - pub unsafe fn new(parker: *mut Parker) { - parker.write(Parker { state: AtomicU64::new(EMPTY) }) - } - - // Does not actually need `unsafe` or `Pin`, but the pthread implementation does. - pub unsafe fn park(self: Pin<&Self>) { - // If the token has already been made available, we can skip - // a bit of work, so check for it here. - if self.state.load(Acquire) != NOTIFIED { - let parked = _lwp_self() as u64; - let hint = self.state.as_mut_ptr().cast(); - if self.state.compare_exchange(EMPTY, parked, Relaxed, Acquire).is_ok() { - // Loop to guard against spurious wakeups. - loop { - ___lwp_park60(0, 0, null_mut(), 0, hint, null()); - if self.state.load(Acquire) == NOTIFIED { - break; - } - } - } - } - - // At this point, the change to NOTIFIED has always been observed with acquire - // ordering, so we can just use a relaxed store here (instead of a swap). - self.state.store(EMPTY, Relaxed); - } - - // Does not actually need `unsafe` or `Pin`, but the pthread implementation does. - pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { - if self.state.load(Acquire) != NOTIFIED { - let parked = _lwp_self() as u64; - let hint = self.state.as_mut_ptr().cast(); - let mut timeout = timespec { - // Saturate so that the operation will definitely time out - // (even if it is after the heat death of the universe). - tv_sec: dur.as_secs().try_into().ok().unwrap_or(time_t::MAX), - tv_nsec: dur.subsec_nanos().into(), - }; - - if self.state.compare_exchange(EMPTY, parked, Relaxed, Acquire).is_ok() { - // Timeout needs to be mutable since it is modified on NetBSD 9.0 and - // above. - ___lwp_park60(CLOCK_MONOTONIC, 0, &mut timeout, 0, hint, null()); - // Use a swap to get acquire ordering even if the token was set after - // the timeout occurred. - self.state.swap(EMPTY, Acquire); - return; - } - } - - self.state.store(EMPTY, Relaxed); - } - - // Does not actually need `Pin`, but the pthread implementation does. - pub fn unpark(self: Pin<&Self>) { - let state = self.state.swap(NOTIFIED, Release); - if !matches!(state, EMPTY | NOTIFIED) { - let lwp = state as lwpid_t; - let hint = self.state.as_mut_ptr().cast(); - - // If the parking thread terminated and did not actually park, this will - // probably return an error, which is OK. In the worst case, another - // thread has received the same LWP id. It will then receive a spurious - // wakeup, but those are allowable per the API contract. The same reasoning - // applies if a timeout occurred before this call, but the state was not - // yet reset. - - // SAFETY: - // The syscall has no invariants to hold. Only unsafe because it is an - // extern function. - unsafe { - _lwp_unpark(lwp, hint); - } - } - } -} diff --git a/library/std/src/sys/unix/thread_parker/darwin.rs b/library/std/src/sys/unix/thread_parking/darwin.rs index 2f5356fe227..b709fada3b4 100644 --- a/library/std/src/sys/unix/thread_parker/darwin.rs +++ b/library/std/src/sys/unix/thread_parking/darwin.rs @@ -46,7 +46,7 @@ unsafe impl Sync for Parker {} unsafe impl Send for Parker {} impl Parker { - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { let semaphore = dispatch_semaphore_create(0); assert!( !semaphore.is_null(), diff --git a/library/std/src/sys/unix/thread_parker/mod.rs b/library/std/src/sys/unix/thread_parking/mod.rs index 35f1e68a87e..185333c072f 100644 --- a/library/std/src/sys/unix/thread_parker/mod.rs +++ b/library/std/src/sys/unix/thread_parking/mod.rs @@ -24,7 +24,7 @@ cfg_if::cfg_if! { pub use darwin::Parker; } else if #[cfg(target_os = "netbsd")] { mod netbsd; - pub use netbsd::Parker; + pub use netbsd::{current, park, park_timeout, unpark, ThreadId}; } else { mod pthread; pub use pthread::Parker; diff --git a/library/std/src/sys/unix/thread_parking/netbsd.rs b/library/std/src/sys/unix/thread_parking/netbsd.rs new file mode 100644 index 00000000000..3be08122138 --- /dev/null +++ b/library/std/src/sys/unix/thread_parking/netbsd.rs @@ -0,0 +1,52 @@ +use crate::ffi::{c_int, c_void}; +use crate::ptr; +use crate::time::Duration; +use libc::{_lwp_self, clockid_t, lwpid_t, time_t, timespec, CLOCK_MONOTONIC}; + +extern "C" { + fn ___lwp_park60( + clock_id: clockid_t, + flags: c_int, + ts: *mut timespec, + unpark: lwpid_t, + hint: *const c_void, + unparkhint: *const c_void, + ) -> c_int; + fn _lwp_unpark(lwp: lwpid_t, hint: *const c_void) -> c_int; +} + +pub type ThreadId = lwpid_t; + +#[inline] +pub fn current() -> ThreadId { + unsafe { _lwp_self() } +} + +#[inline] +pub fn park(hint: usize) { + unsafe { + ___lwp_park60(0, 0, ptr::null_mut(), 0, ptr::invalid(hint), ptr::null()); + } +} + +pub fn park_timeout(dur: Duration, hint: usize) { + let mut timeout = timespec { + // Saturate so that the operation will definitely time out + // (even if it is after the heat death of the universe). + tv_sec: dur.as_secs().try_into().ok().unwrap_or(time_t::MAX), + tv_nsec: dur.subsec_nanos().into(), + }; + + // Timeout needs to be mutable since it is modified on NetBSD 9.0 and + // above. + unsafe { + ___lwp_park60(CLOCK_MONOTONIC, 0, &mut timeout, 0, ptr::invalid(hint), ptr::null()); + } +} + +#[inline] +pub fn unpark(tid: ThreadId, hint: usize) { + unsafe { + _lwp_unpark(tid, ptr::invalid(hint)); + } +} diff --git a/library/std/src/sys/unix/thread_parker/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs index c400c771567..082d25e68f5 100644 --- a/library/std/src/sys/unix/thread_parker/pthread.rs +++ b/library/std/src/sys/unix/thread_parking/pthread.rs @@ -44,7 +44,8 @@ unsafe fn wait_timeout( target_os = "macos", target_os = "ios", target_os = "watchos", - target_os = "espidf" + target_os = "espidf", + target_os = "horizon", ))] let (now, dur) = { use crate::cmp::min; @@ -70,7 +71,8 @@ unsafe fn wait_timeout( target_os = "macos", target_os = "ios", target_os = "watchos", - target_os = "espidf" + target_os = "espidf", + target_os = "horizon", )))] let (now, dur) = { use crate::sys::time::Timespec; @@ -97,7 +99,7 @@ impl Parker { /// /// # Safety /// The constructed parker must never be moved. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { // Use the default mutex implementation to allow for simpler initialization. // This could lead to undefined behaviour when deadlocking. This is avoided // by not deadlocking. Note in particular the unlocking operation before any diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index f5a4ce929b2..62ffee70bec 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -1,9 +1,8 @@ //! Support for "weak linkage" to symbols on Unix //! -//! Some I/O operations we do in libstd require newer versions of OSes but we -//! need to maintain binary compatibility with older releases for now. In order -//! to use the new functionality when available we use this module for -//! detection. +//! Some I/O operations we do in std require newer versions of OSes but we need +//! to maintain binary compatibility with older releases for now. In order to +//! use the new functionality when available we use this module for detection. //! //! One option to use here is weak linkage, but that is unfortunately only //! really workable with ELF. Otherwise, use dlsym to get the symbol value at @@ -29,7 +28,7 @@ use crate::ptr; use crate::sync::atomic::{self, AtomicPtr, Ordering}; // We can use true weak linkage on ELF targets. -#[cfg(all(not(any(target_os = "macos", target_os = "ios")), not(bootstrap)))] +#[cfg(not(any(target_os = "macos", target_os = "ios")))] pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = { @@ -43,30 +42,14 @@ pub(crate) macro weak { ) } -#[cfg(all(not(any(target_os = "macos", target_os = "ios")), bootstrap))] -pub(crate) macro weak { - (fn $name:ident($($t:ty),*) -> $ret:ty) => ( - let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = { - extern "C" { - #[linkage = "extern_weak"] - static $name: *const libc::c_void; - } - #[allow(unused_unsafe)] - ExternWeak::new(unsafe { $name }) - }; - ) -} - // On non-ELF targets, use the dlsym approximation of weak linkage. #[cfg(any(target_os = "macos", target_os = "ios"))] pub(crate) use self::dlsym as weak; -#[cfg(not(bootstrap))] pub(crate) struct ExternWeak<F: Copy> { weak_ptr: Option<F>, } -#[cfg(not(bootstrap))] impl<F: Copy> ExternWeak<F> { #[inline] pub(crate) fn new(weak_ptr: Option<F>) -> Self { @@ -79,34 +62,6 @@ impl<F: Copy> ExternWeak<F> { } } -#[cfg(bootstrap)] -pub(crate) struct ExternWeak<F> { - weak_ptr: *const libc::c_void, - _marker: PhantomData<F>, -} - -#[cfg(bootstrap)] -impl<F> ExternWeak<F> { - #[inline] - pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self { - ExternWeak { weak_ptr, _marker: PhantomData } - } -} - -#[cfg(bootstrap)] -impl<F> ExternWeak<F> { - #[inline] - pub(crate) fn get(&self) -> Option<F> { - unsafe { - if self.weak_ptr.is_null() { - None - } else { - Some(mem::transmute_copy::<*const libc::c_void, F>(&self.weak_ptr)) - } - } - } -} - pub(crate) macro dlsym { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( dlsym!(fn $name($($t),*) -> $ret, stringify!($name)); diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index e67411e1686..77359abe429 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -33,7 +33,7 @@ pub mod stdio; pub mod thread; pub mod thread_local_dtor; pub mod thread_local_key; -pub mod thread_parker; +pub mod thread_parking; pub mod time; cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parking.rs index 2f7ae863b6a..5d43676adbb 100644 --- a/library/std/src/sys/windows/thread_parker.rs +++ b/library/std/src/sys/windows/thread_parking.rs @@ -97,7 +97,7 @@ const NOTIFIED: i8 = 1; impl Parker { /// Construct the Windows parker. The UNIX parker implementation /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Self { state: AtomicI8::new(EMPTY) }); } diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index 8807077cb49..f1d804ef40c 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -20,7 +20,7 @@ pub fn lock() -> impl Drop { /// Prints the current backtrace. pub fn print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { // There are issues currently linking libbacktrace into tests, and in - // general during libstd's own unit tests we're not testing this path. In + // general during std's own unit tests we're not testing this path. In // test mode immediately return here to optimize away any references to the // libbacktrace symbols if cfg!(test) { @@ -111,7 +111,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: } /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that -/// this is only inline(never) when backtraces in libstd are enabled, otherwise +/// this is only inline(never) when backtraces in std are enabled, otherwise /// it's fine to optimize away. #[cfg_attr(feature = "backtrace", inline(never))] pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T @@ -127,7 +127,7 @@ where } /// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that -/// this is only inline(never) when backtraces in libstd are enabled, otherwise +/// this is only inline(never) when backtraces in std are enabled, otherwise /// it's fine to optimize away. #[cfg_attr(feature = "backtrace", inline(never))] pub fn __rust_end_short_backtrace<F, T>(f: F) -> T diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index b1987aa0f62..6b24b0e9aa8 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -27,11 +27,10 @@ pub mod lazy_box; pub mod memchr; pub mod once; pub mod process; -pub mod remutex; pub mod thread; pub mod thread_info; pub mod thread_local_dtor; -pub mod thread_parker; +pub mod thread_parking; pub mod wstr; pub mod wtf8; diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index ae11412067b..18883048dae 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -4,12 +4,13 @@ use crate::collections::BTreeMap; use crate::env; use crate::ffi::{OsStr, OsString}; +use crate::fmt; use crate::io; use crate::sys::pipe::read2; use crate::sys::process::{EnvKey, ExitStatus, Process, StdioPipes}; // Stores a set of changes to an environment -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct CommandEnv { clear: bool, saw_path: bool, @@ -22,6 +23,14 @@ impl Default for CommandEnv { } } +impl fmt::Debug for CommandEnv { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut debug_command_env = f.debug_struct("CommandEnv"); + debug_command_env.field("clear", &self.clear).field("vars", &self.vars); + debug_command_env.finish() + } +} + impl CommandEnv { // Capture the current environment with these changes applied pub fn capture(&self) -> BTreeMap<EnvKey, OsString> { diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs index 747579f1781..2672a2a75b0 100644 --- a/library/std/src/sys_common/thread_local_key.rs +++ b/library/std/src/sys_common/thread_local_key.rs @@ -117,10 +117,14 @@ pub struct Key { /// This value specifies no destructor by default. pub const INIT: StaticKey = StaticKey::new(None); +// Define a sentinel value that is unlikely to be returned +// as a TLS key (but it may be returned). +const KEY_SENTVAL: usize = 0; + impl StaticKey { #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")] pub const fn new(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> StaticKey { - StaticKey { key: atomic::AtomicUsize::new(0), dtor } + StaticKey { key: atomic::AtomicUsize::new(KEY_SENTVAL), dtor } } /// Gets the value associated with this TLS key @@ -144,31 +148,36 @@ impl StaticKey { #[inline] unsafe fn key(&self) -> imp::Key { match self.key.load(Ordering::Relaxed) { - 0 => self.lazy_init() as imp::Key, + KEY_SENTVAL => self.lazy_init() as imp::Key, n => n as imp::Key, } } unsafe fn lazy_init(&self) -> usize { - // POSIX allows the key created here to be 0, but the compare_exchange - // below relies on using 0 as a sentinel value to check who won the + // POSIX allows the key created here to be KEY_SENTVAL, but the compare_exchange + // below relies on using KEY_SENTVAL as a sentinel value to check who won the // race to set the shared TLS key. As far as I know, there is no // guaranteed value that cannot be returned as a posix_key_create key, // so there is no value we can initialize the inner key with to // prove that it has not yet been set. As such, we'll continue using a - // value of 0, but with some gyrations to make sure we have a non-0 + // value of KEY_SENTVAL, but with some gyrations to make sure we have a non-KEY_SENTVAL // value returned from the creation routine. // FIXME: this is clearly a hack, and should be cleaned up. let key1 = imp::create(self.dtor); - let key = if key1 != 0 { + let key = if key1 as usize != KEY_SENTVAL { key1 } else { let key2 = imp::create(self.dtor); imp::destroy(key1); key2 }; - rtassert!(key != 0); - match self.key.compare_exchange(0, key as usize, Ordering::SeqCst, Ordering::SeqCst) { + rtassert!(key as usize != KEY_SENTVAL); + match self.key.compare_exchange( + KEY_SENTVAL, + key as usize, + Ordering::SeqCst, + Ordering::SeqCst, + ) { // The CAS succeeded, so we've created the actual key Ok(_) => key as usize, // If someone beat us to the punch, use their key instead diff --git a/library/std/src/sys_common/thread_parker/futex.rs b/library/std/src/sys_common/thread_parking/futex.rs index d9e2f39e345..588e7b27826 100644 --- a/library/std/src/sys_common/thread_parker/futex.rs +++ b/library/std/src/sys_common/thread_parking/futex.rs @@ -35,7 +35,7 @@ pub struct Parker { impl Parker { /// Construct the futex parker. The UNIX parker implementation /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Self { state: AtomicU32::new(EMPTY) }); } diff --git a/library/std/src/sys_common/thread_parker/generic.rs b/library/std/src/sys_common/thread_parking/generic.rs index f3d8b34d3fd..3209bffe353 100644 --- a/library/std/src/sys_common/thread_parker/generic.rs +++ b/library/std/src/sys_common/thread_parking/generic.rs @@ -19,7 +19,7 @@ pub struct Parker { impl Parker { /// Construct the generic parker. The UNIX parker implementation /// requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Parker { state: AtomicUsize::new(EMPTY), lock: Mutex::new(()), diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs new file mode 100644 index 00000000000..e98169597c3 --- /dev/null +++ b/library/std/src/sys_common/thread_parking/id.rs @@ -0,0 +1,108 @@ +//! Thread parking using thread ids. +//! +//! Some platforms (notably NetBSD) have thread parking primitives whose semantics +//! match those offered by `thread::park`, with the difference that the thread to +//! be unparked is referenced by a platform-specific thread id. Since the thread +//! parker is constructed before that id is known, an atomic state variable is used +//! to manage the park state and propagate the thread id. This also avoids platform +//! calls in the case where `unpark` is called before `park`. + +use crate::cell::UnsafeCell; +use crate::pin::Pin; +use crate::sync::atomic::{ + fence, AtomicI8, + Ordering::{Acquire, Relaxed, Release}, +}; +use crate::sys::thread_parking::{current, park, park_timeout, unpark, ThreadId}; +use crate::time::Duration; + +pub struct Parker { + state: AtomicI8, + tid: UnsafeCell<Option<ThreadId>>, +} + +const PARKED: i8 = -1; +const EMPTY: i8 = 0; +const NOTIFIED: i8 = 1; + +impl Parker { + pub fn new() -> Parker { + Parker { state: AtomicI8::new(EMPTY), tid: UnsafeCell::new(None) } + } + + /// Create a new thread parker. UNIX requires this to happen in-place. + pub unsafe fn new_in_place(parker: *mut Parker) { + parker.write(Parker::new()) + } + + /// # Safety + /// * must always be called from the same thread + /// * must be called before the state is set to PARKED + unsafe fn init_tid(&self) { + // The field is only ever written to from this thread, so we don't need + // synchronization to read it here. + if self.tid.get().read().is_none() { + // Because this point is only reached once, before the state is set + // to PARKED for the first time, the non-atomic write here can not + // conflict with reads by other threads. + self.tid.get().write(Some(current())); + // Ensure that the write can be observed by all threads reading the + // state. Synchronizes with the acquire barrier in `unpark`. + fence(Release); + } + } + + pub unsafe fn park(self: Pin<&Self>) { + self.init_tid(); + + // Changes NOTIFIED to EMPTY and EMPTY to PARKED. + let mut state = self.state.fetch_sub(1, Acquire).wrapping_sub(1); + if state == PARKED { + // Loop to guard against spurious wakeups. + while state == PARKED { + park(self.state.as_mut_ptr().addr()); + state = self.state.load(Acquire); + } + + // Since the state change has already been observed with acquire + // ordering, the state can be reset with a relaxed store instead + // of a swap. + self.state.store(EMPTY, Relaxed); + } + } + + pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) { + self.init_tid(); + + let state = self.state.fetch_sub(1, Acquire).wrapping_sub(1); + if state == PARKED { + park_timeout(dur, self.state.as_mut_ptr().addr()); + // Swap to ensure that we observe all state changes with acquire + // ordering, even if the state has been changed after the timeout + // occured. + self.state.swap(EMPTY, Acquire); + } + } + + pub fn unpark(self: Pin<&Self>) { + let state = self.state.swap(NOTIFIED, Release); + if state == PARKED { + // Synchronize with the release fence in `init_tid` to observe the + // write to `tid`. + fence(Acquire); + // # Safety + // The thread id is initialized before the state is set to `PARKED` + // for the first time and is not written to from that point on + // (negating the need for an atomic read). + let tid = unsafe { self.tid.get().read().unwrap_unchecked() }; + // It is possible that the waiting thread woke up because of a timeout + // and terminated before this call is made. This call then returns an + // error or wakes up an unrelated thread. The platform API and + // environment does allow this, however. + unpark(tid, self.state.as_mut_ptr().addr()); + } + } +} + +unsafe impl Send for Parker {} +unsafe impl Sync for Parker {} diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parking/mod.rs index 08a2bdd8229..0ead6633c35 100644 --- a/library/std/src/sys_common/thread_parker/mod.rs +++ b/library/std/src/sys_common/thread_parking/mod.rs @@ -11,13 +11,17 @@ cfg_if::cfg_if! { ))] { mod futex; pub use futex::Parker; + } else if #[cfg(any( + target_os = "netbsd", + all(target_vendor = "fortanix", target_env = "sgx"), + ))] { + mod id; + pub use id::Parker; } else if #[cfg(target_os = "solid_asp3")] { mod wait_flag; pub use wait_flag::Parker; } else if #[cfg(any(windows, target_family = "unix"))] { - pub use crate::sys::thread_parker::Parker; - } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { - pub use crate::sys::thread_parker::Parker; + pub use crate::sys::thread_parking::Parker; } else { mod generic; pub use generic::Parker; diff --git a/library/std/src/sys_common/thread_parker/wait_flag.rs b/library/std/src/sys_common/thread_parking/wait_flag.rs index 6561c186655..d0f8899a94e 100644 --- a/library/std/src/sys_common/thread_parker/wait_flag.rs +++ b/library/std/src/sys_common/thread_parking/wait_flag.rs @@ -41,7 +41,7 @@ pub struct Parker { impl Parker { /// Construct a parker for the current thread. The UNIX parker /// implementation requires this to happen in-place. - pub unsafe fn new(parker: *mut Parker) { + pub unsafe fn new_in_place(parker: *mut Parker) { parker.write(Parker { state: AtomicI8::new(EMPTY), wait_flag: WaitFlag::new() }) } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 5d267891bb0..b30bb7b77ef 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -905,9 +905,8 @@ pub mod statik { pub mod fast { use super::lazy::LazyKeyInner; use crate::cell::Cell; - use crate::fmt; - use crate::mem; use crate::sys::thread_local_dtor::register_dtor; + use crate::{fmt, mem, panic}; #[derive(Copy, Clone)] enum DtorState { @@ -950,7 +949,7 @@ pub mod fast { // note that this is just a publicly-callable function only for the // const-initialized form of thread locals, basically a way to call the - // free `register_dtor` function defined elsewhere in libstd. + // free `register_dtor` function defined elsewhere in std. pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { unsafe { register_dtor(a, dtor); @@ -1028,10 +1027,15 @@ pub mod fast { // `Option<T>` to `None`, and `dtor_state` to `RunningOrHasRun`. This // causes future calls to `get` to run `try_initialize_drop` again, // which will now fail, and return `None`. - unsafe { + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe { let value = (*ptr).inner.take(); (*ptr).dtor_state.set(DtorState::RunningOrHasRun); drop(value); + })) { + rtabort!("thread local panicked on drop"); } } } @@ -1044,10 +1048,8 @@ pub mod fast { pub mod os { use super::lazy::LazyKeyInner; use crate::cell::Cell; - use crate::fmt; - use crate::marker; - use crate::ptr; use crate::sys_common::thread_local_key::StaticKey as OsStaticKey; + use crate::{fmt, marker, panic, ptr}; /// Use a regular global static to store this key; the state provided will then be /// thread-local. @@ -1137,12 +1139,17 @@ pub mod os { // // Note that to prevent an infinite loop we reset it back to null right // before we return from the destructor ourselves. - unsafe { + // + // Wrap the call in a catch to ensure unwinding is caught in the event + // a panic takes place in a destructor. + if let Err(_) = panic::catch_unwind(|| unsafe { let ptr = Box::from_raw(ptr as *mut Value<T>); let key = ptr.key; key.os.set(ptr::invalid_mut(1)); drop(ptr); key.os.set(ptr::null_mut()); + }) { + rtabort!("thread local panicked on drop"); } } } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 34bdb8bd461..7acda8e98f1 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -173,7 +173,7 @@ use crate::sync::Arc; use crate::sys::thread as imp; use crate::sys_common::thread; use crate::sys_common::thread_info; -use crate::sys_common::thread_parker::Parker; +use crate::sys_common::thread_parking::Parker; use crate::sys_common::{AsInner, IntoInner}; use crate::time::Duration; @@ -1216,7 +1216,7 @@ impl Thread { let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); addr_of_mut!((*ptr).name).write(name); addr_of_mut!((*ptr).id).write(ThreadId::new()); - Parker::new(addr_of_mut!((*ptr).parker)); + Parker::new_in_place(addr_of_mut!((*ptr).parker)); Pin::new_unchecked(arc.assume_init()) }; diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index 02c076f1bb5..1a2c1255661 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -1,9 +1,8 @@ -//! These tests just check that the macros are available in libstd. +//! These tests just check that the macros are available in std. #![cfg_attr( any( all(target_arch = "arm", any(target_os = "linux", target_os = "android")), - all(bootstrap, target_arch = "aarch64", any(target_os = "linux", target_os = "android")), all(target_arch = "powerpc", target_os = "linux"), all(target_arch = "powerpc64", target_os = "linux"), ), diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 0fa11f3761a..036a35869a5 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -88,7 +88,7 @@ pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); // FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in -// the block are reexported in dylib build of libstd. This is needed when build rustc with +// the block are reexported in dylib build of std. This is needed when build rustc with // feature `llvm-libunwind', as no other cdylib will provided those _Unwind_* symbols. // However the `link` attribute is duplicated multiple times and does not just export symbol, // a better way to manually export symbol would be another attribute like `#[export]`. diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index 64b74ecc9de..4105fa5ec96 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Several unsupported `./configure` options have been removed: `optimize`, `parallel-compiler`. These can still be enabled with `--set`, although it isn't recommended. - `remote-test-server`'s `verbose` argument has been removed in favor of the `--verbose` flag - `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument. +- `x.py fmt` now formats only files modified between the merge-base of HEAD and the last commit in the master branch of the rust-lang repository and the current working directory. To restore old behaviour, use `x.py fmt .`. The check mode is not affected by this change. [#105702](https://github.com/rust-lang/rust/pull/105702) ### Non-breaking changes diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 985727bddc5..79c2eb31cda 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -80,18 +80,12 @@ The script accepts commands, flags, and arguments to determine what to do: ## Configuring rustbuild -There are currently two methods for configuring the rustbuild build system. - -First, rustbuild offers a TOML-based configuration system with a `config.toml` +rustbuild offers a TOML-based configuration system with a `config.toml` file. An example of this configuration can be found at `config.toml.example`, and the configuration file can also be passed as `--config path/to/config.toml` if the build system is being invoked manually (via the python script). -Next, the `./configure` options serialized in `config.mk` will be -parsed and read. That is, if any `./configure` options are passed, they'll be -handled naturally. `./configure` should almost never be used for local -installations, and is primarily useful for CI. Prefer to customize behavior -using `config.toml`. +You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it. Finally, rustbuild makes use of the [cc-rs crate] which has [its own method][env-vars] of configuring C compilers and C flags via environment diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 2d5018d934e..9cf43fc7a21 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -753,6 +753,9 @@ class RustBuild(object): target_features += ["-crt-static"] if target_features: env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features)) + target_linker = self.get_toml("linker", build_section) + if target_linker is not None: + env["RUSTFLAGS"] += " -C linker=" + target_linker env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes" env["RUSTFLAGS"] += " -Wsemicolon_in_expressions_from_macros" if self.get_toml("deny-warnings", "rust") != "false": diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 72d6a48b37a..b54bf432621 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -13,7 +13,6 @@ use std::time::{Duration, Instant}; use crate::cache::{Cache, Interned, INTERNER}; use crate::config::{SplitDebuginfo, TargetSelection}; -use crate::dist; use crate::doc; use crate::flags::{Color, Subcommand}; use crate::install; @@ -25,6 +24,7 @@ use crate::tool::{self, SourceType}; use crate::util::{self, add_dylib_path, add_link_lib_path, exe, libdir, output, t}; use crate::EXTRA_CHECK_CFGS; use crate::{check, compile, Crate}; +use crate::{clean, dist}; use crate::{Build, CLang, DocTests, GitRepo, Mode}; pub use crate::Compiler; @@ -96,6 +96,35 @@ impl RunConfig<'_> { pub fn build_triple(&self) -> TargetSelection { self.builder.build.build } + + /// Return a list of crate names selected by `run.paths`. + pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> { + let mut crates = Vec::new(); + for krate in &self.paths { + let path = krate.assert_single_path(); + let crate_name = self.builder.crate_paths[&path.path]; + crates.push(crate_name.to_string()); + } + INTERNER.intern_list(crates) + } +} + +/// A description of the crates in this set, suitable for passing to `builder.info`. +/// +/// `crates` should be generated by [`RunConfig::cargo_crates_in_set`]. +pub fn crate_description(crates: &[impl AsRef<str>]) -> String { + if crates.is_empty() { + return "".into(); + } + + let mut descr = String::from(" {"); + descr.push_str(crates[0].as_ref()); + for krate in &crates[1..] { + descr.push_str(", "); + descr.push_str(krate.as_ref()); + } + descr.push('}'); + descr } struct StepDescription { @@ -633,6 +662,7 @@ impl<'a> Builder<'a> { crate::toolstate::ToolStateCheck, test::ExpandYamlAnchors, test::Tidy, + test::TidySelfTest, test::Ui, test::RunPassValgrind, test::MirOpt, @@ -764,8 +794,9 @@ impl<'a> Builder<'a> { run::GenerateCopyright, ), Kind::Setup => describe!(setup::Profile), - // These commands either don't use paths, or they're special-cased in Build::build() - Kind::Clean | Kind::Format => vec![], + Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std), + // special-cased in Build::build() + Kind::Format => vec![], } } @@ -827,14 +858,12 @@ impl<'a> Builder<'a> { Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), Subcommand::Run { ref paths, .. } => (Kind::Run, &paths[..]), + Subcommand::Clean { ref paths, .. } => (Kind::Clean, &paths[..]), Subcommand::Format { .. } => (Kind::Format, &[][..]), Subcommand::Setup { profile: ref path } => ( Kind::Setup, path.as_ref().map_or([].as_slice(), |path| std::slice::from_ref(path)), ), - Subcommand::Clean { .. } => { - panic!() - } }; Self::new_internal(build, kind, paths.to_owned()) @@ -1077,6 +1106,62 @@ impl<'a> Builder<'a> { None } + /// Like `cargo`, but only passes flags that are valid for all commands. + pub fn bare_cargo( + &self, + compiler: Compiler, + mode: Mode, + target: TargetSelection, + cmd: &str, + ) -> Command { + let mut cargo = Command::new(&self.initial_cargo); + // Run cargo from the source root so it can find .cargo/config. + // This matters when using vendoring and the working directory is outside the repository. + cargo.current_dir(&self.src); + + let out_dir = self.stage_out(compiler, mode); + cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd); + + // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger` + // from out of tree it shouldn't matter, since x.py is only used for + // building in-tree. + let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"]; + match self.build.config.color { + Color::Always => { + cargo.arg("--color=always"); + for log in &color_logs { + cargo.env(log, "always"); + } + } + Color::Never => { + cargo.arg("--color=never"); + for log in &color_logs { + cargo.env(log, "never"); + } + } + Color::Auto => {} // nothing to do + } + + if cmd != "install" { + cargo.arg("--target").arg(target.rustc_target_arg()); + } else { + assert_eq!(target, compiler.host); + } + + if self.config.rust_optimize { + // FIXME: cargo bench/install do not accept `--release` + if cmd != "bench" && cmd != "install" { + cargo.arg("--release"); + } + } + + // Remove make-related flags to ensure Cargo can correctly set things up + cargo.env_remove("MAKEFLAGS"); + cargo.env_remove("MFLAGS"); + + cargo + } + /// Prepares an invocation of `cargo` to be run. /// /// This will create a `Command` that represents a pending execution of @@ -1092,11 +1177,8 @@ impl<'a> Builder<'a> { target: TargetSelection, cmd: &str, ) -> Cargo { - let mut cargo = Command::new(&self.initial_cargo); + let mut cargo = self.bare_cargo(compiler, mode, target, cmd); let out_dir = self.stage_out(compiler, mode); - // Run cargo from the source root so it can find .cargo/config. - // This matters when using vendoring and the working directory is outside the repository. - cargo.current_dir(&self.src); // Codegen backends are not yet tracked by -Zbinary-dep-depinfo, // so we need to explicitly clear out if they've been updated. @@ -1121,8 +1203,6 @@ impl<'a> Builder<'a> { self.clear_if_dirty(&my_out, &rustdoc); } - cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd); - let profile_var = |name: &str| { let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" }; format!("CARGO_PROFILE_{}_{}", profile, name) @@ -1135,32 +1215,6 @@ impl<'a> Builder<'a> { cargo.env("REAL_LIBRARY_PATH", e); } - // Found with `rg "init_env_logger\("`. If anyone uses `init_env_logger` - // from out of tree it shouldn't matter, since x.py is only used for - // building in-tree. - let color_logs = ["RUSTDOC_LOG_COLOR", "RUSTC_LOG_COLOR", "RUST_LOG_COLOR"]; - match self.build.config.color { - Color::Always => { - cargo.arg("--color=always"); - for log in &color_logs { - cargo.env(log, "always"); - } - } - Color::Never => { - cargo.arg("--color=never"); - for log in &color_logs { - cargo.env(log, "never"); - } - } - Color::Auto => {} // nothing to do - } - - if cmd != "install" { - cargo.arg("--target").arg(target.rustc_target_arg()); - } else { - assert_eq!(target, compiler.host); - } - // Set a flag for `check`/`clippy`/`fix`, so that certain build // scripts can do less work (i.e. not building/requiring LLVM). if cmd == "check" || cmd == "clippy" || cmd == "fix" { @@ -1341,9 +1395,6 @@ impl<'a> Builder<'a> { } cargo.arg("-j").arg(self.jobs().to_string()); - // Remove make-related flags to ensure Cargo can correctly set things up - cargo.env_remove("MAKEFLAGS"); - cargo.env_remove("MFLAGS"); // FIXME: Temporary fix for https://github.com/rust-lang/cargo/issues/3005 // Force cargo to output binaries with disambiguating hashes in the name @@ -1827,13 +1878,6 @@ impl<'a> Builder<'a> { } } - if self.config.rust_optimize { - // FIXME: cargo bench/install do not accept `--release` - if cmd != "bench" && cmd != "install" { - cargo.arg("--release"); - } - } - if self.config.locked_deps { cargo.arg("--locked"); } diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 2e1bd8d6d1f..b203ecd3844 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -99,19 +99,13 @@ impl Step for Std { cargo_subcommand(builder.kind), ); std_cargo(builder, target, compiler.stage, &mut cargo); + cargo.args(args(builder)); builder.info(&format!( - "Checking stage{} std artifacts ({} -> {})", + "Checking stage{} library artifacts ({} -> {})", builder.top_stage, &compiler.host, target )); - run_cargo( - builder, - cargo, - args(builder), - &libstd_stamp(builder, compiler, target), - vec![], - true, - ); + run_cargo(builder, cargo, &libstd_stamp(builder, compiler, target), vec![], true, false); // We skip populating the sysroot in non-zero stage because that'll lead // to rlib/rmeta conflicts if std gets built during this session. @@ -155,18 +149,19 @@ impl Step for Std { for krate in builder.in_tree_crates("test", Some(target)) { cargo.arg("-p").arg(krate.name); } + cargo.args(args(builder)); builder.info(&format!( - "Checking stage{} std test/bench/example targets ({} -> {})", + "Checking stage{} library test/bench/example targets ({} -> {})", builder.top_stage, &compiler.host, target )); run_cargo( builder, cargo, - args(builder), &libstd_test_stamp(builder, compiler, target), vec![], true, + false, ); } } @@ -231,19 +226,13 @@ impl Step for Rustc { for krate in builder.in_tree_crates("rustc-main", Some(target)) { cargo.arg("-p").arg(krate.name); } + cargo.args(args(builder)); builder.info(&format!( "Checking stage{} compiler artifacts ({} -> {})", builder.top_stage, &compiler.host, target )); - run_cargo( - builder, - cargo, - args(builder), - &librustc_stamp(builder, compiler, target), - vec![], - true, - ); + run_cargo(builder, cargo, &librustc_stamp(builder, compiler, target), vec![], true, false); let libdir = builder.sysroot_libdir(compiler, target); let hostdir = builder.sysroot_libdir(compiler, compiler.host); @@ -290,6 +279,7 @@ impl Step for CodegenBackend { .arg("--manifest-path") .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend))); rustc_cargo_env(builder, &mut cargo, target); + cargo.args(args(builder)); builder.info(&format!( "Checking stage{} {} artifacts ({} -> {})", @@ -299,10 +289,10 @@ impl Step for CodegenBackend { run_cargo( builder, cargo, - args(builder), &codegen_backend_stamp(builder, compiler, target, backend), vec![], true, + false, ); } } @@ -355,11 +345,13 @@ impl Step for RustAnalyzer { cargo.arg("--benches"); } + cargo.args(args(builder)); + builder.info(&format!( "Checking stage{} {} artifacts ({} -> {})", compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple )); - run_cargo(builder, cargo, args(builder), &stamp(builder, compiler, target), vec![], true); + run_cargo(builder, cargo, &stamp(builder, compiler, target), vec![], true, false); /// Cargo's output path in a given stage, compiled by a particular /// compiler for the specified target. @@ -413,6 +405,8 @@ macro_rules! tool_check_step { cargo.arg("--all-targets"); } + cargo.args(args(builder)); + // Enable internal lints for clippy and rustdoc // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]` // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776 @@ -428,10 +422,10 @@ macro_rules! tool_check_step { run_cargo( builder, cargo, - args(builder), &stamp(builder, compiler, target), vec![], true, + false, ); /// Cargo's output path in a given stage, compiled by a particular diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 069f3d6acf1..468efc1114c 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -9,10 +9,81 @@ use std::fs; use std::io::{self, ErrorKind}; use std::path::Path; +use crate::builder::{crate_description, Builder, RunConfig, ShouldRun, Step}; +use crate::cache::Interned; use crate::util::t; -use crate::Build; +use crate::{Build, Compiler, Mode, Subcommand}; -pub fn clean(build: &Build, all: bool) { +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct CleanAll {} + +impl Step for CleanAll { + const DEFAULT: bool = true; + type Output = (); + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(CleanAll {}) + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let Subcommand::Clean { all, .. } = builder.config.cmd else { unreachable!("wrong subcommand?") }; + clean_default(builder.build, all) + } + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.never() // handled by DEFAULT + } +} + +macro_rules! clean_crate_tree { + ( $( $name:ident, $mode:path, $root_crate:literal);+ $(;)? ) => { $( + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub struct $name { + compiler: Compiler, + crates: Interned<Vec<String>>, + } + + impl Step for $name { + type Output = (); + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + let crates = run.builder.in_tree_crates($root_crate, None); + run.crates(crates) + } + + fn make_run(run: RunConfig<'_>) { + let builder = run.builder; + let compiler = builder.compiler(builder.top_stage, run.target); + builder.ensure(Self { crates: run.cargo_crates_in_set(), compiler }); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let compiler = self.compiler; + let target = compiler.host; + let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean"); + for krate in &*self.crates { + cargo.arg(krate); + } + + builder.info(&format!( + "Cleaning{} stage{} {} artifacts ({} -> {})", + crate_description(&self.crates), compiler.stage, stringify!($name).to_lowercase(), &compiler.host, target, + )); + + // NOTE: doesn't use `run_cargo` because we don't want to save a stamp file, + // and doesn't use `stream_cargo` to avoid passing `--message-format` which `clean` doesn't accept. + builder.run(&mut cargo); + } + } + )+ } +} + +clean_crate_tree! { + Rustc, Mode::Rustc, "rustc-main"; + Std, Mode::Std, "test"; +} + +fn clean_default(build: &Build, all: bool) { rm_rf("tmp".as_ref()); if all { @@ -21,6 +92,7 @@ pub fn clean(build: &Build, all: bool) { rm_rf(&build.out.join("tmp")); rm_rf(&build.out.join("dist")); rm_rf(&build.out.join("bootstrap")); + rm_rf(&build.out.join("rustfmt.stamp")); for host in &build.hosts { let entries = match build.out.join(host.triple).read_dir() { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 0e3bbad9909..147ded3a9ee 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -18,6 +18,7 @@ use std::str; use serde::Deserialize; +use crate::builder::crate_description; use crate::builder::Cargo; use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; @@ -46,17 +47,6 @@ impl Std { } } -/// Return a `-p=x -p=y` string suitable for passing to a cargo invocation. -fn build_crates_in_set(run: &RunConfig<'_>) -> Interned<Vec<String>> { - let mut crates = Vec::new(); - for krate in &run.paths { - let path = krate.assert_single_path(); - let crate_name = run.builder.crate_paths[&path.path]; - crates.push(format!("-p={crate_name}")); - } - INTERNER.intern_list(crates) -} - impl Step for Std { type Output = (); const DEFAULT: bool = true; @@ -76,7 +66,7 @@ impl Step for Std { // Build all crates anyway, as if they hadn't passed the other args. let has_library = run.paths.iter().any(|set| set.assert_single_path().path.ends_with("library")); - let crates = if has_library { Default::default() } else { build_crates_in_set(&run) }; + let crates = if has_library { Default::default() } else { run.cargo_crates_in_set() }; run.builder.ensure(Std { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, @@ -121,7 +111,10 @@ impl Step for Std { let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); if compiler_to_use != compiler { builder.ensure(Std::new(compiler_to_use, target)); - builder.info(&format!("Uplifting stage1 std ({} -> {})", compiler_to_use.host, target)); + builder.info(&format!( + "Uplifting stage1 library ({} -> {})", + compiler_to_use.host, target + )); // Even if we're not building std this stage, the new sysroot must // still contain the third party objects needed by various targets. @@ -137,18 +130,24 @@ impl Step for Std { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build"); std_cargo(builder, target, compiler.stage, &mut cargo); + for krate in &*self.crates { + cargo.arg("-p").arg(krate); + } builder.info(&format!( - "Building stage{} std artifacts ({} -> {})", - compiler.stage, &compiler.host, target + "Building{} stage{} library artifacts ({} -> {})", + crate_description(&self.crates), + compiler.stage, + &compiler.host, + target, )); run_cargo( builder, cargo, - self.crates.to_vec(), &libstd_stamp(builder, compiler, target), target_deps, false, + false, ); builder.ensure(StdLink::from_std( @@ -436,7 +435,7 @@ impl Step for StdLink { let target_compiler = self.target_compiler; let target = self.target; builder.info(&format!( - "Copying stage{} std from stage{} ({} -> {} / {})", + "Copying stage{} library from stage{} ({} -> {} / {})", target_compiler.stage, compiler.stage, &compiler.host, target_compiler.host, target )); let libdir = builder.sysroot_libdir(target_compiler, target); @@ -603,7 +602,7 @@ impl Step for Rustc { } fn make_run(run: RunConfig<'_>) { - let crates = build_crates_in_set(&run); + let crates = run.cargo_crates_in_set(); run.builder.ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, @@ -702,7 +701,8 @@ impl Step for Rustc { )); } - // cfg(bootstrap): remove if condition once the bootstrap compiler supports dylib LTO + // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary + // and may just be a time sink. if compiler.stage != 0 { match builder.config.rust_lto { RustcLto::Thin | RustcLto::Fat => { @@ -724,17 +724,24 @@ impl Step for Rustc { } } + for krate in &*self.crates { + cargo.arg("-p").arg(krate); + } + builder.info(&format!( - "Building stage{} compiler artifacts ({} -> {})", - compiler.stage, &compiler.host, target + "Building{} stage{} compiler artifacts ({} -> {})", + crate_description(&self.crates), + compiler.stage, + &compiler.host, + target, )); run_cargo( builder, cargo, - self.crates.to_vec(), &librustc_stamp(builder, compiler, target), vec![], false, + true, // Only ship rustc_driver.so and .rmeta files, not all intermediate .rlib files. ); builder.ensure(RustcLink::from_rustc( @@ -991,7 +998,7 @@ impl Step for CodegenBackend { "Building stage{} codegen backend {} ({} -> {})", compiler.stage, backend, &compiler.host, target )); - let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false); + let files = run_cargo(builder, cargo, &tmp_stamp, vec![], false, false); if builder.config.dry_run() { return; } @@ -1415,10 +1422,10 @@ pub fn add_to_sysroot( pub fn run_cargo( builder: &Builder<'_>, cargo: Cargo, - tail_args: Vec<String>, stamp: &Path, additional_target_deps: Vec<(PathBuf, DependencyType)>, is_check: bool, + rlib_only_metadata: bool, ) -> Vec<PathBuf> { if builder.config.dry_run() { return Vec::new(); @@ -1441,7 +1448,7 @@ pub fn run_cargo( // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| { + let ok = stream_cargo(builder, cargo, &mut |msg| { let (filenames, crate_types) = match msg { CargoMessage::CompilerArtifact { filenames, @@ -1452,13 +1459,35 @@ pub fn run_cargo( }; for filename in filenames { // Skip files like executables - if !(filename.ends_with(".rlib") - || filename.ends_with(".lib") + let mut keep = false; + if filename.ends_with(".lib") || filename.ends_with(".a") || is_debug_info(&filename) || is_dylib(&filename) - || (is_check && filename.ends_with(".rmeta"))) { + // Always keep native libraries, rust dylibs and debuginfo + keep = true; + } + if is_check && filename.ends_with(".rmeta") { + // During check builds we need to keep crate metadata + keep = true; + } else if rlib_only_metadata { + if filename.contains("jemalloc_sys") || filename.contains("rustc_smir") { + // jemalloc_sys and rustc_smir are not linked into librustc_driver.so, + // so we need to distribute them as rlib to be able to use them. + keep |= filename.ends_with(".rlib"); + } else { + // Distribute the rest of the rustc crates as rmeta files only to reduce + // the tarball sizes by about 50%. The object files are linked into + // librustc_driver.so, so it is still possible to link against them. + keep |= filename.ends_with(".rmeta"); + } + } else { + // In all other cases keep all rlibs + keep |= filename.ends_with(".rlib"); + } + + if !keep { continue; } @@ -1556,7 +1585,6 @@ pub fn run_cargo( pub fn stream_cargo( builder: &Builder<'_>, cargo: Cargo, - tail_args: Vec<String>, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { let mut cargo = Command::from(cargo); @@ -1576,10 +1604,6 @@ pub fn stream_cargo( } cargo.arg("--message-format").arg(message_format).stdout(Stdio::piped()); - for arg in tail_args { - cargo.arg(arg); - } - builder.verbose(&format!("running: {:?}", cargo)); let mut child = match cargo.spawn() { Ok(child) => child, diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 84278583846..b41d60d51a8 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -49,10 +49,7 @@ pub enum DryRun { /// Global configuration for the entire build and/or bootstrap. /// -/// This structure is derived from a combination of both `config.toml` and -/// `config.mk`. As of the time of this writing it's unlikely that `config.toml` -/// is used all that much, so this is primarily filled out by `config.mk` which -/// is generated from `./configure`. +/// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters. /// /// Note that this structure is not decoded directly into, but rather it is /// filled out from the decoded forms of the structs below. For documentation diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 6b139decb55..31cc4aa57bb 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -405,7 +405,9 @@ if 'target' in config: configured_targets.append(target) for target in configured_targets: targets[target] = sections['target'][:] - targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target)) + # For `.` to be valid TOML, it needs to be quoted. But `bootstrap.py` doesn't use a proper TOML parser and fails to parse the target. + # Avoid using quotes unless it's necessary. + targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", "'{}'".format(target) if "." in target else target) def is_number(value): diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5838049aa5c..9bad9046ecc 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -12,6 +12,7 @@ use std::fs; use std::io; use std::path::{Path, PathBuf}; +use crate::builder::crate_description; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; @@ -506,7 +507,11 @@ impl Step for Std { // Look for library/std, library/core etc in the `x.py doc` arguments and // open the corresponding rendered docs. for requested_crate in requested_crates { - if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) { + if requested_crate == "library" { + // For `x.py doc library --open`, open `std` by default. + let index = out.join("std").join("index.html"); + builder.open_in_browser(index); + } else if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) { let index = out.join(requested_crate).join("index.html"); builder.open_in_browser(index); } @@ -554,7 +559,8 @@ fn doc_std( requested_crates: &[String], ) { builder.info(&format!( - "Documenting stage{} std ({}) in {} format", + "Documenting{} stage{} library ({}) in {} format", + crate_description(requested_crates), stage, target, format.as_str() diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 851cb5ecf4c..2c6d201d18f 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -130,6 +130,7 @@ pub enum Subcommand { test_args: Vec<String>, }, Clean { + paths: Vec<PathBuf>, all: bool, }, Dist { @@ -351,22 +352,32 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`", // fn usage() let usage = |exit_code: i32, opts: &Options, verbose: bool, subcommand_help: &str| -> ! { - let config = Config::parse(&["setup".to_string()]); - let build = Build::new(config); - let paths = Builder::get_help(&build, subcommand); - println!("{}", opts.usage(subcommand_help)); - if let Some(s) = paths { - if verbose { + if verbose { + // We have an unfortunate situation here: some Steps use `builder.in_tree_crates` to determine their paths. + // To determine those crates, we need to run `cargo metadata`, which means we need all submodules to be checked out. + // That takes a while to run, so only do it when paths were explicitly requested, not on all CLI errors. + // `Build::new` won't load submodules for the `setup` command. + let cmd = if verbose { + println!("note: updating submodules before printing available paths"); + "build" + } else { + "setup" + }; + let config = Config::parse(&[cmd.to_string()]); + let build = Build::new(config); + let paths = Builder::get_help(&build, subcommand); + + if let Some(s) = paths { println!("{}", s); } else { - println!( - "Run `./x.py {} -h -v` to see a list of available paths.", - subcommand.as_str() - ); + panic!("No paths available for subcommand `{}`", subcommand.as_str()); } - } else if verbose { - panic!("No paths available for subcommand `{}`", subcommand.as_str()); + } else { + println!( + "Run `./x.py {} -h -v` to see a list of available paths.", + subcommand.as_str() + ); } crate::detail_exit(exit_code); }; @@ -601,14 +612,7 @@ Arguments: open: matches.opt_present("open"), json: matches.opt_present("json"), }, - Kind::Clean => { - if !paths.is_empty() { - println!("\nclean does not take a path argument\n"); - usage(1, &opts, verbose, &subcommand_help); - } - - Subcommand::Clean { all: matches.opt_present("all") } - } + Kind::Clean => Subcommand::Clean { all: matches.opt_present("all"), paths }, Kind::Format => Subcommand::Format { check: matches.opt_present("check"), paths }, Kind::Dist => Subcommand::Dist { paths }, Kind::Install => Subcommand::Install { paths }, diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index b2f6afead79..84e46118959 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -1,7 +1,7 @@ //! Runs rustfmt on the repository. use crate::builder::Builder; -use crate::util::{output, t}; +use crate::util::{output, program_out_of_date, t}; use ignore::WalkBuilder; use std::collections::VecDeque; use std::path::{Path, PathBuf}; @@ -44,6 +44,86 @@ fn rustfmt(src: &Path, rustfmt: &Path, paths: &[PathBuf], check: bool) -> impl F } } +fn get_rustfmt_version(build: &Builder<'_>) -> Option<(String, PathBuf)> { + let stamp_file = build.out.join("rustfmt.stamp"); + + let mut cmd = Command::new(match build.initial_rustfmt() { + Some(p) => p, + None => return None, + }); + cmd.arg("--version"); + let output = match cmd.output() { + Ok(status) => status, + Err(_) => return None, + }; + if !output.status.success() { + return None; + } + Some((String::from_utf8(output.stdout).unwrap(), stamp_file)) +} + +/// Return whether the format cache can be reused. +fn verify_rustfmt_version(build: &Builder<'_>) -> bool { + let Some((version, stamp_file)) = get_rustfmt_version(build) else {return false;}; + !program_out_of_date(&stamp_file, &version) +} + +/// Updates the last rustfmt version used +fn update_rustfmt_version(build: &Builder<'_>) { + let Some((version, stamp_file)) = get_rustfmt_version(build) else {return;}; + t!(std::fs::write(stamp_file, version)) +} + +/// Returns the Rust files modified between the `merge-base` of HEAD and +/// rust-lang/master and what is now on the disk. +/// +/// Returns `None` if all files should be formatted. +fn get_modified_rs_files(build: &Builder<'_>) -> Option<Vec<String>> { + let Ok(remote) = get_rust_lang_rust_remote() else { return None; }; + if !verify_rustfmt_version(build) { + return None; + } + + let merge_base = + output(build.config.git().arg("merge-base").arg(&format!("{remote}/master")).arg("HEAD")); + Some( + output(build.config.git().arg("diff-index").arg("--name-only").arg(merge_base.trim())) + .lines() + .map(|s| s.trim().to_owned()) + .filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs")) + .collect(), + ) +} + +/// Finds the remote for rust-lang/rust. +/// For example for these remotes it will return `upstream`. +/// ```text +/// origin https://github.com/Nilstrieb/rust.git (fetch) +/// origin https://github.com/Nilstrieb/rust.git (push) +/// upstream https://github.com/rust-lang/rust (fetch) +/// upstream https://github.com/rust-lang/rust (push) +/// ``` +fn get_rust_lang_rust_remote() -> Result<String, String> { + let mut git = Command::new("git"); + git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]); + + let output = git.output().map_err(|err| format!("{err:?}"))?; + if !output.status.success() { + return Err("failed to execute git config command".to_owned()); + } + + let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?; + + let rust_lang_remote = stdout + .lines() + .find(|remote| remote.contains("rust-lang")) + .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?; + + let remote_name = + rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; + Ok(remote_name.into()) +} + #[derive(serde::Deserialize)] struct RustfmtConfig { ignore: Vec<String>, @@ -110,6 +190,14 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { // preventing the latter from being formatted. ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path); } + if !check && paths.is_empty() { + if let Some(files) = get_modified_rs_files(build) { + for file in files { + println!("formatting modified file {file}"); + ignore_fmt.add(&format!("/{file}")).expect(&file); + } + } + } } else { println!("Not in git tree. Skipping git-aware format checks"); } @@ -187,4 +275,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { drop(tx); thread.join().unwrap(); + if !check { + update_rustfmt_version(build); + } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index f84fcd21cfc..5ea41d10bc8 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -727,10 +727,6 @@ impl Build { return format::format(&builder::Builder::new(&self), *check, &paths); } - if let Subcommand::Clean { all } = self.config.cmd { - return clean::clean(self, all); - } - // Download rustfmt early so that it can be used in rust-analyzer configs. let _ = &builder::Builder::new(&self).initial_rustfmt(); @@ -1400,7 +1396,10 @@ impl Build { let mut list = vec![INTERNER.intern_str(root)]; let mut visited = HashSet::new(); while let Some(krate) = list.pop() { - let krate = &self.crates[&krate]; + let krate = self + .crates + .get(&krate) + .unwrap_or_else(|| panic!("metadata missing for {krate}: {:?}", self.crates)); ret.push(krate); for dep in &krate.deps { if !self.crates.contains_key(dep) { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 0d9c22e210f..ea906be7e3a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -11,6 +11,7 @@ use std::iter; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use crate::builder::crate_description; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::Interned; use crate::compile; @@ -1048,7 +1049,7 @@ impl Step for RustdocGUI { if entry.file_name() == "link_to_definition" { cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition"); } else if entry.file_name() == "scrape_examples" { - cargo.arg("-Zrustdoc-scrape-examples=examples"); + cargo.arg("-Zrustdoc-scrape-examples"); } builder.run(&mut cargo); } @@ -1142,6 +1143,40 @@ help: to skip test's attempt to check tidiness, pass `--exclude src/tools/tidy` } } +/// Runs tidy's own tests. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct TidySelfTest; + +impl Step for TidySelfTest { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("tidyselftest") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(TidySelfTest); + } + + fn run(self, builder: &Builder<'_>) { + let bootstrap_host = builder.config.build; + let compiler = builder.compiler(0, bootstrap_host); + let cargo = tool::prepare_tool_cargo( + builder, + compiler, + Mode::ToolBootstrap, + bootstrap_host, + "test", + "src/tools/tidy", + SourceType::InTree, + &[], + ); + try_run(builder, &mut cargo.into()); + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct ExpandYamlAnchors; @@ -2154,8 +2189,12 @@ impl Step for Crate { } builder.info(&format!( - "{} {:?} stage{} ({} -> {})", - test_kind, self.crates, compiler.stage, &compiler.host, target + "{}{} stage{} ({} -> {})", + test_kind, + crate_description(&self.crates), + compiler.stage, + &compiler.host, + target )); let _time = util::timeit(&builder); try_run(builder, &mut cargo.into()); diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 24b033cc0dc..63026bd44d4 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -72,7 +72,7 @@ impl Step for ToolBuild { builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| { + let is_expected = compile::stream_cargo(builder, cargo, &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { "rls" | "cargo" | "clippy-driver" | "miri" | "rustfmt" => {} diff --git a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile index 78fee152eb9..dc0e591cad6 100644 --- a/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile @@ -32,5 +32,4 @@ RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-require COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/ -ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 -ENV SCRIPT python3 ../x.py test --stage 0 src/tools/tidy +ENV SCRIPT python3 ../x.py test --stage 0 src/tools/tidy tidyselftest diff --git a/src/ci/run.sh b/src/ci/run.sh index f05bb81d4a1..0db9c993eec 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -45,14 +45,6 @@ fi ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh" -if command -v python > /dev/null; then - PYTHON="python" -elif command -v python3 > /dev/null; then - PYTHON="python3" -else - PYTHON="python2" -fi - if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.metrics" @@ -192,16 +184,16 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then $SRC/configure --set rust.parallel-compiler # Save the build metrics before we wipe the directory - if [ $HAS_METRICS = 1 ]; then + if [ "$HAS_METRICS" = 1 ]; then mv build/metrics.json . fi rm -rf build - if [ $HAS_METRICS = 1 ]; then + if [ "$HAS_METRICS" = 1 ]; then mkdir build mv metrics.json build fi - CARGO_INCREMENTAL=0 $PYTHON ../x.py check + CARGO_INCREMENTAL=0 ../x check fi sccache --show-stats || true diff --git a/src/doc/book b/src/doc/book -Subproject a60f4316ec923a5ac2ed6a2eba6960edb832d85 +Subproject 2bd5d42c9956369132228da6409f0e68da56c51 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject dd37e21ccee43918ed18a71581bb2af537ffe4f +Subproject 8ca261268068d80c0969260fff15199bad87b58 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 995df09b65c582eb6290ab7ea5d9485983eb4c3 +Subproject 8888f9428fe9a48f31de6bd2cef9b9bf80791ed diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 8b42eb5f57d3d8ed2257a22d0e850d9db52afed +Subproject b3e2a6e6c8a3aae5b5d950c63046f23bae07096 diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md index 5859df83f64..f291cde2e5a 100644 --- a/src/doc/rustc/src/targets/index.md +++ b/src/doc/rustc/src/targets/index.md @@ -1,7 +1,10 @@ # Targets `rustc` is a cross-compiler by default. This means that you can use any compiler to build for any -architecture. The list of *targets* are the possible architectures that you can build for. +architecture. The list of *targets* are the possible architectures that you can build for. See +the [Platform Support](../platform-support.md) page for a detailed list of targets, or +[Built-in Targets](built-in.md) for instructions on how to view what is available for your version +of `rustc`. To see all the options that you can set with a target, see the docs [here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/struct.Target.html). diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md index e3b08648999..8ecf05f0e12 100644 --- a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -9,11 +9,11 @@ are the same: ```rust,no_run /// This is a doc comment. -#[doc = " This is a doc comment."] +#[doc = r" This is a doc comment."] # fn f() {} ``` -(Note the leading space in the attribute version.) +(Note the leading space and the raw string literal in the attribute version.) In most cases, `///` is easier to use than `#[doc]`. One case where the latter is easier is when generating documentation in macros; the `collapse-docs` pass will combine multiple diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 92886bbfe26..07a9c48365f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1612,7 +1612,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T match ty.kind { TyKind::Never => Primitive(PrimitiveType::Never), TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))), - TyKind::Rptr(ref l, ref m) => { + TyKind::Ref(ref l, ref m) => { let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(*l, cx)) }; BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) } } @@ -1853,7 +1853,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Placeholder(..) => panic!("Placeholder"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), - ty::Error(_) => panic!("Error"), + ty::Error(_) => rustc_errors::FatalError.raise(), } } @@ -1949,20 +1949,28 @@ pub(crate) fn clean_field_with_def_id( } pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocContext<'tcx>) -> Item { + let discriminant = match variant.discr { + ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }), + ty::VariantDiscr::Relative(_) => None, + }; + let kind = match variant.ctor_kind() { - Some(CtorKind::Const) => Variant::CLike(match variant.discr { - ty::VariantDiscr::Explicit(def_id) => Some(Discriminant { expr: None, value: def_id }), - ty::VariantDiscr::Relative(_) => None, - }), - Some(CtorKind::Fn) => Variant::Tuple( + Some(CtorKind::Const) => VariantKind::CLike, + Some(CtorKind::Fn) => VariantKind::Tuple( variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), ), - None => Variant::Struct(VariantStruct { + None => VariantKind::Struct(VariantStruct { ctor_kind: None, fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), }), }; - Item::from_def_id_and_parts(variant.def_id, Some(variant.name), VariantItem(kind), cx) + + Item::from_def_id_and_parts( + variant.def_id, + Some(variant.name), + VariantItem(Variant { kind, discriminant }), + cx, + ) } fn clean_variant_data<'tcx>( @@ -1970,19 +1978,23 @@ fn clean_variant_data<'tcx>( disr_expr: &Option<hir::AnonConst>, cx: &mut DocContext<'tcx>, ) -> Variant { - match variant { - hir::VariantData::Struct(..) => Variant::Struct(VariantStruct { + let discriminant = disr_expr.map(|disr| Discriminant { + expr: Some(disr.body), + value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(), + }); + + let kind = match variant { + hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct { ctor_kind: None, fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(), }), hir::VariantData::Tuple(..) => { - Variant::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect()) + VariantKind::Tuple(variant.fields().iter().map(|x| clean_field(x, cx)).collect()) } - hir::VariantData::Unit(..) => Variant::CLike(disr_expr.map(|disr| Discriminant { - expr: Some(disr.body), - value: cx.tcx.hir().local_def_id(disr.hir_id).to_def_id(), - })), - } + hir::VariantData::Unit(..) => VariantKind::CLike, + }; + + Variant { discriminant, kind } } fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7a13e7e36d1..77ec0242621 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -807,8 +807,11 @@ impl ItemKind { match self { StructItem(s) => s.fields.iter(), UnionItem(u) => u.fields.iter(), - VariantItem(Variant::Struct(v)) => v.fields.iter(), - VariantItem(Variant::Tuple(v)) => v.iter(), + VariantItem(v) => match &v.kind { + VariantKind::CLike => [].iter(), + VariantKind::Tuple(t) => t.iter(), + VariantKind::Struct(s) => s.fields.iter(), + }, EnumItem(e) => e.variants.iter(), TraitItem(t) => t.items.iter(), ImplItem(i) => i.items.iter(), @@ -824,7 +827,6 @@ impl ItemKind { | TyMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) - | VariantItem(_) | ForeignFunctionItem(_) | ForeignStaticItem(_) | ForeignTypeItem @@ -1740,7 +1742,7 @@ impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> { let t: PrimitiveType = match *self { Type::Path { ref path } => return Some(path.def_id()), - DynTrait(ref bounds, _) => return Some(bounds[0].trait_.def_id()), + DynTrait(ref bounds, _) => return bounds.get(0).map(|b| b.trait_.def_id()), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), @@ -2136,17 +2138,23 @@ impl Enum { } #[derive(Clone, Debug)] -pub(crate) enum Variant { - CLike(Option<Discriminant>), +pub(crate) struct Variant { + pub kind: VariantKind, + pub discriminant: Option<Discriminant>, +} + +#[derive(Clone, Debug)] +pub(crate) enum VariantKind { + CLike, Tuple(Vec<Item>), Struct(VariantStruct), } impl Variant { pub(crate) fn has_stripped_entries(&self) -> Option<bool> { - match *self { - Self::Struct(ref struct_) => Some(struct_.has_stripped_entries()), - Self::CLike(..) | Self::Tuple(_) => None, + match &self.kind { + VariantKind::Struct(struct_) => Some(struct_.has_stripped_entries()), + VariantKind::CLike | VariantKind::Tuple(_) => None, } } } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index c6f1f9de51a..656aeefb01a 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -37,17 +37,21 @@ pub(crate) trait DocFolder: Sized { i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect(); ImplItem(i) } - VariantItem(i) => match i { - Variant::Struct(mut j) => { - j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - VariantItem(Variant::Struct(j)) - } - Variant::Tuple(fields) => { - let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); - VariantItem(Variant::Tuple(fields)) - } - Variant::CLike(disr) => VariantItem(Variant::CLike(disr)), - }, + VariantItem(Variant { kind, discriminant }) => { + let kind = match kind { + VariantKind::Struct(mut j) => { + j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + VariantKind::Struct(j) + } + VariantKind::Tuple(fields) => { + let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect(); + VariantKind::Tuple(fields) + } + VariantKind::CLike => VariantKind::CLike, + }; + + VariantItem(Variant { kind, discriminant }) + } ExternCrateItem { src: _ } | ImportItem(_) | FunctionItem(_) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index a7b57c373e3..40dfb069750 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1220,15 +1220,15 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str(" "); let name = v.name.unwrap(); match *v.kind { - clean::VariantItem(ref var) => match var { - // FIXME(#101337): Show discriminant - clean::Variant::CLike(..) => write!(w, "{}", name), - clean::Variant::Tuple(ref s) => { + // FIXME(#101337): Show discriminant + clean::VariantItem(ref var) => match var.kind { + clean::VariantKind::CLike => write!(w, "{}", name), + clean::VariantKind::Tuple(ref s) => { write!(w, "{}(", name); print_tuple_struct_fields(w, cx, s); w.write_str(")"); } - clean::Variant::Struct(ref s) => { + clean::VariantKind::Struct(ref s) => { render_struct( w, v, @@ -1286,25 +1286,28 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: " rightside", ); write!(w, "<h3 class=\"code-header\">{name}", name = variant.name.unwrap()); - if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind { + + let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() }; + + if let clean::VariantKind::Tuple(ref s) = variant_data.kind { w.write_str("("); print_tuple_struct_fields(w, cx, s); w.write_str(")"); } w.write_str("</h3></section>"); - use crate::clean::Variant; - - let heading_and_fields = match &*variant.kind { - clean::VariantItem(Variant::Struct(s)) => Some(("Fields", &s.fields)), - // Documentation on tuple variant fields is rare, so to reduce noise we only emit - // the section if at least one field is documented. - clean::VariantItem(Variant::Tuple(fields)) - if fields.iter().any(|f| f.doc_value().is_some()) => - { - Some(("Tuple Fields", fields)) + let heading_and_fields = match &variant_data.kind { + clean::VariantKind::Struct(s) => Some(("Fields", &s.fields)), + clean::VariantKind::Tuple(fields) => { + // Documentation on tuple variant fields is rare, so to reduce noise we only emit + // the section if at least one field is documented. + if fields.iter().any(|f| f.doc_value().is_some()) { + Some(("Tuple Fields", fields)) + } else { + None + } } - _ => None, + clean::VariantKind::CLike => None, }; if let Some((heading, fields)) = heading_and_fields { diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 8eb9c07f8a7..2d61519d6c9 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -322,8 +322,7 @@ fn get_index_type_id(clean_type: &clean::Type) -> Option<RenderTypeId> { match *clean_type { clean::Type::Path { ref path, .. } => Some(RenderTypeId::DefId(path.def_id())), clean::DynTrait(ref bounds, _) => { - let path = &bounds[0].trait_; - Some(RenderTypeId::DefId(path.def_id())) + bounds.get(0).map(|b| RenderTypeId::DefId(b.trait_.def_id())) } clean::Primitive(p) => Some(RenderTypeId::Primitive(p)), clean::BorrowedRef { ref type_, .. } | clean::RawPointer(_, ref type_) => { diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 2b2b148f05e..bc0458bcd28 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -347,20 +347,23 @@ pre { .source .content pre { padding: 20px; } +.rustdoc.source .example-wrap > pre.src-line-numbers { + padding: 20px 0 20px 4px; +} img { max-width: 100%; } -.source .content { - overflow: visible; -} - .sub-logo-container, .logo-container { /* zero text boxes so that computed line height = image height exactly */ line-height: 0; } +.sub-logo-container { + margin-right: 32px; +} + .sub-logo-container > img { height: 60px; width: 60px; @@ -371,10 +374,6 @@ img { filter: var(--rust-logo-filter); } -.sidebar, .mobile-topbar, .sidebar-menu-toggle { - background-color: var(--sidebar-background-color); -} - .sidebar { font-size: 0.875rem; flex: 0 0 200px; @@ -393,7 +392,8 @@ img { overflow-y: hidden; } -.source .sidebar, #src-sidebar-toggle, #source-sidebar { +.sidebar, .mobile-topbar, .sidebar-menu-toggle, +#src-sidebar-toggle, #source-sidebar { background-color: var(--sidebar-background-color); } @@ -519,10 +519,6 @@ ul.block, .block li { display: none; } -.source .content pre.rust { - padding-left: 0; -} - .rustdoc .example-wrap { display: flex; position: relative; @@ -550,23 +546,21 @@ ul.block, .block li { -moz-user-select: none; -ms-user-select: none; user-select: none; + padding: 14px 8px; + color: var(--src-line-numbers-span-color); } -.example-line-numbers { - border: 1px solid; - padding: 13px 8px; - border-top-left-radius: 5px; - border-bottom-left-radius: 5px; - border-color: var(--example-line-numbers-border-color); +.rustdoc .example-wrap > pre.src-line-numbers { + padding: 14px 0; } - .src-line-numbers a, .src-line-numbers span { color: var(--src-line-numbers-span-color); + padding: 0 8px; } .src-line-numbers :target { background-color: transparent; border-right: none; - padding-right: 0; + padding: 0 8px; } .src-line-numbers .line-highlighted { background-color: var(--src-line-number-highlighted-background-color); @@ -674,9 +668,6 @@ nav.sub { .source nav.sub { margin: 0 0 15px 0; } -.source .search-form { - margin-left: 32px; -} a { text-decoration: none; @@ -1111,7 +1102,6 @@ pre.rust .doccomment { } .example-wrap .tooltip:hover::after { - text-align: center; padding: 5px 3px 3px 3px; border-radius: 6px; margin-left: 5px; @@ -1323,15 +1313,11 @@ a.test-arrow:hover { -webkit-appearance: none; opacity: 1; } + #settings-menu, #help-button { margin-left: 4px; display: flex; } - -#settings-menu > a, #help-button > a, #copy-path { - width: 33px; -} - #settings-menu > a, #help-button > a { display: flex; align-items: center; @@ -1343,6 +1329,7 @@ a.test-arrow:hover { /* Rare exception to specifying font sizes in rem. Since this is acting as an icon, it's okay to specify their sizes in pixels. */ font-size: 20px; + width: 33px; } #settings-menu > a:hover, #settings-menu > a:focus, @@ -1358,6 +1345,7 @@ a.test-arrow:hover { padding: 0; padding-left: 2px; border: 0; + width: 33px; } #copy-path > img { filter: var(--copy-path-img-filter); @@ -1399,31 +1387,10 @@ details.dir-entry { padding-left: 4px; } -details.dir-entry > summary::after { - content: " â–º"; - position: absolute; - left: -15px; - top: 0px; - font-size: 80%; - padding: 2px 0px; - /* set width to cover gap between arrow and text */ - width: 25px; -} - -details[open].dir-entry > summary::after { - content: " â–¼"; -} - -details.dir-entry > summary::-webkit-details-marker, -details.dir-entry > summary::marker { - display: none; -} - details.dir-entry > summary { - margin: 0 0 0 13px; - list-style: none; + margin: 0 0 0 -4px; + padding: 0 0 0 4px; cursor: pointer; - position: relative; } details.dir-entry div.folders, details.dir-entry div.files { @@ -1836,13 +1803,6 @@ in storage.js height: 35px; width: 35px; } - - #src-sidebar-toggle { - top: 10px; - } - .source-sidebar-expanded #src-sidebar-toggle { - top: unset; - } } .variant, @@ -1880,9 +1840,13 @@ in storage.js font-size: 12px; position: relative; bottom: 1px; - border-width: 1px; - border-style: solid; + border: 1px solid var(--scrape-example-help-border-color); border-radius: 50px; + color: var(--scrape-example-help-color); +} +.scraped-example-list .scrape-help:hover { + border-color: var(--scrape-example-help-hover-border-color); + color: var(--scrape-example-help-hover-color); } .scraped-example { @@ -1958,15 +1922,6 @@ in storage.js bottom: 0; } -.scraped-example .code-wrapper .src-line-numbers { - padding: 14px 0; -} - -.scraped-example .code-wrapper .src-line-numbers a, -.scraped-example .code-wrapper .src-line-numbers span { - padding: 0 14px; -} - .scraped-example .code-wrapper .example-wrap { width: 100%; overflow-y: hidden; @@ -1977,6 +1932,13 @@ in storage.js overflow-x: hidden; } +.scraped-example .example-wrap .rust span.highlight { + background: var(--scrape-example-code-line-highlight); +} +.scraped-example .example-wrap .rust span.highlight.focus { + background: var(--scrape-example-code-line-highlight-focus); +} + .more-examples-toggle { max-width: calc(100% + 25px); margin-top: 10px; @@ -2005,6 +1967,11 @@ in storage.js .toggle-line-inner { min-width: 2px; height: 100%; + background: var(--scrape-example-toggle-line-background); +} + +.toggle-line:hover .toggle-line-inner { + background: var(--scrape-example-toggle-line-hover-background); } .more-scraped-examples .scraped-example, .example-links { diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index ce416f77afe..979e7e0f999 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -62,7 +62,6 @@ Original by Dempfi (https://github.com/dempfi/ayu) --code-highlight-question-mark-color: #ff9011; --code-highlight-comment-color: #788797; --code-highlight-doc-comment-color: #a1ac88; - --example-line-numbers-border-color: none; --src-line-numbers-span-color: #5c6773; --src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06); --test-arrow-color: #788797; @@ -90,6 +89,14 @@ Original by Dempfi (https://github.com/dempfi/ayu) --source-sidebar-background-hover: #14191f; --table-alt-row-background-color: #191f26; --codeblock-link-background: #333; + --scrape-example-toggle-line-background: #999; + --scrape-example-toggle-line-hover-background: #c5c5c5; + --scrape-example-code-line-highlight: rgb(91, 59, 1); + --scrape-example-code-line-highlight-focus: rgb(124, 75, 15); + --scrape-example-help-border-color: #aaa; + --scrape-example-help-color: #eee; + --scrape-example-help-hover-border-color: #fff; + --scrape-example-help-hover-color: #fff; } h1, h2, h3, h4 { @@ -132,7 +139,7 @@ pre, .rustdoc.source .example-wrap { .src-line-numbers .line-highlighted { color: #708090; - padding-right: 4px; + padding-right: 7px; border-right: 1px solid #ffb44c; } @@ -161,18 +168,18 @@ pre, .rustdoc.source .example-wrap { color: #788797; } -#titles > button.selected { +#search-tabs > button.selected { background-color: #141920 !important; border-bottom: 1px solid #ffb44c !important; border-top: none; } -#titles > button:not(.selected) { +#search-tabs > button:not(.selected) { background-color: transparent !important; border: none; } -#titles > button:hover { +#search-tabs > button:hover { border-bottom: 1px solid rgba(242, 151, 24, 0.3); } @@ -182,11 +189,7 @@ individually rather than as a group) */ /* FIXME: these rules should be at the bottom of the file but currently must be above the `@media (max-width: 700px)` rules due to a bug in the css checker */ /* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */ -pre.rust .lifetime {} -pre.rust .kw {} -#titles > button:hover, #titles > button.selected {} -pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, pre.rust .attribute {} -pre.rust .kw-2, pre.rust .prelude-ty {} +#search-tabs > button:hover, #search-tabs > button.selected {} #settings-menu > a img { filter: invert(100); @@ -201,29 +204,9 @@ pre.rust .kw-2, pre.rust .prelude-ty {} color: #ffb44c; } -.scraped-example-list .scrape-help { - border-color: #aaa; - color: #eee; -} -.scraped-example-list .scrape-help:hover { - border-color: white; - color: white; -} -.scraped-example .example-wrap .rust span.highlight { - background: rgb(91, 59, 1); -} -.scraped-example .example-wrap .rust span.highlight.focus { - background: rgb(124, 75, 15); -} .scraped-example:not(.expanded) .code-wrapper::before { background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); } .scraped-example:not(.expanded) .code-wrapper::after { background: linear-gradient(to top, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); } -.toggle-line-inner { - background: #999; -} -.toggle-line:hover .toggle-line-inner { - background: #c5c5c5; -} diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 33d934ff3c3..fb15863b027 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -57,7 +57,6 @@ --code-highlight-question-mark-color: #ff9011; --code-highlight-comment-color: #8d8d8b; --code-highlight-doc-comment-color: #8ca375; - --example-line-numbers-border-color: #4a4949; --src-line-numbers-span-color: #3b91e2; --src-line-number-highlighted-background-color: #0a042f; --test-arrow-color: #dedede; @@ -85,41 +84,29 @@ --source-sidebar-background-hover: #444; --table-alt-row-background-color: #2A2A2A; --codeblock-link-background: #333; + --scrape-example-toggle-line-background: #999; + --scrape-example-toggle-line-hover-background: #c5c5c5; + --scrape-example-code-line-highlight: rgb(91, 59, 1); + --scrape-example-code-line-highlight-focus: rgb(124, 75, 15); + --scrape-example-help-border-color: #aaa; + --scrape-example-help-color: #eee; + --scrape-example-help-hover-border-color: #fff; + --scrape-example-help-hover-color: #fff; } -#titles > button:not(.selected) { +#search-tabs > button:not(.selected) { background-color: #252525; border-top-color: #252525; } -#titles > button:hover, #titles > button.selected { +#search-tabs > button:hover, #search-tabs > button.selected { border-top-color: #0089ff; background-color: #353535; } -.scraped-example-list .scrape-help { - border-color: #aaa; - color: #eee; -} -.scraped-example-list .scrape-help:hover { - border-color: white; - color: white; -} -.scraped-example .example-wrap .rust span.highlight { - background: rgb(91, 59, 1); -} -.scraped-example .example-wrap .rust span.highlight.focus { - background: rgb(124, 75, 15); -} .scraped-example:not(.expanded) .code-wrapper::before { background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); } .scraped-example:not(.expanded) .code-wrapper::after { background: linear-gradient(to top, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); } -.toggle-line-inner { - background: #999; -} -.toggle-line:hover .toggle-line-inner { - background: #c5c5c5; -} diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 30e91077d33..053fa78d1dc 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -57,7 +57,6 @@ --code-highlight-question-mark-color: #ff9011; --code-highlight-comment-color: #8e908c; --code-highlight-doc-comment-color: #4d4d4c; - --example-line-numbers-border-color: #c7c7c7; --src-line-numbers-span-color: #c67e2d; --src-line-number-highlighted-background-color: #fdffd3; --test-arrow-color: #f5f5f5; @@ -82,41 +81,29 @@ --source-sidebar-background-hover: #e0e0e0; --table-alt-row-background-color: #F5F5F5; --codeblock-link-background: #eee; + --scrape-example-toggle-line-background: #ccc; + --scrape-example-toggle-line-hover-background: #999; + --scrape-example-code-line-highlight: #fcffd6; + --scrape-example-code-line-highlight-focus: #f6fdb0; + --scrape-example-help-border-color: #555; + --scrape-example-help-color: #333; + --scrape-example-help-hover-border-color: #000; + --scrape-example-help-hover-color: #000; } -#titles > button:not(.selected) { +#search-tabs > button:not(.selected) { background-color: #e6e6e6; border-top-color: #e6e6e6; } -#titles > button:hover, #titles > button.selected { +#search-tabs > button:hover, #search-tabs > button.selected { background-color: #ffffff; border-top-color: #0089ff; } -.scraped-example-list .scrape-help { - border-color: #555; - color: #333; -} -.scraped-example-list .scrape-help:hover { - border-color: black; - color: black; -} -.scraped-example .example-wrap .rust span.highlight { - background: #fcffd6; -} -.scraped-example .example-wrap .rust span.highlight.focus { - background: #f6fdb0; -} .scraped-example:not(.expanded) .code-wrapper::before { background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); } .scraped-example:not(.expanded) .code-wrapper::after { background: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); } -.toggle-line-inner { - background: #ccc; -} -.toggle-line:hover .toggle-line-inner { - background: #999; -} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index d7184053c87..84af194904d 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -646,15 +646,20 @@ impl FromWithTcx<clean::Enum> for Enum { impl FromWithTcx<clean::Variant> for Variant { fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self { - use clean::Variant::*; - match variant { - CLike(disr) => Variant::Plain(disr.map(|disr| disr.into_tcx(tcx))), - Tuple(fields) => Variant::Tuple(ids_keeping_stripped(fields, tcx)), - Struct(s) => Variant::Struct { + use clean::VariantKind::*; + + let discriminant = variant.discriminant.map(|d| d.into_tcx(tcx)); + + let kind = match variant.kind { + CLike => VariantKind::Plain, + Tuple(fields) => VariantKind::Tuple(ids_keeping_stripped(fields, tcx)), + Struct(s) => VariantKind::Struct { fields_stripped: s.has_stripped_entries(), fields: ids(s.fields, tcx), }, - } + }; + + Variant { kind, discriminant } } } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 995fb5dcc1c..bf111133b9f 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -132,7 +132,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> { // implementations of traits are always public. clean::ImplItem(ref imp) if imp.trait_.is_some() => true, // Variant fields have inherited visibility - clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true, + clean::VariantItem(clean::Variant { + kind: clean::VariantKind::Struct(..) | clean::VariantKind::Tuple(..), + .. + }) => true, _ => false, }; diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index d29ceead4f3..390b9436121 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -17,10 +17,10 @@ pub(crate) trait DocVisitor: Sized { EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)), TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)), ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)), - VariantItem(i) => match i { - Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)), - Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)), - Variant::CLike(_) => {} + VariantItem(i) => match &i.kind { + VariantKind::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)), + VariantKind::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)), + VariantKind::CLike => {} }, ExternCrateItem { src: _ } | ImportItem(_) diff --git a/src/llvm-project b/src/llvm-project -Subproject 3dfd4d93fa013e1c0578d3ceac5c8f4ebba4b6e +Subproject 9ad24035fea8d309753f5e39e6eb53d1d0eb39c diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 1ee96b8231c..387d5787dfc 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -9,7 +9,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 23; +pub const FORMAT_VERSION: u32 = 24; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -334,10 +334,17 @@ pub struct Enum { } #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Variant { + /// Whether the variant is plain, a tuple-like, or struct-like. Contains the fields. + pub kind: VariantKind, + /// The discriminant, if explicitly specified. + pub discriminant: Option<Discriminant>, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] -#[serde(tag = "variant_kind", content = "variant_inner")] -pub enum Variant { - /// A variant with no parentheses, and possible discriminant. +pub enum VariantKind { + /// A variant with no parentheses /// /// ```rust /// enum Demo { @@ -345,7 +352,7 @@ pub enum Variant { /// PlainWithDiscriminant = 1, /// } /// ``` - Plain(Option<Discriminant>), + Plain, /// A variant with unnamed fields. /// /// Unlike most of json, `#[doc(hidden)]` fields will be given as `None` diff --git a/src/stage0.json b/src/stage0.json index c3f50272b67..6a389a64406 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -17,349 +17,355 @@ "tool is executed." ], "compiler": { - "date": "2022-11-01", + "date": "2022-12-27", "version": "beta" }, "rustfmt": { - "date": "2022-11-01", + "date": "2022-12-27", "version": "nightly" }, "checksums_sha256": { - "dist/2022-11-01/cargo-beta-aarch64-apple-darwin.tar.gz": "ebc0b11a2af0385bf11a5183dc159d890161be45d231acc34c6326aa25b84b95", - "dist/2022-11-01/cargo-beta-aarch64-apple-darwin.tar.xz": "a0e44bf77337518e2200c34cb297a91dd4db51f0d331ca4cc496989da61676b3", - "dist/2022-11-01/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "a4beae1c53df4d35fe991ebc713e37246d4d89e5543ec740274605a7124806b3", - "dist/2022-11-01/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "5f8ec5c8b012d7e6bc28ca3d700c1c7c742f6532adb044539cee3b2280c1056c", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "54d8fc5ce70b1f06164e17e34d33abde7260c6b1f3356d98d77271ec89766fb1", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "f2debb6ae264fefc49380997759bb0b5022ac1c65ced9bc17bc146671be37116", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "7a8e10be17c8cd624fb3ae2bb7eaab3c493b637c2c1c1100b5333982d1dfd962", - "dist/2022-11-01/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "553decfc64b56d9967ae067bc942ef7117c81d6976b5fa4cf8e5171397836af7", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "64bdb603cdc05b983393d707e9e6e6cd1c71dd8213d08b3d0d1cdf168ceb165b", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "0afe4ca54c65668257dcad5941c678498ab917bbf82a808f39c093719a53f2ed", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "c7fe3bacc9c4acb9b42677281655904b5ed5aec27042b9a8cf9743b737b6b657", - "dist/2022-11-01/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "57f985ccaa2452778c90733e2586a991969dc15697bdbc9547da8a62c871b674", - "dist/2022-11-01/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "873b2a0c2990eef29d689984293394e6972b4659bd6e4c31fb9bc9c8f1c679f9", - "dist/2022-11-01/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "f8a9e74159594d57ce8dda1f7ce7ee4e1d494b9135a0f32b3afc89a637cad8ae", - "dist/2022-11-01/cargo-beta-i686-pc-windows-gnu.tar.gz": "9570141b118c2339237aac12c1e6d71c138ccef784db2effdfd9d02fb12d0d0d", - "dist/2022-11-01/cargo-beta-i686-pc-windows-gnu.tar.xz": "183b63cded6c4cc26feaa14be036a619289b155a6718f4964f94c38a9208742b", - "dist/2022-11-01/cargo-beta-i686-pc-windows-msvc.tar.gz": "9382bf364c5fc9400fb22b046c0a951001961efac221f5cd0f9bf45b1005d36e", - "dist/2022-11-01/cargo-beta-i686-pc-windows-msvc.tar.xz": "aae0a58b9711365ce1d76966af7387f310b496859a9e02ddbff8e23da93226c7", - "dist/2022-11-01/cargo-beta-i686-unknown-linux-gnu.tar.gz": "507727f9b5a920ea28e7104c9aae681c50fa8aaea446a3e10b991a9408adaefc", - "dist/2022-11-01/cargo-beta-i686-unknown-linux-gnu.tar.xz": "4ebfaf11ffc346eec9f05b2d93123483b784b83a322cca6f5fd406066ecf0fcc", - "dist/2022-11-01/cargo-beta-mips-unknown-linux-gnu.tar.gz": "6407889854bee2e45a00585abb4fc8b387103e33e3e67244dba4e140abe46480", - "dist/2022-11-01/cargo-beta-mips-unknown-linux-gnu.tar.xz": "1aeba894f0ca756dd9c3d9b99c7c94bf1f49d5d87ea919249fd0fcf195eb9c52", - "dist/2022-11-01/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "292a95a8de3387832173d9adde633b3d34a019879f97bf196cb41556c3909337", - "dist/2022-11-01/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "872819f00ab0a848401d7dfbb18cf139f85b3d8e48eee0a034cf7f0b970bd865", - "dist/2022-11-01/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "15eb49c334688e48e83f2565c620b3f1af29775599406efa1814c78ee80673cc", - "dist/2022-11-01/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "e74f6884e71109d36d03f7147b7e506f374ba291aadbe4246f6c429bd6fffd1f", - "dist/2022-11-01/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "7f3cf8b35465e4df5fc18cc7cb4f4db6e1b240a39f7583126d7f8ad6d18e8bf0", - "dist/2022-11-01/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "c59f2893999dd88a55c0a5bdb4436640ae9c18f943baf48f63eff6069f7a3e8d", - "dist/2022-11-01/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "566c315b6206a63bf33acf178547bb757a8803e3cfc71f1f63ee033eb6a17138", - "dist/2022-11-01/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "814a8e8f8f5caf5bb4018e54ffc2c1bd9d23df94dcaffbc04881b91bb3c8aefe", - "dist/2022-11-01/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "5db8a63532be5fb9511238d7976075496aba6c732302dcc27bed9ae61188f917", - "dist/2022-11-01/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "6b95c8cc4dda3847f53fb62ea711ca99c1b1b1639249b8b01d54a9ecbc4421ec", - "dist/2022-11-01/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "2ad497be28760f7e4ec6dfa6421a6c10ab049e0dbf45ecb3a2dbde5db7a959de", - "dist/2022-11-01/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "6e9b982857c64518c10392779528e7065191262a95e091ee289c8668b6cbfc4c", - "dist/2022-11-01/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "88a0751ef36816f9e26e9f6d72809687b1f6821b32a3a17c58feaa32f882aecf", - "dist/2022-11-01/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "bd6f626002a0c5a3af975419a1258a77c9db91e0db5d4acccbc7dbf25ffd17c8", - "dist/2022-11-01/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "69bad5758f27f53d3e48abcd5aa70b16eb29d5445233c65ab50a8ad0a1629077", - "dist/2022-11-01/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "06212f4cb605fb79d811060d3096bc4b43cf00e1a4fe4a375154b56ff60c92f5", - "dist/2022-11-01/cargo-beta-x86_64-apple-darwin.tar.gz": "741f3490b5562afd57cdda846ab322c69e20940bcc11f3ca5690d662d5de280b", - "dist/2022-11-01/cargo-beta-x86_64-apple-darwin.tar.xz": "2d698df7c00b7c227ca388830732a8787b2a85b328b554c0f8c417813d97ef46", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "9c22b476f25c3f0946cb834da3904516248137cf22c5eed30432401ff061a4cf", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "1604c5d60379227d26d819bd2f7a57c79a9e000a6077ec06e95b418bb0351180", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "673d8941202c2113a431fcef396e604d7ea79000c97a64ef6e93b26956f75fe7", - "dist/2022-11-01/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "3d613d04b48a2eb8644e2bfbb07a88cefe02c7b5cc7bf061b8ef307980230d47", - "dist/2022-11-01/cargo-beta-x86_64-unknown-freebsd.tar.gz": "e0ce6fa69af565e3b79f7059a4de88e39955d7ea6866d56c2b0946b47929192f", - "dist/2022-11-01/cargo-beta-x86_64-unknown-freebsd.tar.xz": "de602b7802b1448a861df05c41430dcde4f07358a05711784a1ca37836525b74", - "dist/2022-11-01/cargo-beta-x86_64-unknown-illumos.tar.gz": "c4eacf4821c126b321a67e0233d2f84571b3dcf25686165cad00d9645787f03d", - "dist/2022-11-01/cargo-beta-x86_64-unknown-illumos.tar.xz": "01ec5ab637010498b784ea2fe6aacea626fc341792eaa5a50756f9b483a765e5", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "2e6efadbcf138ab72750c1375bfeaf2d5102559aa9b745294b9973821e193703", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "e089b1b4248ad8e05ba54cfb278101a74aa34154bd2d44dd50119026bf436d1d", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "ca079fce260accce11c1fb27e550421cd0900027e29b18e24e54a298d78031c3", - "dist/2022-11-01/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "ff33e9fd6f06e02277f580f13d82f753987f4dad7d7926405b63dcb362eec498", - "dist/2022-11-01/cargo-beta-x86_64-unknown-netbsd.tar.gz": "46101fc5f53595ae53f3ceb755cc72c078471479a337b5319c85e629e5df3b28", - "dist/2022-11-01/cargo-beta-x86_64-unknown-netbsd.tar.xz": "b063425ccc69284e8788211bbde5a7843bd16a3b9c779fab68a11d22ebdf319b", - "dist/2022-11-01/rust-std-beta-aarch64-apple-darwin.tar.gz": "77bb5db904089e087032c24fa2e011536e13d3982299285a7515beb97f445078", - "dist/2022-11-01/rust-std-beta-aarch64-apple-darwin.tar.xz": "63aae4b9f10f15fb48b2ac20aa7f112a685d49bdf94d8997d036472e928fcbde", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "8f63b6be668e6a25411582db9145c9de8192d58acb42c490b0de89489a3e36c6", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "d862bdeaf2c78b15babaf74cf1c6feaa5c4871a90095f3d4239d81f44217cff4", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios.tar.gz": "e5b1e9420d387a1442c77bed10efebd7b0268713820a728a067bb4ead6088041", - "dist/2022-11-01/rust-std-beta-aarch64-apple-ios.tar.xz": "569c667e422ca7ac373d59b6e13c299cdb7f334164c84e6f0c8d0f076352fbf0", - "dist/2022-11-01/rust-std-beta-aarch64-fuchsia.tar.gz": "3f945c43c09704b3df6af66a2132da12243b13752094383965d6a8a83c6edb0a", - "dist/2022-11-01/rust-std-beta-aarch64-fuchsia.tar.xz": "3662f02892ab184be99f93a9d0f99e030a73cc61447934b74fcba84e05b022b1", - "dist/2022-11-01/rust-std-beta-aarch64-linux-android.tar.gz": "ab04a0228074e974d70a15e594d57479fe22ed37c8acfa5104201dbbe57747a7", - "dist/2022-11-01/rust-std-beta-aarch64-linux-android.tar.xz": "fb96925878a24dc9e90d356e96cf4fd1fc9152c39f8914f9a9bb676d78069cba", - "dist/2022-11-01/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "45e824f75ac530ee9eaf0b0a01cacd5b8dd64ddf5203c032c49fd2bc4fabb245", - "dist/2022-11-01/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "a6488faf4c87cabb4467f4cbe7348d553045c2f10f450bc6e000fcf18ca9b073", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "e2a66e04b24aad8a8898d6c0270d8dcff63205213cea3b893807ef186e8c0936", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "a4244ac1600726b5abe6b5f9a171fc2e4cc57bbe7cecdeaf23b69e906f05e303", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "9e3e0f675ca50b7a2a1afeacdaf5d7f2f4ec1536f596ff99aadacfcb59fd42f5", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "7e7a8fb4fe0283b71deb79c5ccb1ae61b2099392b3c8e09d03d4a68fbab7a184", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "7543df1d71d805b079d19ccd785f777918b3f11b131bca05d079cb5d3952a38b", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "eb082e894047cd77ac3fcc9c03eaaef77e6bafbd075cb0d62ba3a3ba277f5d64", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none.tar.gz": "144fc6973b06ffb12b5ad0bbfc9fcdcb2a0732de50bb140d62d6af3d6b462908", - "dist/2022-11-01/rust-std-beta-aarch64-unknown-none.tar.xz": "8ee2ba2d4eca35a426fb089e0f0b50b2ac3ad1ab036c5f8f4786e2953405092f", - "dist/2022-11-01/rust-std-beta-arm-linux-androideabi.tar.gz": "4a46d6591c1983d0853f7596f7b76e7c82b6b0cbfd97802b565a17aece0d13be", - "dist/2022-11-01/rust-std-beta-arm-linux-androideabi.tar.xz": "3888fe036b5fa9a5dfa009462a002a05c70e56eb70db3a0c872fab1432e9c9ed", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "529d668389506443f87bd93e98dc72d12be9a4ab41675dc6a1c7373e934ca017", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "dffa1a94f4166435d6fe2a76a4d35deb8c128cc93146f181979416816e77e29a", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "2913bc06d6b49c52804a8dc18d1d3cb1b564e0272cba93f8594747731d360f9c", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "c12bb97fcbeeb0a9a71b2575b2d5113948c515616f720dae3891e2aa886d03a7", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "a844ad8a80fa07b9196dc040d5171749daf94443c57348bca04e69b8dad37cba", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "c261662fa988748ed03722d6034228c893e02a0e473f906bba61c1f43be7cd79", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "1ae5967f4fb80047711519dafea21fed8d6afd308566033e468c11587073d216", - "dist/2022-11-01/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "150393cde94d8349eb488a161572589c53fed456c8401e5b1a59d1dd87003f7c", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabi.tar.gz": "b1777a389e4db0ccd80ece774865bc99731c4b483be80c909f1b5a2a185dc5a1", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabi.tar.xz": "877a00491650bac92e93760c2457b644d2b5ee28d410c1e29fc4b40c05da493a", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabihf.tar.gz": "3dfbf001db319a41874e2c0de2f55407285d88156fa0563cfe3c3bb1939998fb", - "dist/2022-11-01/rust-std-beta-armebv7r-none-eabihf.tar.xz": "b2d6a543cdf64a5c147001ea30d07bd13b98e2918a343bff08bb57eed1f81462", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "cd8f0803ef86052d09606601b09dde05d1997a93fad7a22604fda1176157040e", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "748cef6595fcd30da6735c29476639ac80cba94eb627d6654665d656da2979ec", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "1dcae3588a3e552778ff1079a92750bee15835f08f8b9ff1123e4e6c5a73c087", - "dist/2022-11-01/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "3711105029d28fd91f413f488b7041ea42c70e5a244f992e9259b4e9d52abed1", - "dist/2022-11-01/rust-std-beta-armv7-linux-androideabi.tar.gz": "a2af3f6d3681e1c545d0c21bf04fbfe3de1cdb2273fadcbbb4408f5590054d11", - "dist/2022-11-01/rust-std-beta-armv7-linux-androideabi.tar.xz": "23e658070e1cbe8011d48678f57bedbbde819cd64f43509858af563a7073a3fd", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "ff7b429d5a6d33f0e467b333225f7c42de279ccf3e91f3ef7c5463dc06939579", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "8d41b293656c5cf93f46754499e5723a89dd997d3723bfbe56f953a7d864c435", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "6dd89ed0f20a0ea4a279dd4f810c7908c3e8a377da8a2983f8890efeea169177", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "504fb533fca6c46ad98c728781ab31170d65e5b35cbc9199aab97b1146a24702", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "f9a731fd3ea961f0c5eff24e6290aed19d79d5444bf562670abc0cd46ee309fe", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "825acb16e4bbba0c9b535e635b972ec581fe6ef115c5a41bace9b85c704eccad", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "41da8404f0e3cef386f6efef9b27fde27de77de71140dceeaddd8e15260ce45d", - "dist/2022-11-01/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "c8f81fa9cfb40ce92f2c95ef8b57e8a62d819628111e1dfe0c6760fb48802be3", - "dist/2022-11-01/rust-std-beta-armv7a-none-eabi.tar.gz": "fa8c3168dff5c167c6ed25f9c605941ab51e73e70c0dd162a5fd17287c5fd5a5", - "dist/2022-11-01/rust-std-beta-armv7a-none-eabi.tar.xz": "36a5ff7865f8a16b867ab3fff4ac32f0c62c260a5c27385098e67b75b21790fb", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabi.tar.gz": "0417cef6468fd66bf626729e7c0089b47b149cfc43e8e0d4281f76f73ed17edc", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabi.tar.xz": "1de6cb38a68ef336e1edf2c1c51d999482898df99e2bc078cafe6ac5380bf3f2", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabihf.tar.gz": "91003d4648fb01306d6e0a0214e089d444a57c5ff09138040f07cc81e89af639", - "dist/2022-11-01/rust-std-beta-armv7r-none-eabihf.tar.xz": "884306ac77518ece0cb2f22d898e3d2aa50698bd4181ca23a1dada6d82778682", - "dist/2022-11-01/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "f17ca8f54eca5d73006659fd08142d537eff23731b6e5a35bd67efafe0dc8cb1", - "dist/2022-11-01/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "b04a17d33d7b9b1caae666dfa5ee9a98e5dc079773b6345f6c49733731e14bfe", - "dist/2022-11-01/rust-std-beta-i586-pc-windows-msvc.tar.gz": "55e61aa74bdb50df54394a0f62b9edc88682c37b51fe9d8d5c05c0619eacd1e3", - "dist/2022-11-01/rust-std-beta-i586-pc-windows-msvc.tar.xz": "ec3d887742289ef9c171ae56ca20c3e9cf1972cc3e6c511611404070c55dac8a", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "a36444f0ba0e7e03d06fbf65d830cb7067c675ed061e8f6efd6ed445d5955e88", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "dfc07297ee8cb63f76d2019ae822352e6b42e5cccd225eaa5597a63ecff3624f", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-musl.tar.gz": "e8de9f830cf277be584b54d86d6621a249fb2987fdf32d5f16cde9b492722d45", - "dist/2022-11-01/rust-std-beta-i586-unknown-linux-musl.tar.xz": "f9d8bd74788e2209ecb8d0cc49d94b4e2752c9239f89bcdff3e8fae315d1d923", - "dist/2022-11-01/rust-std-beta-i686-linux-android.tar.gz": "b15636654925fdba1e9ec1704573e4af1fc5f1158a0657b245901e22c06cd378", - "dist/2022-11-01/rust-std-beta-i686-linux-android.tar.xz": "9abbfcaa40d86e8a4cf49f2a58b1c7b2f422b6890303cb43feb83cfb8f650a42", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-gnu.tar.gz": "30953eb457a397966221dad058ff7ebd99ca4497f184016b5a61db0f122bdee9", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-gnu.tar.xz": "f9d6d266eb3bb46c058615786483d817138aa29efc3c62c3cd9c87e572956b12", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-msvc.tar.gz": "b55202c349a4e9a493a2de7a3d48788befce32274998d3dfc1d1b6f4a96ba9e3", - "dist/2022-11-01/rust-std-beta-i686-pc-windows-msvc.tar.xz": "6dd8d42e5712d699704e85bb90cd42e0142a4fab7cf7f80132cb0902cc415ccb", - "dist/2022-11-01/rust-std-beta-i686-unknown-freebsd.tar.gz": "d2a7c9e7f1dba3a317692a46f8efec8d7ba1e9e943c88d3f342a820c34829aa0", - "dist/2022-11-01/rust-std-beta-i686-unknown-freebsd.tar.xz": "ecf6abb631dd6887b5630d1ea0b8778fc1539405e6c00d7585c8afa2230ef9ec", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "93c5912258a49a003a12ca01101f5935d5894f9a133301a47047cca934a7439e", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "f8a6e67723cb968e874827a6148a5e25d3d45c56577faee627010347d0f03d92", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-musl.tar.gz": "8838592167a8d68f463dc18e55d5d2d55c474426e8a4ec0f28fd2cd4230cf638", - "dist/2022-11-01/rust-std-beta-i686-unknown-linux-musl.tar.xz": "c8330a06862a7f375b57774b382a54a1280c33ddc1b94d5d5ec45eb6ff0de8cb", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "4b50cc174eb1da9dc831de828e6ee2fc8a81abf8e6dd52b041e4ab00eaff73ac", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "4820db058569be7350a81396fdedf9a28233b8061c9bcf607cf2d1058cbf437a", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-musl.tar.gz": "dfbc460e8322114bde5614b0b45e90066805adbaca999ccdc4f2aae456fc3f1f", - "dist/2022-11-01/rust-std-beta-mips-unknown-linux-musl.tar.xz": "d98c19268b0c84f44f1224f432847a93eb809a85ca48fbe2e4b68fb436bc36aa", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "8617edc6d62591d50dbadc4a7bc41b31b66bee6fee830af46636c5206027217f", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "98a6132c8dd7558eb5f44007fa681a3a91b2dfd98d1f68e59f0a4660dc37b500", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "81f794c54d7a8c680c52a8fc1a0e479526744205d51266007fc3c542496957ba", - "dist/2022-11-01/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "dedc5b1a76f8454d1b3d7fda0a05398e5a9ae4cf16ddc4b44477799217a1fb75", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "6d9b3d469ae92e38144d9578de8cf0c891e4bf3e667e4e465eb6f0d498140c3c", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "f9deb84c24bd0f21ed02d763d3ad8dd92c009de4ceb2b78ec06d90d66609c5f6", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "073882815493668dd484b8f107efc047f6e07d8c563703d0e7f73ef33dae0efc", - "dist/2022-11-01/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "d1ab3758d1b08937a3f98737ff9fad20377e5bc43d7ab3a9359b4131ea11dcbc", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "bc82f3d23dfb7b331558180f474c334ca3798322e19cc64657cbe894d0682901", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "fcc12f82ea0c02e8434420165f1ee072bf4587a82ff5ecf34d19f754ffc091ef", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "1c4507c7824c02b1af2857c88ff1624e9ead3f38c1456aa031586b43223e9490", - "dist/2022-11-01/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "932598fbcc35ee4958be4778450f5b809ce9eabb2aa3d7573fd79744ed4d18ad", - "dist/2022-11-01/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "c17f11707c1edef2353fba7e3f4800cecb8a273233825817b6d07ed78d6acd50", - "dist/2022-11-01/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "7e90a819b8887f0b1a3ab02fb9a56a9b9eb752408a7bb934c99c7f6ddda48a71", - "dist/2022-11-01/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "c437a6fc7cd7869df7cdbb52c51ae1e602ed1206517c38689deb73da6d7b4877", - "dist/2022-11-01/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "76c1fc55b16a809ab1c8dfce894899f40d24b20dc670d318a7679953beb6c3a1", - "dist/2022-11-01/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "d62396390fb85d5543a80ffbeaf7c32b5297a513dce14790124c35835813032b", - "dist/2022-11-01/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "4595485492c650aa53bb9deaeb425ea956f2052c5b5503bb477778f7bcaf6ac6", - "dist/2022-11-01/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "ee841bb8fbb0075a0bf51db2007bee2962830a89649c00fd15c67b31fd9226a3", - "dist/2022-11-01/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "cac036fafa93f2860a5a2622394e12938c35e629ff81d7cc5930d99c980f9321", - "dist/2022-11-01/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "025d70e57d608b81d61799c84ccce9bca3603736c4d3e006fc662c3a7b39e8db", - "dist/2022-11-01/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "9450b1b1f95e188bcb9050085d612c8bef36e819881255fc20d70da1f45fa61e", - "dist/2022-11-01/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "ff707c6d209f9d8e421fc530a11d41a46daaebdb4aebd5cfbaab761b2cf192ff", - "dist/2022-11-01/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "8eb48a94c58440e2afc8ef7bbdbc725f403fe38724c0afde4e7c29a1ba2c7591", - "dist/2022-11-01/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "e921a841b7a9e02e28182e91c921746042330d90f0478fc7e01230cb1b881c1c", - "dist/2022-11-01/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "122135e161a4cc7dd857e3cb35b64ff7db450dcc07cbb990c8aa83e06bb4b346", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "084824d6daeca6a0662ef1e11df84c651138d8d4e7d5c8ef66c5811354b16211", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "09e3df606e10a0a59a67bf7b49825a04c23062e6050cebed674e0bdb2c396fcc", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "f9929f62ffec9c6b3342da8dd21b1c14526e033174a4f86015182acdbb93a985", - "dist/2022-11-01/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "932450fc6b5e8fa4813886baa389b53c6ff1c5b1e71f7370017b9658b04fd13c", - "dist/2022-11-01/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "e7776d188a04779e7f6a7257bf367d8671e7d5d804d74db426592f683cabf562", - "dist/2022-11-01/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "bbc765adc116c6a1bcbf659853b7169d95b240ffc15227cbb1d60b46d63e120a", - "dist/2022-11-01/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "a0ff6e9ea827d7f93563aaec213eacd00efe4be9c921b448405b2af8bbf0066e", - "dist/2022-11-01/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "7603744cbbbbdec5b2a322aabe68751e848ac7379c710866c59dcc22e4b873bd", - "dist/2022-11-01/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "1f67446eb09505e87a5218b8504dfc678d0a712a5add763362f3c74306010bea", - "dist/2022-11-01/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "1baca6f0e7f18a8eb9efcf35bca4320a493d51f08e62bf96a31036e2f2c433fc", - "dist/2022-11-01/rust-std-beta-sparcv9-sun-solaris.tar.gz": "455e52fa3f232c2239112030483c0a657e7f69754d8d36ab72423c76c056fb68", - "dist/2022-11-01/rust-std-beta-sparcv9-sun-solaris.tar.xz": "913801ca45eb1d70c9ddfcdd66aa21edaafccc85acf9864e88991bf8a5a7cf25", - "dist/2022-11-01/rust-std-beta-thumbv6m-none-eabi.tar.gz": "14e4f69fbf710f16275ccb582a90eee1399ea1226945c7c96f75335df9118966", - "dist/2022-11-01/rust-std-beta-thumbv6m-none-eabi.tar.xz": "40549d9d9c923a73381b8e45628cfa1896d0e78caabf2aa921c767e0bc979136", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabi.tar.gz": "d40bd56883abc142155188674580c4e29100fd7303fccc70b0c55b964721a156", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabi.tar.xz": "874c97a01d06e1516a89797d7a6effeabf34afb4933956aa34e907a65ea78690", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "cf7acd2b4a083522c01f1909891aaba27502ea0a3a5eff93dfb41971f832bba6", - "dist/2022-11-01/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "e9544acbefa3effe55537de85311b00077a0567d64345aa80414752037212b5f", - "dist/2022-11-01/rust-std-beta-thumbv7m-none-eabi.tar.gz": "247e9dae16f46c64da895528f3e902030110e2aad8270f169c636ca14bfc28aa", - "dist/2022-11-01/rust-std-beta-thumbv7m-none-eabi.tar.xz": "b7de9e8bf7b7d04fc9575390d69eacbcc62a39c35c81f37d2170424cffe6a356", - "dist/2022-11-01/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "bd3dc986a11967e8ed050a88d03d1c0814b08cc1ab0cf929561fbf5a941a335e", - "dist/2022-11-01/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "262b4c4ccbe20c9e913a7417c8ca72c6fb7e71f187103929057dcd0fc0b49cea", - "dist/2022-11-01/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "85f6a725e5a726afab9ae019944567b42ee769db98a8d3c335d449eca92344e0", - "dist/2022-11-01/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "07e897f4320f249b3f458e44e5440591962105a3b6032b54f4448c0bd21da964", - "dist/2022-11-01/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "e92855841ae93990f88f3893a1bf511853fc3f10938eda767d5c7ff7d310aa4f", - "dist/2022-11-01/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "3c3412a67f769ead9e8bafbcb5ff6dfc8ef89f0d8234baee7b39ab9df9fadebf", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "f3cd623fdd466e5c0b5749dc4e90a75122f1989f6fcae0ace8c76f3b394a0752", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "3793ab2a42f1bc59ad560ad1af75ed90c49e25f665330b5b8ce50ed73ef88508", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "cc6c715e320c7fc5fd90f446f7c2ce6b356e95934d05f79c4e2d0fc304f212bd", - "dist/2022-11-01/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "42a47ce6768b24c2b40c6a724003a401bfb37201a773e3c31ee413cc559cda70", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "4c09e5b03a921d8c1d8a10d9535e81be3b3bbed961d229311cc691396ae10cbb", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "775f7223bc5d962b5356a4884565a948d3cb5289fafe3e2eb2b8ad67550d72b4", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-unknown.tar.gz": "bc027d9170132c36faa47da1ff8f26d26d383a5145cb9dd2dce20e769ea300ba", - "dist/2022-11-01/rust-std-beta-wasm32-unknown-unknown.tar.xz": "9a721d3550132930820d9b809074535d2b63ecb91d5c061effded92b503bf0c2", - "dist/2022-11-01/rust-std-beta-wasm32-wasi.tar.gz": "047d58ef5e10ab51a81dbc11646fca184945a1c52e7a91552449c67952c8d898", - "dist/2022-11-01/rust-std-beta-wasm32-wasi.tar.xz": "a490ce6ebc77a4a49c2fdeec471dd9e586b2aa26f1e7f2fc1323cc06b2b336d5", - "dist/2022-11-01/rust-std-beta-x86_64-apple-darwin.tar.gz": "df73bc81d446792d9366772944a04f69ad32f427e1949e05d4f7c202c350c269", - "dist/2022-11-01/rust-std-beta-x86_64-apple-darwin.tar.xz": "450aec3ec53594869bbf16ffe1713dfa19b8dcadd812a4af811bd56f1f58c929", - "dist/2022-11-01/rust-std-beta-x86_64-apple-ios.tar.gz": "fb698f63336a186983b09c2c49109dd080c22653f3367dabfcbae564144aff35", - "dist/2022-11-01/rust-std-beta-x86_64-apple-ios.tar.xz": "0d475ba4a4444f4da5fb39d26c9cdbc0352ea799d7e30f57e2e79d8c3c7a7021", - "dist/2022-11-01/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "137234fc37b93ef4fa543f4e33217079137b4dbb51efbea669b93e561932b5e9", - "dist/2022-11-01/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "01e1978d9359a5112aa77409ff17c3d0e0dec774815f679065db6c6293aaa623", - "dist/2022-11-01/rust-std-beta-x86_64-fuchsia.tar.gz": "662e62862b1586f29372339319680c88b7cebe41e98401b5dd62e320755f0d62", - "dist/2022-11-01/rust-std-beta-x86_64-fuchsia.tar.xz": "4a644c6c85c8e427d68a669b0f598669023e2c0db2b69b94a7124c18772052dd", - "dist/2022-11-01/rust-std-beta-x86_64-linux-android.tar.gz": "752a57eb3de0060c1ffc6eb0af71d88d5f881b543b11b209593be2b18af1f902", - "dist/2022-11-01/rust-std-beta-x86_64-linux-android.tar.xz": "19effccfd9d63e955cb0736968c4c300c6d919217a64cde464c30a499ae9fd9c", - "dist/2022-11-01/rust-std-beta-x86_64-pc-solaris.tar.gz": "aa8a36ec1892c68a1c1ea0d9ac1b92b03c975a0d8ee538aaee5d757ad84d5b2e", - "dist/2022-11-01/rust-std-beta-x86_64-pc-solaris.tar.xz": "955ad79007d397a9e24d819e95017880b25424bdac01386cb8fc6d50247b1274", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "9f15bf80a2384f2fd333dee41289fdd8529170192dcbdd8cba0a73d32715ccc3", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "539bcefcd6b888c5f38abca47792dcff1676ef31eeb9a4a045703582262758c1", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "748fd22a993be659f85c3799871c4de09a99fcd7805c6d0e9d5a18dddfd2e26b", - "dist/2022-11-01/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "68c22dfa2ef5ecd2d43661716e8a8394eaa36e8e960d34dc421bbbe57c3e0d23", - "dist/2022-11-01/rust-std-beta-x86_64-sun-solaris.tar.gz": "f06118445fc6671d491c61dd8e6ff83ca21fc1d692058eea072cbe01ff798fb2", - "dist/2022-11-01/rust-std-beta-x86_64-sun-solaris.tar.xz": "b3fdd56baadf3a8bffd17730d61b2ccef25ffa25d5cd826bb9a45940bf573fb5", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "2dfab0336a523182d200c7a6096fb29c199339b282ba03b469a9a1e5c5a5bb0b", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "ee5b9158ca0c2e829bb79ac526d17a2ba27ca4e305e134241ba1f8347a9bace5", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-illumos.tar.gz": "fe62b766d11e9ac55db5011a63086af5d87ce560c0656dc214c668db752675e4", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-illumos.tar.xz": "e4b1068de2812c62e7ac0ec080f605fa90123a94563dc4f898221275fbd5178b", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "c5ce6885405ba4d1694a7eb767837320ece5a02133e94c1c22ac07143d6f752c", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "eac46cc9200125be2548d6b9f2c2d37b046b8b43b25dd7f7347d88ef6795a3c7", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "1b3d1d051cf355eb26bf9de5096d984f83dc92fdeab3bdcd18d88152c0e2a2bf", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "a17cf4a9df1b1be17f5163f05665bc40638e62210d8e0623fb1afeeb96acad2a", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "90a2e5712bc37f28a0d1f71c54cc04233049c638e4f0592b50adea352e21038f", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "ad76d090357f5e272b1598c35dd24137fb9950e1bdc50b9332fa1d2fcc33a00b", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "37e0954add559b24c08ad284fb80294e435491159db63ea78a6183af5926dcec", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "d6542bd592edd3924999e690416b6bc559486388add76fa77044114b70700fac", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-none.tar.gz": "d021e49b68b8321354d99ae0fe80a6b042ec798ca7fe37cc92d4f0c0480f7ebf", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-none.tar.xz": "f6202c50c6d3575fdb398a8c98adeb0d86794b60c3951887c90a9e4acb6a89c0", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-redox.tar.gz": "b8ca678975c0c18d0fda1bb118b35366d1261e366639b8bb455b6bc59388082f", - "dist/2022-11-01/rust-std-beta-x86_64-unknown-redox.tar.xz": "119f9e65dc3484f677064e068da42a1e7b8dc0be21d0cbf5185c9836589b39be", - "dist/2022-11-01/rustc-beta-aarch64-apple-darwin.tar.gz": "11aa79c56a9dea2d5305ed049485a1257912fc0dfca1feff37b768971f4c1701", - "dist/2022-11-01/rustc-beta-aarch64-apple-darwin.tar.xz": "a031051ccf97100bd8b4d2e4df7a67371cdf300df4697e1d05a7cec33a7d8c09", - "dist/2022-11-01/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "4d015042d7d06929488f607bc56d925002e6f352d74fe192dc30e7feebb9947c", - "dist/2022-11-01/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "d72824112c96514d927df46f6e755898d26ddd5b805f6c2c0411c773105ad61f", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "3e70261ed7c130cb7256717cec0c37476961932be228e46e028818f9076dfccf", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "452f07f63888cf27ca2d061751602bb07a43348eca9cab30db27940a36f496e5", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "995a6410305d43234eb94710ddc251bafd9f5fe4ecacc51c4dc1447f364be30a", - "dist/2022-11-01/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "2d586e5d1a72194ce2798d4f07c873d52ea441cabe5040ff682664d618b98d4e", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "65954bc862cd149cae2702f25b186fa2166d80cb45bfe6867d075381f2614464", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "f3a5f8318efee7eb9ba4d861876b0a5415f308c9dc2cea751a10b2e259303627", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "d4be89140f0bd4ef9f73a1b54f949973ce560c4dd62c664974f82278ca0d6079", - "dist/2022-11-01/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "5b381b513c27f95f9d170e9c532839a27facfe6eb4dd215c078b44fde40e3ba3", - "dist/2022-11-01/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "ffdf714a07408901962c861103b062adf334e0febc1abfa8c538c40b0070793e", - "dist/2022-11-01/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "ada55533236ef8c629ca72f929bb87db4b68f8c3d4c6fb3e7001f892a84a2b82", - "dist/2022-11-01/rustc-beta-i686-pc-windows-gnu.tar.gz": "b7e059973b61a4d7a0c96b4642629bf72668380a5ad8a2962181b1229ac2174c", - "dist/2022-11-01/rustc-beta-i686-pc-windows-gnu.tar.xz": "9aa3bc05e1782b8ff5d278f5b5baac4b0ae523ad8bba2bacd46e1bca11cd38b9", - "dist/2022-11-01/rustc-beta-i686-pc-windows-msvc.tar.gz": "acab77f5641be0d7102e6b911f134aa36b6fcad5ac594100889ed0e494eccca3", - "dist/2022-11-01/rustc-beta-i686-pc-windows-msvc.tar.xz": "e9af106c009e5fa0da36450a7a89a148ec176bd672ff636010846ab978804e4a", - "dist/2022-11-01/rustc-beta-i686-unknown-linux-gnu.tar.gz": "546e7b52f7f9e8c9a99163265dbc8a5ce65dac0fef4f6e1dc8b1bed79f0a24c3", - "dist/2022-11-01/rustc-beta-i686-unknown-linux-gnu.tar.xz": "b5ea7fc6016a4abcae3337261724ca2bd21025856134e1c2a1a1922d12ec19a8", - "dist/2022-11-01/rustc-beta-mips-unknown-linux-gnu.tar.gz": "0f3e0c8e7883dc7ebbec38e1f3446a33651ebba9a725443856b09ae7e8bcfec0", - "dist/2022-11-01/rustc-beta-mips-unknown-linux-gnu.tar.xz": "42871f7f098008f61f6cfd3cf78240156280cc7f5e52860d8125e22b3733a207", - "dist/2022-11-01/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "ded0d4da36a0658d46c6705c04fa40d0894b6e113776d2ef8e954e9675e98f9a", - "dist/2022-11-01/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "2f9ec1ba69a7abbe4efbc5fa00715f520b4c69792b96e98ed8a72e3f798eb137", - "dist/2022-11-01/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "090431409021fa0167576c717cf5daac750f9baf7badc3bc031547dad8dedb18", - "dist/2022-11-01/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "0542d0336c8cdacf8a830d2a7c3218b76a00ae37db23fb2f12b928bb7b7dd488", - "dist/2022-11-01/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "2d6db76bc5242af8c2199c5e74f152bbd8103477855379e7c5c200b498ccf901", - "dist/2022-11-01/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "0dc803a305497cc905f3937691e4f1679c72a385b57ee931b19ac5347052c502", - "dist/2022-11-01/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "809f547fb5c27c7d15816642839f9ff5fee20f03a3ce390d5b2bfdc983a7c7e2", - "dist/2022-11-01/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "bd8403226676b78b40c7a494b3a89f9bed956e7eedf3a65a61cba41a6382f5b6", - "dist/2022-11-01/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "12cd357dc72d67911a521dc0ea44a8d05bc4c214a7f6b9e88872ddc03811dc15", - "dist/2022-11-01/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "d92f790cabb85373455b5adee9e692dc934dff60eccb70c077f29cde35e7cd00", - "dist/2022-11-01/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "a175a2b7d948459c12f44592c1ee5c79825a120557ff0c488fb0bd4e45c7ee99", - "dist/2022-11-01/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "d047a4ed562cc91469785fed44d97061d60e1f9c677b5de05245648373df111f", - "dist/2022-11-01/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "1b1f20032337e6a0b5e4745a3542a5638747bf2f3b62b2eb855c0ea1ac54d81c", - "dist/2022-11-01/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c8a46c9c002ce19e940a449a4787055b4ad45076a606bd68626a1c8d892d8191", - "dist/2022-11-01/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "547c670fd6a5f38f98e7b47daaf6822fd5a1abd5a7c11b6f2b5838cb145c615e", - "dist/2022-11-01/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "16a0783135c22b64541cbf9201e5f84ab4befbc9ec0117f3e9639cd42dcb81bf", - "dist/2022-11-01/rustc-beta-x86_64-apple-darwin.tar.gz": "3121d060a0306c539334fb42c0c6edb6295eb4b5d05b63e55df98d5dc1cb0eba", - "dist/2022-11-01/rustc-beta-x86_64-apple-darwin.tar.xz": "4697febb60fdecb5cd70bde0cffad77cdcf8cce057349b4e1f26e3dd4f2f4a51", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "c33bb5e98d83f0a7393c631b6b53eb4a8517bdbf506e1ceb6f0bdd8493fa24b9", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "167e1ab52c4478e6aa8b2bea563f2d8caf3605158731a892181f9d24b027ffff", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "efbe536d85810f2edb6bb7232617f12d3f208e077d177c24f507ff02c8e83a11", - "dist/2022-11-01/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "b6acaa3206a3af7fe0e97d4d9211fc76ba972afcdd188443a72027dd34236658", - "dist/2022-11-01/rustc-beta-x86_64-unknown-freebsd.tar.gz": "8eb739094411afb56ad791b84aa2ddcd2c98b6ca5a4c1cd7fa631571702f1d67", - "dist/2022-11-01/rustc-beta-x86_64-unknown-freebsd.tar.xz": "4572c19bf416c188a3691cc9542422b92a124594bdf83c82213d07a3aaeef465", - "dist/2022-11-01/rustc-beta-x86_64-unknown-illumos.tar.gz": "eca080758173b3bee5a1ed7d04473a8334422fc58c762031877e690a255202c8", - "dist/2022-11-01/rustc-beta-x86_64-unknown-illumos.tar.xz": "68b1ced7efbd6bb4cac647e7417b2ad982f58a1cc546b9391213e85e5852ce6c", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "3a4870b33c0f223dc295fcf3f1c4e331a2631dbc07279f4ca7452d86c5f6e730", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "556821823576a5c0387f0dc89139d3cddc2a17072199607c352fe4b190b7f02f", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "4e1723c8f268eecc9bf3efb16241ce03bf109b9f7c6f4f62e430b7ccd1c092cb", - "dist/2022-11-01/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "47bb3fb8f8529f19fa9725a43a57abd8bc3c7b2a30e17f86b137df0c57a3c549", - "dist/2022-11-01/rustc-beta-x86_64-unknown-netbsd.tar.gz": "530c24d950028d0745110672fad230da8a2a0e4cd4e5ac5afcf1ff8562288925", - "dist/2022-11-01/rustc-beta-x86_64-unknown-netbsd.tar.xz": "cd3654b33b3a8e7fbcde2e380bf2914cb07fe6f8355c8810a5bcfe3a05d63f84", - "dist/2022-11-01/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "47527c62b813c0612b80c864b3720b7e0673eb2dd762887254fd6a80f11c94b0", - "dist/2022-11-01/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "82248dd276ecc0fd45031ba131cb2c870a4b3c09b822d8ad4454f26f506d7810", - "dist/2022-11-01/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "fdc9cc842850023e7c22ac22173a18aa5383a2e2fecb713c802e59d55cc5232d", - "dist/2022-11-01/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "10ddbe6a89cadde47f6f52ef0c4f9ab08f4ced2281fadd1ecbc6a0e4736c9787", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "2135c6d129fa7ecd831e451e173c38677ea39975a91cd6092252e4c0bd93eeaa", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "387d43021bd0ec1586155d1b977470646a68e2625fc192331b76180755687d37", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "41da916cbac667f5f238c3aee3bfb230c3345a4d625779c1fcf57813c9138696", - "dist/2022-11-01/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "f28cf712bc617f1755e78a7a442633a7aff78857b98d9aae473effc5684ce8aa", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "065fd7fdcb9f38a9c08b256b46627c8ce38a6433dc162034a306f4d4f4627a31", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "1fc14261867b540e6d014cc5a21c557d0a4bb31d2619ae98a330585915365614", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "1a9ebea072c333e99a3339a87ac3971deb4fe2baca9bd0e8429321a81cce847f", - "dist/2022-11-01/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "1c7a72cf8e9cda52d02bd5f4244164aea829914087501cb0bedd75f05f464a91", - "dist/2022-11-01/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "1f8405178138601f65dbe10f93d326c705ea91f9e7200f253d6123f618d09ad8", - "dist/2022-11-01/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "00365767eb739ecd82c6264795768baba07a101aacec59e137a7495afd0b3288", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "b2e4c4672f440e1f97913497ee158280cb8ed70c81cb47a85e5382cb3de0b03c", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "01bea91a3ab8203b32cbd1fb2945a1eca68179e8f4011e387a230587fc2736a4", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "2d0db2a9f187d300c183cfe2ac6778547ab6492720c0e9df3e78f5b06004e758", - "dist/2022-11-01/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "b89b02b9fdedb9a93dee602dd9c818e97c397ef73c3f1d0164ddd2ab809cddc2", - "dist/2022-11-01/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "4498a8e6d0ae7a793a9f3c84e3bbe9218c37053a1f3dd6a0b4ad7edd1a41493f", - "dist/2022-11-01/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "27041aa61921b767be6670f0f08aad1a1ab8d09d0e86cd2e431e54744ed25d0b", - "dist/2022-11-01/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "870923556049bd4be8da03fa6d876fa8249e4acf0ea2c83850c4e23a09fe577f", - "dist/2022-11-01/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "8c05e1f60a59064c05db7522245d482b559ae858a5c9c772db81a05daa60a4c6", - "dist/2022-11-01/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "1a88c20701cc6f7dd2b3e32bef72a78936c39095a35237fc4a4b5a497790a048", - "dist/2022-11-01/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "9b5ccf5413650144a79f382efd12204aeddf3421ea6f06615afc489cdf30691e", - "dist/2022-11-01/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "4bcf264ba7ce42aee79d76ba0f19818aff71ee666ac4ac417c2a60b0dafa8865", - "dist/2022-11-01/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "fd6ff248063cd53ee6b0538c8b3c8af1758ae5c42cc2f5fc805ab96799033f7d", - "dist/2022-11-01/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "a03cf4d831ba58d1e562d6fd48dd7558d9034046ae7050883eb1d0fc2cad6895", - "dist/2022-11-01/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "30be7166fa091929d1a4b5eed4b72c4b5c94898861f4e91fb45a2b9ad4333ca6", - "dist/2022-11-01/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "59f3910a559994863f1910ffcf34cae348d0c07128d00ce5ac085bbca349f7f5", - "dist/2022-11-01/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "817df1ddab344e47df34c73918c5bbb3a7b33048f8ac5c5794cb35624f5bce24", - "dist/2022-11-01/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "7825a5f19cb29245de96eb22183fbfc38b75eda0ba63d2255fa062f9c6764bbf", - "dist/2022-11-01/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "0d6384aa1162d821edb6d22326b0a1d481e6735d4343a70df7bead694bb71567", - "dist/2022-11-01/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "aef195c86920cfecafc29f80ce6a88c704f09d72011ad1fd462564bf858c75a6", - "dist/2022-11-01/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "da43e621a113d88f7c4805f70cb5208bac66f97c68485a60f95cf11f5ae0f55c", - "dist/2022-11-01/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "2603b5061d059655e3298df94875fa4876d5ea9af1e04dd197ec5cefa3e1eb4c", - "dist/2022-11-01/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "f79606c20ce3bf64a9ede63e878cda199e7f1b0b13f40bd51d7108b3d4c72cb0", - "dist/2022-11-01/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "f6c46ffbb38f8838c496e1eddea7d6f27392699abfafd0d13b234eee39238181", - "dist/2022-11-01/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "9244fc29cd3c32c971f44fcdaa26623b8976efaf0a4705b573798af5b0b0896e", - "dist/2022-11-01/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "bd502f9105d56af252da1038687a4e942a477c7047cac9730de7414cdbbfbc48", - "dist/2022-11-01/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "426785558da44683a554c542475c9402932c72d63148c37917e8cc6e429ad413", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "52646c86ad464c5803f74ab37166dc1692383bc5fd94818bd579e518c327251e", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "67d1490a41932c2a89981e18c9735d4437faedd1e708e26f75dfd21d4709488b", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "9feb7b704a6d3e6b019a99ecd033042ce81a4b126e4288e0b4772266c6e0a65e", - "dist/2022-11-01/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "fba240009d3f27e04200133120c46112ac64281e99952da44d6fe8a01557f236", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "ce15bda4992ada52f94dae6b1a0e220f26324acefb62094035abe112aa878fec", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "189a8579cf3fe99b9c084821ce1ee9bec6977470341e2ae45b859dcdacf65d21", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "15abcd9e43f2c87fc894b3e280a99865508f9079badcbe7be07c6b79e85f01b4", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "f52dab31a428e568518b00d3afc1426569810bcd20a7db1c0093200c6db86d24", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "57ec35b95a5fd803b2d4dacf7657847111a6cc9bda3cda962174965cd6005085", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "96987349e20e3f602bb6f518924660c09a4575887730b1bbe36adee921921956", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "76d6f5882573169985f5b8a9e13cee8bbe3bd3b423ad287280a0809c6a5efc5a", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "9a2c79685b4ac57efea65e43dafa28b59cead1c14e98f10e0196cb2cfd2fa0b6", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "0be98b45af7e666955e6e0adb5b4cc3f5517c8d144702b10daedd053450cd5d5", - "dist/2022-11-01/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "ae9ac6e1c0e14bfba746f3a85bfa3f009113d0edbf880a2cf20ece6046ee27bb" + "dist/2022-12-27/cargo-beta-aarch64-apple-darwin.tar.gz": "00b7df89de07931d150940536a1e6c980897ed0e9880bb6f24d5ebbad896c8f2", + "dist/2022-12-27/cargo-beta-aarch64-apple-darwin.tar.xz": "17e1e9cf2c4dad4fec7f420f43cea21923d76ba2d6f87ad67c90ea9c8e4a04f6", + "dist/2022-12-27/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "783b7e2569490dffc953d4b24e659fec384739ceb8bad37e3a97df374945a91d", + "dist/2022-12-27/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "a9402480620b03c010cb18dacca9a95c82e7b6078d2c1163543bc4292d7dd300", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "7fa9aa92c2b1268420f60af2826dffa50b61c9926a2a1cd1c8273fe5861cde11", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "97d583ed82db1fd5a03ce44a660f1163d0812b6f352adc6d78e61d7ae4fbfe23", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "69236898b091d6ef31445eb1223acfc01adf21fb1aa277a7d441eaa300c0c9ad", + "dist/2022-12-27/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "4a92788cdba1705b79ce9999d45a62d4631dbc59cc980437e1635dc908458b66", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "b35b72b16c59b38e38acddf2c06c2c819ca78f146bbf4f3ce9d7ff982b86655e", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "81d7fbe3f50cbad04c2ad0e118001976a880d23ad2a894ee49c6f6c10583d10d", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "942f6860e2cf9da7c5399d308acad43f862750bf7d383444c2dd636b86553e14", + "dist/2022-12-27/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "5f2f3c7186a2cb28f96bba8db7d404b0f3338bbe57edd631bb16fe4d2c8d493a", + "dist/2022-12-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "f15932518f114587c3639ed270cab3e4ef4eb28e0abb6b59b5f63138fa43e829", + "dist/2022-12-27/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "41116748ab087e0c7a5354508fb95e1a966212ef5cac40da59e363108077c3a9", + "dist/2022-12-27/cargo-beta-i686-pc-windows-gnu.tar.gz": "37bbf0a9dcc1b3fbc11a5f72de922fb0f5dc80a632d803fa0a892d72bdd457c1", + "dist/2022-12-27/cargo-beta-i686-pc-windows-gnu.tar.xz": "7a8afd8a69e1e25e47122096920217bbe765e82e831583420487702831241d5c", + "dist/2022-12-27/cargo-beta-i686-pc-windows-msvc.tar.gz": "c40ec16780156f6568bf8f1353a3bb367d4bec09dc6e98b03de44bd2ed301ae8", + "dist/2022-12-27/cargo-beta-i686-pc-windows-msvc.tar.xz": "94320949f071236d828fb1252159f0f2b1f18030303af1ae0b7ca06cd9567de0", + "dist/2022-12-27/cargo-beta-i686-unknown-linux-gnu.tar.gz": "1fb3fc33289ae716f950feca832196bb32cde0556e41e501d05c84116836d916", + "dist/2022-12-27/cargo-beta-i686-unknown-linux-gnu.tar.xz": "4f112ea5a91abbf63db484368090fdf8fbc6b7abc1a5d7c8353df15e7908c2e3", + "dist/2022-12-27/cargo-beta-mips-unknown-linux-gnu.tar.gz": "b90f3c17c73f4dd7b36e0ff56b17be8e1c90f82b33c9be28b7b813fc5c788e05", + "dist/2022-12-27/cargo-beta-mips-unknown-linux-gnu.tar.xz": "8754bb3f116b09a8b38ac0684014532a19ccb57e4e94d1097a8484e8d67e31ce", + "dist/2022-12-27/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "549733dbbc3ec23976d6975e78ec8b8a30396eb45e4a8f5eef6d4c846cf04da1", + "dist/2022-12-27/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "f5997ebe7c67969b7d14a2233897b6014ebd9b38010eee101d9e484d42b220c9", + "dist/2022-12-27/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "3450c71c082bf84115fb035239453e39230afa0575dca0fc52586222b474a0c2", + "dist/2022-12-27/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "a16c397c5e980a926e0122cff5f8d30c4b54c2dba7f48ef00b587c5cda8f500d", + "dist/2022-12-27/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "62e025463eca2dac0547275c7827e6ecd109d1b84d056526e647abd220b3e1fc", + "dist/2022-12-27/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "99c5f5511b23d93707df394c2ab90ddd98e7876c9ee74c861dc919cdd498399b", + "dist/2022-12-27/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "eee574420f365d02d52f5f4754563bc1fe4f0b07d02a554f6aa886bccbe4c092", + "dist/2022-12-27/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "64e53a591e2d4dee9935fca4a2df18fbbed1b00b74dd6631473ba2d5b257891b", + "dist/2022-12-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "37d2a5f1c496c8ad8d2b5af5e89a4a325ddcef32ebd7087ef3cc9e653e5a8f4a", + "dist/2022-12-27/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "8753d9bfdda6decdcc4f58d2391956609e0aeb75ce4368c7ed52c23ed3f28943", + "dist/2022-12-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "303c63a294f2112fceb70cee063f35cbee3296b93ca91e43300e72b064d80da7", + "dist/2022-12-27/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "96b752dd307d2709dbf2b91c687a55992f4e0e5a143223a8c2a267883b4a2832", + "dist/2022-12-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "e5c279922e9adb47e6ecaee191ad291bfc627aa05e4c026628664bc47e5ce254", + "dist/2022-12-27/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "7e0145fe22bfca7070dcace196e3229a86f9f5b31ab1cfc4fd7ff158db5b1388", + "dist/2022-12-27/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "49df0b5774471ced53703942c6551c045ed56c92a3a224615f583511bc845a61", + "dist/2022-12-27/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "955e67ac19fc7a2a882f759339343c466da9658b2cd95799dd78328c13d6527e", + "dist/2022-12-27/cargo-beta-x86_64-apple-darwin.tar.gz": "a0e01a9ded551ea1f411da70d4481627579e870c2ff7592efde1d8be83ca46d5", + "dist/2022-12-27/cargo-beta-x86_64-apple-darwin.tar.xz": "a9205d81dff07cbf2468fa6f6999fd0f1266ad4faf84f5688e3e5cb330bdce0f", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "d6406b59361cdc97df606901beeafe6660a4cf557b9de4a313d4659c83f10255", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "ae15fd38cfcd149de306280a48785fe269ea36b1a958de6815adc7a80792d798", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "d75a793188af608b8bbd92907ff69294bc66b85b7ffe03882abcb661fd8c27f9", + "dist/2022-12-27/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "26f4ed51fc227dccc67d4c68fcac78374fb1441093d3524ec157b1b6b6e90012", + "dist/2022-12-27/cargo-beta-x86_64-unknown-freebsd.tar.gz": "6503b65a5258b5517c5213f0fb858aeff7e00c453a3633749d1a72f7f645050b", + "dist/2022-12-27/cargo-beta-x86_64-unknown-freebsd.tar.xz": "75ba61fe1670d0e4cf9f9f35460c663701c75ceca95917ed25e98f20cc2f0ef5", + "dist/2022-12-27/cargo-beta-x86_64-unknown-illumos.tar.gz": "e003c3a1ed8b57546e6ecdcbbcb58a97896a8e511b6a8fdc31100c24b8dd5a17", + "dist/2022-12-27/cargo-beta-x86_64-unknown-illumos.tar.xz": "b377d76b8fae7ebc607f33400cc0b37974fbf02a4d29187b1f0f6f668c12ff01", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "0dcfb9c65b5ad5c6af905c78d6914f5d7f8a62def817e64192b29c957b848783", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "1ca64be7777194c3191350723e8a909cce93d8ac28ceafb5df641f3066c6a8b9", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "9c24ff865929e88db27285fcb4a10adf97289a388f93ff5fa421211f35267047", + "dist/2022-12-27/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "b794e0397ca0ec274e307468ed56b8116438c0b8a444f593eb56350d687e8137", + "dist/2022-12-27/cargo-beta-x86_64-unknown-netbsd.tar.gz": "0fc5f8716933c46509cc05492e5bf75f6d06575dd6f803882397929b95394e12", + "dist/2022-12-27/cargo-beta-x86_64-unknown-netbsd.tar.xz": "0cfe7415cb4c0a96019eefe0363c1d61934d76f3b5fb72a113b9de1401ecfad9", + "dist/2022-12-27/rust-std-beta-aarch64-apple-darwin.tar.gz": "777b016bebe68ea79bfb336eedb595174466bfd54321523b9913f5c2741d0135", + "dist/2022-12-27/rust-std-beta-aarch64-apple-darwin.tar.xz": "c4ab94494052bf3fb37a226e1313886546bde1ec4d7188049cb95dbf2963e1fa", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "884004f47fea38414ed805abda4afce3adf5a83fcd072ddececfa888e55bdef4", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "db0858bd63fa8609ceb6ee42cbddc31f31b2a0ce0c02e1fe1c2d32f0c8d607c6", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios.tar.gz": "996c8612a39bddb3047ce0f23f761deeca61d15b36f2ea270f5a220d14c1ed27", + "dist/2022-12-27/rust-std-beta-aarch64-apple-ios.tar.xz": "c06360094800d069261d363b709ca552d3899d50c12d39c23eb58d75015c980a", + "dist/2022-12-27/rust-std-beta-aarch64-fuchsia.tar.gz": "891f1909fcc78019f77d704c3b3b1031c605dee01a116f04e7f4f402d6b9b2af", + "dist/2022-12-27/rust-std-beta-aarch64-fuchsia.tar.xz": "3033d409735b299b6754852c28c1dac378a94ad892144ed76199d542a265c8a7", + "dist/2022-12-27/rust-std-beta-aarch64-linux-android.tar.gz": "080c97ad158327dfdd24a3c17477614de1dfe27f1236c73ed43b1e7e881f6b06", + "dist/2022-12-27/rust-std-beta-aarch64-linux-android.tar.xz": "80b89416148f4ed917978686ba337ebdbb3d4a50903a792831fa3b83032c43cb", + "dist/2022-12-27/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "854badcf35650c196b2051be46254d2f4e86b4522dbfa9f1d1a64148cae7bf1e", + "dist/2022-12-27/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "e4ccf358da4cb13b281c999318816fc99948a3531e9ecd6d0abad9b819c117be", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "9473f12fc35106ab9144b38bddc3c35d56b0413bec06c2d1d5f43d4fde614331", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "5cb44be7d8adc0589afca90ef0669c42f03a61a622d856fb057d450554d24c01", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "25ebf045fc59488abc07ed24aa3364fb64cc186f6c852b12cb5c094f81d5fd69", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "d43bca65f55159d6eafb7e342ec5d4598d63bc8fad0c9fc15b6bd88743321d4e", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "91198741990d9300024da5113843cbeff02ed9ea344d9feb57736e9334136d27", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "0aee6204d34246480be1d0f6efd6a66eb10d83a9dd1c215433e840949687c598", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none.tar.gz": "97f3193bfde82b997346b49231a0f24a6960da88773bf27c73f57f40ec4f84e6", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-none.tar.xz": "1d2122442cc0a6595c901831e8cbaaeafd2043fbc8c4b028265310d2086673cb", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-uefi.tar.gz": "6d351f35cb9252c2825311eb22049283534cc2877cfd673fc1b5b3c94c6ef864", + "dist/2022-12-27/rust-std-beta-aarch64-unknown-uefi.tar.xz": "054bb5a98df25830201ab04e81f63630dc329f48daa0d715a3443f95d2c0f442", + "dist/2022-12-27/rust-std-beta-arm-linux-androideabi.tar.gz": "93b70e7c6b686ed5695bcf2f0b2da14e89a50e54304d445ebfc35107f689c442", + "dist/2022-12-27/rust-std-beta-arm-linux-androideabi.tar.xz": "9b8983be6089216428007e968844f57bd88e2371dd592b1ca06aed2aa6479d8c", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "753ef462dd47349fee5f45adadc073363250fbcbf566ff337250466d0ce73343", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "c19389db997fd0e158e5a5e847f566f6b03f06b3161ce5644ca0178fae25d0f5", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "c819d6a3de743f54e28eab0f2c7744dd5a5be7c6677bb712bfd3f93938435194", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "4ca09f9df5476449c3510c82e284026329411253e2a02c90e6239f30a9a6074a", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "f7994d565baee0fbdb010211fcd30398f7f90bd97770ce72e5ba34bf1f06a466", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "f54e1efdb9a088a13371e5fd7e1599a7bcadc5db4247e8811ab9d374c17fac8a", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "add3333e892ccfc31b8fa506e79d5633261daf13e7902549ac5ecfe8f3655bbd", + "dist/2022-12-27/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "bfa9a7cb0de16ecef093d593677e32164e4e68042806f543824c16f2a12b55ae", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabi.tar.gz": "81c958b4ba5933c02cb2872efc4d5de86a2bc1a1d326bf563256ec74e256fd8f", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabi.tar.xz": "634d2e35b2314826198eb2a7fd6f253cac5c2bbe7a5a7c7cdecc09949db23b3a", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabihf.tar.gz": "62dd020647cfa88c6719b4b9a803d07f3ccae7c2f94c924e1529def264db1be8", + "dist/2022-12-27/rust-std-beta-armebv7r-none-eabihf.tar.xz": "53a03694b610146cb80e0ef0033600ea4dd6f8b7d413c3ac675cb57c9b4c5cde", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "ac7c396d35406501eda50191b92abab74e19148ec6caa2d5171bba35f2d3ec96", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "058c514636a2063193d278e16fc683dbe9c1dadcbca45707152d150dba71065a", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "bc5400e734bc4747b3ea44bb5c3cf9af5f11d5b5f2e970bd4626a25a276f15f7", + "dist/2022-12-27/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "0079d1cb3d1fd5be99bed480e6ec0b451dd9e2a2299e3347cbee33344cd8c718", + "dist/2022-12-27/rust-std-beta-armv7-linux-androideabi.tar.gz": "9dbc9e97f9990f03efe67c817c9dda7fcdc931c7605742182f4d128859c1a53f", + "dist/2022-12-27/rust-std-beta-armv7-linux-androideabi.tar.xz": "d0119bed6cb41629aa65d83f7c1021e05e2f90bd21a28e6f0d3b6f0ea9127dd4", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "09cab74e4a6e38d07622fd80e97d424d7437d554c05ce1896acaaddad0e3b637", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "4602ca768e8ba85cfc5a4d4a2964cccd048ad82f349b7453f077e38de918cb0d", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b983a7699fce4c6f9c7f16ea3fd2905a8ddf21623bae71a9e7515b5cd5b288ec", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "ca2d6d4c09326559a1528cf32c7a899f985c7e3b7751cec8911d0facac149e51", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "dfa375f608f297f4dd0fc39921609ecebb31101850d73a8bb8b67ce98e319f3d", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "3159afaebb2b17f6b12128e2829944f9406e26cc7019eb33839fda311ea0b809", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "5a2c2361c944d85455b7a037bc820fbfe824180106f5a6d6fbf4066ef78236a3", + "dist/2022-12-27/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "0bd7ac1cada0a3a3894d404ad5871ef3abc4963eeb5a1f05f59e6264b1e6cc3c", + "dist/2022-12-27/rust-std-beta-armv7a-none-eabi.tar.gz": "1f9daa0af4695c51e4cda38235497923b9adfefd1a6eb4be086d720cffab7594", + "dist/2022-12-27/rust-std-beta-armv7a-none-eabi.tar.xz": "b9e5b75720d71bc9e0e16b73b7cf04cd3e5a57da7a6b842926ffcf273308543b", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabi.tar.gz": "4837b13f144f12e9edb5b49ddf5169d1cd13cff0a3ec3e54160714d45138448e", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabi.tar.xz": "32a56e92757a9ee82ff71962c7c8144e4240133d44de77d5955510640a31061b", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabihf.tar.gz": "d31ed0250a195a8043e71c8ae3b2e86111ec07b00892ae05c3783761b20774ee", + "dist/2022-12-27/rust-std-beta-armv7r-none-eabihf.tar.xz": "06b70c26d9161b17c2e4ca9255ae1a73f7bbeadb24d733c320875e3dbbc77caf", + "dist/2022-12-27/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "6271afcf4b05fb4de2ed08ba441b3ee0b476e2e33dbda8a5efa3d7540475bca5", + "dist/2022-12-27/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "131c51bb571df676dbafd84d5015888c4bc15130bd7300d4c53c1667907f7f51", + "dist/2022-12-27/rust-std-beta-i586-pc-windows-msvc.tar.gz": "d6bca2e8ba737a4704dc01dd6fca58a7c8dc8a065107f9fa98588c5fbdfe39a3", + "dist/2022-12-27/rust-std-beta-i586-pc-windows-msvc.tar.xz": "d64aa029d4209256e18d7bed6e0e28156a965b1d50cb3eb8d70abab57be55a97", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "f48248f5fedc961ea4050254cf9bdbbe70420ebdaf712847a5374a3c97e21df3", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "c9287bc9be332f084a2779803964ae374930d3bec787155ac3c8d1d6be6a587d", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-musl.tar.gz": "1914ba0edb77b0bc7cd83dd93d8a6ca53b29800844cdec9a976342982aad8b27", + "dist/2022-12-27/rust-std-beta-i586-unknown-linux-musl.tar.xz": "30d5d1bf54eb6758e0bd3a3f48f186a957fdb1310ba8b3625b5f33994c8a58fb", + "dist/2022-12-27/rust-std-beta-i686-linux-android.tar.gz": "6c05a59ff653bcde6a71dfcbd38718ca3cfeb89b7ec09d1cd380fdb589941d27", + "dist/2022-12-27/rust-std-beta-i686-linux-android.tar.xz": "80b6b57ff73a9483046380c0d4cfc8c090fca5fc4174d5c47f71fffccb7178a6", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-gnu.tar.gz": "941bb6f5107630a0b26b8749be29c6df920ccb467df367a5f55491b062352f4a", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-gnu.tar.xz": "f3f2ece3bb0080980e099c176a8a1366171741450fa8b8e515362572b519e19f", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-msvc.tar.gz": "a94fcee79bd5941e718a112d855163563f6e5377b59a9c1405ac8804131b0383", + "dist/2022-12-27/rust-std-beta-i686-pc-windows-msvc.tar.xz": "4bea862e2d998e976526cb741b7d674a7d620fc7e4838955ef4c53d000cf24aa", + "dist/2022-12-27/rust-std-beta-i686-unknown-freebsd.tar.gz": "e5cc60f1c00d966809cd76fd452bbb03452c5cc94a487ef4ad14af12608ae5fa", + "dist/2022-12-27/rust-std-beta-i686-unknown-freebsd.tar.xz": "df8df7d1750cf9e92b3e4b57b83b195c1eea6ca62f38ad317882a69e2e813ba9", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "4ff8fc04b63f7a80587d4f75376c74ade7721369ad1508faf5c0f83930e1cf7a", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "4716141a8be8017adb8540c05f88e6463b2add95439320b0084ffb290bc0d943", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-musl.tar.gz": "d7cff128c80db94aaaa2bb708bafa3f857fe8b819ff21a85f7c6c7c5170576be", + "dist/2022-12-27/rust-std-beta-i686-unknown-linux-musl.tar.xz": "bc83b17627e87ee4b555e9cc5912dbfbba74586f46719994be6832e22f70424b", + "dist/2022-12-27/rust-std-beta-i686-unknown-uefi.tar.gz": "ec6723c138565c4d9ca87bcda199aceb7b3a42ddf979658cf9e8433a4dae9c70", + "dist/2022-12-27/rust-std-beta-i686-unknown-uefi.tar.xz": "0e67f10a29f2826399604839a4dcbd173f8de39a755283a0c245c54b8a658210", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "a78f899f6fae1671e41aa7d76b37d9041cc32dfa6e9315dabff3afe21f93700b", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "4c74cece45b9271c77c4b328d1b3d876b50429077074580d771fc2b03f0d4738", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-musl.tar.gz": "a854fbab503a0541d593cf9496a4e4cf8b9edb49422406b3a7f34e3fa21905f6", + "dist/2022-12-27/rust-std-beta-mips-unknown-linux-musl.tar.xz": "f42a81564e7366d5d630632af3113b99c5de6d147d7eb9e31da762bb9d35d4ea", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "de070d1ae3fb8a825092a9a78c26db553839c6d862e451a497d5f94230414bc5", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "0a7092c99c587ef69801af713ef834bae809e4868dfcff43babd44bec532717e", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "7077c20142082b0e2b8d6299ffcd8739c8295d315b917563cffe6d42e129cd08", + "dist/2022-12-27/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "86f0988f3baf0b5bbed81483e7d68004651f227ab22d1d36b34c73f132191dfb", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "536fe3059a8095bcc1c44391c27b7d9832d6a057388b4de089915810cbe1baae", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "6b4e397a3a175f4cbbddabb750df14d668c1f4c8520577d35fbcb9dfa8613097", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "30f42499ab4f21caf21551e0e92bb5db9a2e0f42fd0b3e59ee9789dd40d10391", + "dist/2022-12-27/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "1190cfa1023a8d35d202979a1070863bb713495c2c9b720d0371b6d70d23bd7c", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "4ac79a395ba5d70e1a09d0e1ce232b9405b9995f7c459d176be52eade40bbab7", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "42f3666885680cbb2d15ec85cfbc9103e5b170346a9b8cff63a2d15f78472c67", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "0b1c979205f8476ad6f0e35c05acb1976cb4c44006c25931e73c35025939f1ff", + "dist/2022-12-27/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "7b6c76ae46ca56746b0bdea404125256636f05c1354e5dcf32c2a487d25e0ee1", + "dist/2022-12-27/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ad9cb2ec325e2a2f14ac4db6a5df53a7c06adfe8c4c58f0f2c83748a34d0c550", + "dist/2022-12-27/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "1d507bb0cd8c80ee4e9155a0740c2319027ee5280552c1056ee7921a82bb9aa7", + "dist/2022-12-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "e8d3b7bb483d7b3b737840ddf7a27a28c216d9d0b3ffc7ccded547f76bc932c5", + "dist/2022-12-27/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "130edffa27b82def2876fb5562fc7a3971d33855e3ce023e18507b3e1bd47d10", + "dist/2022-12-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "b5659dcc18fb0e5849acb13df7153518c8df5ca9566852cabaeee33583321d1f", + "dist/2022-12-27/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "6bdfae3e9cf07608c862f4c042c47ed318c388bfcfb4cabfa233580b90c7a459", + "dist/2022-12-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "f28795f8c2823bd817df63486d8a11b6b7cfb9538110e87d8d008ed979a81a3c", + "dist/2022-12-27/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "695f6acb6ddb4c4a87515646157b88d2f58e2114b100f22bedcd4e2fa8de00b8", + "dist/2022-12-27/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "5f004e4b265efae872e8b0d8fda81f4e65cc50452d558ef90b9bef7639f6ba6d", + "dist/2022-12-27/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "c93c1cb534e83d43c40c62ed6623559e3e380f177c4bd151a0d1389a80a58139", + "dist/2022-12-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "79988bb7bfa27dcacae0c459143be6a34f328ec6bcb73c2267d41a6f022fc045", + "dist/2022-12-27/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "11235a96e7e8e14a173db0be71cd1ce7955c79f5a7d20b7436238256a06342fd", + "dist/2022-12-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "a315accc791f1247e92a6362eb7bd6ab899c4688db7decb36b8d892c200186b1", + "dist/2022-12-27/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "a4f6ac1d21ecda00c9d3e34d900771a4c5a50e3e5071d2eba837c9e4738edc80", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "06dd8941f63c3031fa0383dd34981c655b26fd10d5510cd06bdcabb4a592a435", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "882e464b44acb7e286f49d45a4f5a41fbf570ee0d78f1915fd6f94ac392fa928", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "734d6f54d143ddddc2141da72ee02a32d4d505e20eaf0041c86c89f8ad8730ea", + "dist/2022-12-27/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "be32ca1ddb2d48877c70c9a128dba02bfdca7a00e93c114c3c99127e7be04adf", + "dist/2022-12-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "a6c70d3715b7e50ff15f5473348d8e1c5a061036055a85784b5e84a99e4008ee", + "dist/2022-12-27/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "0dbbf637d310f7ef44cb1bc08122c172606c8ff1c886195eebbd52cad5789597", + "dist/2022-12-27/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "3e2f7751028f9123d94ff72b08f8ce0b40da36eada77e1414d4178756b46313a", + "dist/2022-12-27/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "382a35c79a03f7abebb9c5788f9dd19bd0973cb89e9b07a971eaafc611c3645a", + "dist/2022-12-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "3eb49f766b206966433eecc7cdbbf709e75991644eae6f44596e5ec893fb3e8b", + "dist/2022-12-27/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "9162e50f2ddb12fefecdc7c4c2d60e76874e78fd89b45d7fd81a6c95a856ee28", + "dist/2022-12-27/rust-std-beta-sparcv9-sun-solaris.tar.gz": "dbf20b8fd52e1b6a553369a1690344574e6c660996ddd5121d4a05bfb71c87aa", + "dist/2022-12-27/rust-std-beta-sparcv9-sun-solaris.tar.xz": "a40d8d444e57eabeecf8acf0b59f24b5d4e2c97ee538bfe38904a1f81a48fb14", + "dist/2022-12-27/rust-std-beta-thumbv6m-none-eabi.tar.gz": "1e63244aa865e6a115e603f238b64410606453fb38802b1684fa6397660a1501", + "dist/2022-12-27/rust-std-beta-thumbv6m-none-eabi.tar.xz": "ecd94de3f4a3aff8f9f920ff68383e342dc293ad2fb2584c9d9e48bf60eb82d5", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabi.tar.gz": "ad21ab2584999c7c528dcde2e435d0ee73686b9b94c4f31dfeb3abf3cf9b9821", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabi.tar.xz": "9394854e14bc3e671060630c01b6977ab5afcf9022790986c492fe58f0509191", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "1cbabb457c0546da725a548a88b3268bb0feca4269af2b9cd0b98455c2e0c468", + "dist/2022-12-27/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "1bb23d8d2783554e2043ed71cf982d9750bafa3ccac6e387b25d279137042867", + "dist/2022-12-27/rust-std-beta-thumbv7m-none-eabi.tar.gz": "076a918e524cc33a02ab2c94e3a607dd293d5d6d63e0797b16f2246057d1082c", + "dist/2022-12-27/rust-std-beta-thumbv7m-none-eabi.tar.xz": "de8f3e8907fde91bfcbff0c353eb3d1cb9d06dec31142479ef1ad2c6c368d5c6", + "dist/2022-12-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "658d66031594324821649058e16e3e0b06542e8c9dd17c5fe705c487b5915ffe", + "dist/2022-12-27/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "56a9a0235c0aacf561cfc9e7981c57a4d174dbedf5ed943d266302662246b10e", + "dist/2022-12-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "3318c23ea42624e26cf2a25dd5fae206ccb96137d6833f28d7bfebe3ba7e327c", + "dist/2022-12-27/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "b91396e82a9c30711608c3650d637a3ad56ea90d682460c791210f8bfb5a6854", + "dist/2022-12-27/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "55b45e9863e197262bd97a9bcb80991c9c34385acaa228b062546b690621b530", + "dist/2022-12-27/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "dc0b7ed56a142475759164713bcdd7c64958c7e7febcafa5371414082ae495b2", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "b2bed92d03b295035e4bc4e0fd63b44ee1cc634edb394cfbd7afdc00353a73e9", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "bcce53fd7c0c494ea1c45227190a959e992f07851dd064b2a9c599fafb07077c", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "d6df9026c218b906671e89e433b165552a9486e41399a8f01a12d10495afc8dc", + "dist/2022-12-27/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "f5f2411e3ff94f6e524a14ee46e6e6bc2e9ec91e395b0382f7a40bc6e970d623", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "c766ec36907ce0a7e76ba9a227fdd57eae7a744bc5679b67a6ce1d6ab41ea19f", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "de5f398bc34fb22489e9f6f2a9847954d8231ff5732f2595e8be93eaf7849986", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-unknown.tar.gz": "e3ed4bc39da4731443b3bbd584106444aceaf91720546ac66e98712fe65dfa93", + "dist/2022-12-27/rust-std-beta-wasm32-unknown-unknown.tar.xz": "704a65e4f3e1afea9d1bd6a60c4d3e5fd57e3e14ba0dd2e2b94305c3e1c92cb8", + "dist/2022-12-27/rust-std-beta-wasm32-wasi.tar.gz": "03e2ca41c758fb4f9a2ea562ac4ed7186e27607458bdd7b575d786368336ea11", + "dist/2022-12-27/rust-std-beta-wasm32-wasi.tar.xz": "1ebc2ac44181d6d26928cbd550c64c5b496008e97356c68497f15f8cc8351f37", + "dist/2022-12-27/rust-std-beta-x86_64-apple-darwin.tar.gz": "0f0520f7163ef3d659e5761b2f0c7a9f2de00b2f769eeec8d1e7e9b3b08daf6d", + "dist/2022-12-27/rust-std-beta-x86_64-apple-darwin.tar.xz": "25795f1876330666b7fd6dd724661b364643448d0688d479f492c02faf2f7a4a", + "dist/2022-12-27/rust-std-beta-x86_64-apple-ios.tar.gz": "014a022bbb524d8c550d5dc7d678b9764adcc9962538980e9596ebced9c5614d", + "dist/2022-12-27/rust-std-beta-x86_64-apple-ios.tar.xz": "9b38e214e203c959eba0e8d651410f6cafc9e4b5725228c2bb4ac8f562e6cfa7", + "dist/2022-12-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "afd9236304892945334183b31072b9b9f9b4faef8b7cdc4ad1f45a9b3e080a58", + "dist/2022-12-27/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "33a7e5fd18f2166fb2b6cbe7630d80915533d59afc0080f1370bcfad1114eaa1", + "dist/2022-12-27/rust-std-beta-x86_64-fuchsia.tar.gz": "7e91e1298da3676c4c051d7f34eec21f2fffa0a34af212c785b79c2d1048fe92", + "dist/2022-12-27/rust-std-beta-x86_64-fuchsia.tar.xz": "fff70ed752d0760990f7a90bc3c50ac6586e8b012e61a15b6dfb325dd081b9a9", + "dist/2022-12-27/rust-std-beta-x86_64-linux-android.tar.gz": "f9183794392422fbe8cfd61ea7bae0dadd8731e82b1d15a59f4e93acccd2048f", + "dist/2022-12-27/rust-std-beta-x86_64-linux-android.tar.xz": "4fce2ab0dacac153de7d9805786b17d517863b0ff04a8224540daee86eff4056", + "dist/2022-12-27/rust-std-beta-x86_64-pc-solaris.tar.gz": "d5b64111b3763063c38ae63915ca366a4fdb63f0dcf8121588a8953f01ebc669", + "dist/2022-12-27/rust-std-beta-x86_64-pc-solaris.tar.xz": "c396b086773dc06db2e59bcdaff8ffbb7069efee5841b9e3cdd4dfb05fd95ce4", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "e851812f69bcb2fe606bfbda125fa6b3f55752fd1a2330878c48ca99eedbb8b6", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "689738a0952a0eab27ba3d3f9bc9b531ec29f338ea373bfa783a83786d5c2885", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "b51f78199bfc1417f020e2d0dd16044f63f6b6675b2b6856f669f8604e44a6bf", + "dist/2022-12-27/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "7713269f3c51717f6231cf4100043eca2330512b602c2962da81af561e90193b", + "dist/2022-12-27/rust-std-beta-x86_64-sun-solaris.tar.gz": "9f0a129f4c2ea324e2dc94fad3f7acbc7bf2b988f66d9c42dd8abbc60c569acf", + "dist/2022-12-27/rust-std-beta-x86_64-sun-solaris.tar.xz": "6ca71851fd0a7879aa750a63deb4ee587f82c28b27486f716e4fae5ebe599086", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "6cfbf0f85757854fba1551c3312baac820e398b573d50b005cc3958723db7c82", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "2e2dfb82fa7e23f888ae9541a30d15ba978cb29bbdfec6afb00590a39c16df5d", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-illumos.tar.gz": "92650856a7e74c8b912d5c84cd1002a490f9c8e3fa4506733fcbedb3cd42792b", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-illumos.tar.xz": "3dd302996bd3fb9f8b077e6d5fe3dc6f7dd9590d5fc3eb3bab2cffaada4e99d3", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "3a1faf905ffc7263e725ce7571cb84dd8698adbc45b6902da86350299b2e3ccb", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "daef635cdf88c8d9c924c0d66e2b26db1f56bda9b48ca0c21e089060b07dc997", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "567bb99f67737cca721d1dc6975daefd3dad29b13d531d3b939405ef4e7aee84", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "aa218c4547e77f33ba4bc45bba0b6fcf3cce9355c2cf11d74a3a4c5e49f9b3cd", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "de43b04cccb3c2bdcd2a7993c391299a4bde5041102ce0eb5e32b6cfae86cd79", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "f99963704b4c3189361925ec8b53daa2ca15ae4af9215cbd87cfec23e044cefa", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "3d4949e63f137552e3b74e50b366f95d7a153e7c61cf5587634be51516fdc610", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "5b48095a35f862190536e64eff726327e25c23981c0bc1224c8c44bfccbb705d", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-none.tar.gz": "12b5c69138260daf976e963ba503c66ec4432f11cf7506bc9ba691ac2c1df4a1", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-none.tar.xz": "5c334a67f6586dc406b6e55c7f9d64b7701e1c7879bf5860b378069301c57854", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-redox.tar.gz": "58c15f9119e5f78d7c70b24e67af57ce10bb2d2cb1347b9b4631478665c624de", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-redox.tar.xz": "a2f8b635254d53ec5b902dbeb8ac63c6c3982f94dfbcaec3d093f17f0f5fa896", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-uefi.tar.gz": "1ce5c25480e97699b12c180ed6198766a0c12a3543dd317ba6f4a52538027b0d", + "dist/2022-12-27/rust-std-beta-x86_64-unknown-uefi.tar.xz": "e4d9ffe34ba40e5ccf87007085dc4daa20a8a52944f092e2a075527702b55072", + "dist/2022-12-27/rustc-beta-aarch64-apple-darwin.tar.gz": "f5c8dadb8eb0335a50326a94f858625e4f01e3159e933d58f9d24338d47943be", + "dist/2022-12-27/rustc-beta-aarch64-apple-darwin.tar.xz": "0a6eeb32e4d85b628044c3e075e5f1414a42bb582905b199d360addae466d3ae", + "dist/2022-12-27/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "0f7ce917f14a1d42637fbbbc343473596becceb22634cb7c7cdee6beaa2b9ca1", + "dist/2022-12-27/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "49667bd902fb5fb2855e843ca5c1dcd453171f164a3dee2dcd9e09b0d9e1e57e", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "d5a03695685afff4debff8e09f2d91db02d2ac29981a9ec230619c3e388ce1c9", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "db1aeb772a08f111d8f024164b570322f45ecab0f6db4e931b91971b2b982323", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "0e51f97b677b5c813862bba3e5a3b0884f0ecdf9b7c3676089625431a3d0cb2c", + "dist/2022-12-27/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "f88c6c33ac3682f340ed60b4f62ee8ed61eb21069a1f0a912024d19e41c0d5c7", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "25abe3158ec3ab7c064341247d78ea265ad7e0dc2063837fb5cf0a3bea9d011e", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "1d430b8e35ebd63a79b34917edacebb76b2fa8f1cea4772ba2c4ef0340485fb3", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "1858d5ed21a3132af4b56c841cbabc9fb834d501946956a0e9aeeddfa095344f", + "dist/2022-12-27/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "17cc52dbd6ccbed4677ad52fa666ea10295c11209528e78ac190f01b5d509f87", + "dist/2022-12-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "3440edd99025f24f2640528d2d1c10047c834b93cb09a935c65ecfb72012e7d0", + "dist/2022-12-27/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7e1ff0a950db0ecbadef3a9ee55a593891f11a42c6c0ff59637074c8b5c4da74", + "dist/2022-12-27/rustc-beta-i686-pc-windows-gnu.tar.gz": "90487ff490c4e71ae62e28492cf49600f8f92e0f35f5d76a50eafcf4bbcf4bcb", + "dist/2022-12-27/rustc-beta-i686-pc-windows-gnu.tar.xz": "8b44fb934aba0eef296098bfc5a9f2994cdd595420ce10f4f310c5ee9d481071", + "dist/2022-12-27/rustc-beta-i686-pc-windows-msvc.tar.gz": "0fefda6b62234a43976ebf18d7cd62057cad5b494c750f2d9730f5df64cadb00", + "dist/2022-12-27/rustc-beta-i686-pc-windows-msvc.tar.xz": "c9eecbc06e7456bf5e383557a8e5720d00d09de640b8c46139121faadc354d74", + "dist/2022-12-27/rustc-beta-i686-unknown-linux-gnu.tar.gz": "8b17d032192aa17e52a3f08a074079561ad7ad6c439f9274aef228af93adacc3", + "dist/2022-12-27/rustc-beta-i686-unknown-linux-gnu.tar.xz": "c70638cad594097450a469837411b110e979c303727341623427e3c9e4e4f507", + "dist/2022-12-27/rustc-beta-mips-unknown-linux-gnu.tar.gz": "3669ff9024092ab467a1b95aec2cb1692810ee716739f31e3aee7d89e6bd6d7f", + "dist/2022-12-27/rustc-beta-mips-unknown-linux-gnu.tar.xz": "165859e42492e33bff634c80b6c96b13fd2252981b4be2821b96a6593933e22a", + "dist/2022-12-27/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "2ac418c0cdeb2382aea7296169d747f65349d7e6d5aebbdde7b377e985de354e", + "dist/2022-12-27/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "21ae51357508398527b6edd2e5fbb1745fda1c8db2683c40847216c0ce251d47", + "dist/2022-12-27/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "3eb68935676424aa8c68bc32b06c010c5c1302fa6f77e9b33e5543565562d176", + "dist/2022-12-27/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "0eeb58035b510a166b8506168f67850993e278888986773c779bee24d7a6ec11", + "dist/2022-12-27/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "f41d878b2e49beb9ee3a1bb8863ce1b81fae7100a786a78d9922bf8a4fd0dfc8", + "dist/2022-12-27/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "e0cd18973c7651cd2e1e041f92900375a045bef62754d432df539000aa5946c4", + "dist/2022-12-27/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "7206be82ba39971c6a734f4a89f7f750d581768d82253e31cd985fecd1d17c3e", + "dist/2022-12-27/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "f9ec2a3e98a3b94b170237386256c763d62925b430d0e12a289982c7c79d2bfc", + "dist/2022-12-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "32be7fe5f359cb2312c9bd966eb43b143b336b4acbdf118bf09221574f157b16", + "dist/2022-12-27/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "a8163a5b527b1ee932e06589d690c17d8848dbfa8504de6984a718579698abb2", + "dist/2022-12-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "3e875cb943dd0ffff907f6a582a64f923cb84a07ddd8b5e6f1ec2e1d4228342f", + "dist/2022-12-27/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "22537364de01be77a2a5d79486b1090dbee7b3273fc634073031f82576a61a14", + "dist/2022-12-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "230041ec7d0d4debc841abafe2f3314de51793d281a1077835d9190286a558f7", + "dist/2022-12-27/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "2dafdb1a97469737123149608476c248a77ccebeb22834b6a2166fc30551a7ce", + "dist/2022-12-27/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "0bd96121550321138dad9f74f331eaefd77ab388843e5561c5c0cb32e9d80072", + "dist/2022-12-27/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "ecb02c8535c1518e589eefb10be17830010c40be61f3184576abe93e098d793d", + "dist/2022-12-27/rustc-beta-x86_64-apple-darwin.tar.gz": "600b83ea5c832dc6ad9746d74b7dbc8ea566adb9208c4260b183ef05078d2bff", + "dist/2022-12-27/rustc-beta-x86_64-apple-darwin.tar.xz": "175930f3062b433fc0a2b959917933bf3347d3f3e0900684785493d0ee9dc6f3", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "d1701678ee1d2f2e91f3c1f898f852593ec1b109e430c53c13bc2898b08bca3f", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "3400e923af537d28139b9d5d780caa039828e06677cbf499322614006552778c", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "d462ca50803b13e136fbfd49ac4a6e186e416041f3cdaa8b4fe72e628cc10555", + "dist/2022-12-27/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "81ca0992ec8306ff67b00f5f85f31c6617f78b7350116dd56df082c477c9069d", + "dist/2022-12-27/rustc-beta-x86_64-unknown-freebsd.tar.gz": "65fe64154264ab76bb94aa7f107efa9b58cb801c9aaabcc7e6ffa0ce14319ef9", + "dist/2022-12-27/rustc-beta-x86_64-unknown-freebsd.tar.xz": "cd6e9bfb6e8c08a46dce7bc623cfdc5a04e55c8377eaa3a75fae0bfe8e00b43e", + "dist/2022-12-27/rustc-beta-x86_64-unknown-illumos.tar.gz": "a66bb4b0d9dd9a21b54857c4fa7eb48a88789f0414fec4a1e36c798546c4b71f", + "dist/2022-12-27/rustc-beta-x86_64-unknown-illumos.tar.xz": "b63e6299e961b75d9c9bcb46e1dbc22b8fec89292ee6c8758edd43f4b89cb12e", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "c768beca1350bdcbcc31c7d3f30c3ccec0ab2bea0c28bc4c89cdd32d9780cd00", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "62a675d74274ddb4d8a9146c20942cb91b86e0c94a902169c2cf77f4d471d645", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "8f2b81b37bc34291f3d90bb6aec621da0ac760c39727bfd24449c288cc8cb3c3", + "dist/2022-12-27/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "053c313c9a751bf0102448866fad2a80ca67b9f79afce82ce03805430e2e695b", + "dist/2022-12-27/rustc-beta-x86_64-unknown-netbsd.tar.gz": "a9f42eb0ffdc4bef87669d8fb5163e81a5d82ff6baf631f159b7bccafe9df453", + "dist/2022-12-27/rustc-beta-x86_64-unknown-netbsd.tar.xz": "d1ea529e56d57132de1782396a767f8f00f30e2b5f7c9a5fa96c3289b43e3515", + "dist/2022-12-27/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "411b96fddfbcc90b4522e3f4e2d6e174f3440960e89193c97fcd5ca8afd62809", + "dist/2022-12-27/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "29db6fb11b411dc8351a8a8d1b148e81d9c87f9fb234b3a18722ee470b4d36c0", + "dist/2022-12-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "32ab437117791eb7113ac522ee4119e2e43722528141302772adf9cda7306b24", + "dist/2022-12-27/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "4d892f3c65ef8e32670ab3c3e8fb39a2ae623c59d1ff555ec94644254e954474", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "8bff3a1591d25d3e1acb70600e6cd54d712772247376ac5eb90a4b2aafd21a6a", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "b81b094d128a37b178da1eda7c72399a9da4bd614e697c53e9c4d78589f859f5", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "b3a685d1abe4ac639a0a3ea187b83ec660cd838e7c5c010ed60f8620d17df906", + "dist/2022-12-27/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "10b7563202520708fd27cc221ee8db34b368563eb1586be1395955ebf4313d6e", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "34e5ca3d51b51ccd97ded5e0c31c999a84f9d5ca5ee3d010e15212a97ab40567", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "16638ba8478861276c10847b989fd23de942cb82a9d4da9d92858c6800a39a9e", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "13fa3bf29e9d20291703bf2c03bc97cd8e2081d1c747b6835eb0a06f94dd5d19", + "dist/2022-12-27/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "98dd01d90657e43ab3a2b91673137cd6ae4c171633db1f1e4b68b2e90bcb9bab", + "dist/2022-12-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "1370e4c8ad5bab425c02fc924d5ac079ac1387368a3ea5d22c1cdc2edc9c6ba0", + "dist/2022-12-27/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8c312da4ccd992c303fa3f181dc46f9b01022f72061ef43b2fd5848736547870", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "0d7a87816f50452349bd26cefdd9f53f2d93a53243290ac59bd5de414407aa1e", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "982fc6783ad07235d375c4c8964104fdc64a009ea359cca532cc268a8249e88c", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "a5b76840e49a912a819809a2b4c73a0e750422fad4876d11b409a8ed49a77911", + "dist/2022-12-27/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "9566b6417a0bdb4c73272d167cc743b297db62f625449343a6f1ab60c52d5327", + "dist/2022-12-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "bf6cb5e886ce02a3f9b4b00a3696da0ee277af8f690f5a31119c5fce5779cd4d", + "dist/2022-12-27/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "7afa5129bc43346614869721e7094f65eba6681bb9b8ca8a3559925f29433f10", + "dist/2022-12-27/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "f9805697506a0c730299492fe04c53433c8c4deb70ca245ff1c2cf5151fe306e", + "dist/2022-12-27/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "f5d7d5a841a7e7a5d749e52cdb118d2f2cec09de68835a42748db4b3a0a79979", + "dist/2022-12-27/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "dc903c64c969a3c21664263c2a30e9cb0dc42069a95f755545ce9648240a376e", + "dist/2022-12-27/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "de6591cc73244d99b3469d88439ad442f00037a1cdcaf5fdc5a694b52e47b2fb", + "dist/2022-12-27/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "f4e8dba56a1b90d5871bf8722a5ecd2027a4f101299880a8689f5cf46df2606a", + "dist/2022-12-27/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "496c19042848726db446cd3df4c52f3e8a5527002ca5492e2d6ef72528d6887a", + "dist/2022-12-27/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "58742a5c8230e8749b01058acea639d92d45090bcec6fb7eb1d8f356b0f08631", + "dist/2022-12-27/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "bbbdaa32d8d29c407133b0ef2851970da884032effeb85c271d57e58b7d38a44", + "dist/2022-12-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "1a8a59193dc15d331c3243a2cfaf5c81c023464becc4da63201583d2d2cdc27d", + "dist/2022-12-27/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "ee86ae7621804a7b57ccab06dc73b7d87453b53814d482ea43dc26dd01dae1c5", + "dist/2022-12-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "21a79a050e4461305e280ed7de7c0ade2774ad5230f671c76667be7bdbdc47af", + "dist/2022-12-27/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "033afa47c24a4887d40d62391f9f66b76dffdc1bd8f1ad622bfb14db91d7df03", + "dist/2022-12-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "01cea51850a7f676803f5f8f9a556a71bfb8e7a7e04cc5fc0e7d1b706473338b", + "dist/2022-12-27/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "720bf138fb2c541d8d8d0c60d6584cff692c932c6f383901f999e7b3d4078770", + "dist/2022-12-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "8c3f3fd601bc7d8670f6acfcda29206fd5590fb3a2a6cbb3794ba29cf749144d", + "dist/2022-12-27/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "8f1b43479a724197c7ac051c6a6d2a10bd87c6b24fed1d38c9e93f503c87e5b6", + "dist/2022-12-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "b38b6dc1e65cc0f5031d2045a90404f3b2ce2648884db1f658641e76168d0109", + "dist/2022-12-27/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "ed635e2388fcd3bbe94f497404b6787edd5e7471d6c6471345386a43444f46d1", + "dist/2022-12-27/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "457995f055ef35a2491326f95caf31376b21e3cc4c0316cf4536cb7604e472d3", + "dist/2022-12-27/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "d80b01e8c007da58250f7affea8d034a536437efd766eeb8de6d5b7feba9b0d5", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "ee2ab7683e75fa68ad482c81e546cd71b9209497f16a0590507e5de884f1e627", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "d08326f42bf7f38855e37c624a38923d09cbf162b666e8058891aff06ec017c8", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "e42ee4dfdd0aa342dd8192204fd6cfb503eaa0069f70776adbbca352d7e7b661", + "dist/2022-12-27/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "76ec230ae507729fb4ced016a45b0020775a9eef068c2b2e5ae6e3fcb451d32d", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "55f5c89950a81b00efc542c19b42cbfeb9c969af63280106fc78e8893df3d568", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "5a4cf3589d06e562ebed70bf0015af3e80f83de1c4d311c810ebf09feac640bf", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "fb44bc69be6c89c7245b914324e23284dbd9887ac0c1c4a65379344ce78cfb28", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "8d34915b54cd8ea6abf0bff01546f31f74342e1d21128b1e14c32cdfd3505afd", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "d15403f81b36c0a2829ad2dee5c1edf39a993a13ccc57f01bb45c77898e3b9ec", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "4c0c61f404ec6bb87ab044c0850d116c577a2ff3cfda9ac1598a7858b4fe1a7d", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "8bc1fe0e2496769f52a576ccd13f706b26f706f060bebb2618e2c64c3831e2d3", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "bcb527bb736bea88bbbb6974ba388b11fe20596c2c178314bbfdad5e2db65fcc", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "8bffdf816b12c53d5443e2523c0960a37ab67c93590b0bb753fd5a026e67d368", + "dist/2022-12-27/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "bb5c947ab6dfa28fa7c3d7050e9c14c02eaedf2a4e06d290bee554f569be2c30" } } diff --git a/src/test/codegen/comparison-operators-newtype.rs b/src/test/codegen/comparison-operators-newtype.rs new file mode 100644 index 00000000000..5cf6c3ac0a2 --- /dev/null +++ b/src/test/codegen/comparison-operators-newtype.rs @@ -0,0 +1,49 @@ +// The `derive(PartialOrd)` for a newtype doesn't override `lt`/`le`/`gt`/`ge`. +// This double-checks that the `Option<Ordering>` intermediate values used +// in the operators for such a type all optimize away. + +// compile-flags: -C opt-level=1 +// min-llvm-version: 15.0 + +#![crate_type = "lib"] + +use std::cmp::Ordering; + +#[derive(PartialOrd, PartialEq)] +pub struct Foo(u16); + +// CHECK-LABEL: @check_lt +// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]]) +#[no_mangle] +pub fn check_lt(a: Foo, b: Foo) -> bool { + // CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]] + // CHECK-NEXT: ret i1 %[[R]] + a < b +} + +// CHECK-LABEL: @check_le +// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]]) +#[no_mangle] +pub fn check_le(a: Foo, b: Foo) -> bool { + // CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]] + // CHECK-NEXT: ret i1 %[[R]] + a <= b +} + +// CHECK-LABEL: @check_gt +// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]]) +#[no_mangle] +pub fn check_gt(a: Foo, b: Foo) -> bool { + // CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]] + // CHECK-NEXT: ret i1 %[[R]] + a > b +} + +// CHECK-LABEL: @check_ge +// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]]) +#[no_mangle] +pub fn check_ge(a: Foo, b: Foo) -> bool { + // CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]] + // CHECK-NEXT: ret i1 %[[R]] + a >= b +} diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 44fee952307..0f9e90f6ba7 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -145,7 +145,7 @@ pub fn raw_struct(_: *const S) { // `Box` can get deallocated during execution of the function, so it should // not get `dereferenceable`. -// CHECK: noalias noundef nonnull align 4 {{i32\*|ptr}} @_box({{i32\*|ptr}} noalias noundef nonnull align 4 %x) +// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @_box({{i32\*|ptr}} noalias noundef nonnull align 4 %x) #[no_mangle] pub fn _box(x: Box<i32>) -> Box<i32> { x diff --git a/src/test/codegen/issue-103840.rs b/src/test/codegen/issue-103840.rs new file mode 100644 index 00000000000..f19d7031bb3 --- /dev/null +++ b/src/test/codegen/issue-103840.rs @@ -0,0 +1,9 @@ +// compile-flags: -O +#![crate_type = "lib"] + +pub fn foo(t: &mut Vec<usize>) { + // CHECK-NOT: __rust_dealloc + let mut taken = std::mem::take(t); + taken.pop(); + *t = taken; +} diff --git a/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs index ece2adbdf43..b9c33914360 100644 --- a/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/src/test/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -131,6 +131,13 @@ pub struct Type13<'a> { member3: &'a Type13<'a>, } +// Helper type to allow `Type14<Bar>` to be a unique ID +pub struct Bar; + +// repr(transparent) parameterized type +#[repr(transparent)] +pub struct Type14<T>(T); + pub fn foo0(_: ()) { } // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] pub fn foo1(_: c_void, _: ()) { } @@ -425,6 +432,12 @@ pub fn foo145(_: Type13, _: Type13) { } // CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]] pub fn foo146(_: Type13, _: Type13, _: Type13) { } // CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]] +pub fn foo147(_: Type14<Bar>) { } +// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]] +pub fn foo148(_: Type14<Bar>, _: Type14<Bar>) { } +// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]] +pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { } +// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]] // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvvE"} @@ -570,6 +583,9 @@ pub fn foo146(_: Type13, _: Type13, _: Type13) { } // CHECK: ![[TYPE141]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooE"} // CHECK: ![[TYPE142]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooS_E"} // CHECK: ![[TYPE143]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3FooS_S_E"} -// CHECK: ![[TYPE144]] = !{i64 0, !"_ZTSFvu3refIu3refIvEEE"} -// CHECK: ![[TYPE145]] = !{i64 0, !"_ZTSFvu3refIu3refIvEES0_E"} -// CHECK: ![[TYPE146]] = !{i64 0, !"_ZTSFvu3refIu3refIvEES0_S0_E"} +// CHECK: ![[TYPE144]] = !{i64 0, !"_ZTSFvu3refIvEE"} +// CHECK: ![[TYPE145]] = !{i64 0, !"_ZTSFvu3refIvES_E"} +// CHECK: ![[TYPE146]] = !{i64 0, !"_ZTSFvu3refIvES_S_E"} +// CHECK: ![[TYPE147]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarE +// CHECK: ![[TYPE148]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_E +// CHECK: ![[TYPE149]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3BarS_S_E diff --git a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs index 34fd401f9e4..ea5bae18e23 100644 --- a/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs +++ b/src/test/codegen/unwind-abis/c-unwind-abi-panic-abort.rs @@ -10,7 +10,7 @@ #[no_mangle] pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() { // Handle both legacy and v0 symbol mangling. - // CHECK: call void @{{.*core9panicking15panic_no_unwind}} + // CHECK: call void @{{.*core9panicking19panic_cannot_unwind}} may_unwind(); } diff --git a/src/test/codegen/unwind-and-panic-abort.rs b/src/test/codegen/unwind-and-panic-abort.rs index b370191bf8c..e43e73b96b9 100644 --- a/src/test/codegen/unwind-and-panic-abort.rs +++ b/src/test/codegen/unwind-and-panic-abort.rs @@ -10,7 +10,7 @@ extern "C-unwind" { // CHECK: Function Attrs:{{.*}}nounwind // CHECK-NEXT: define{{.*}}void @foo // Handle both legacy and v0 symbol mangling. -// CHECK: call void @{{.*core9panicking15panic_no_unwind}} +// CHECK: call void @{{.*core9panicking19panic_cannot_unwind}} #[no_mangle] pub unsafe extern "C" fn foo() { bar(); diff --git a/src/test/codegen/vec-shrink-panik.rs b/src/test/codegen/vec-shrink-panik.rs index 18409014bde..aa6589dc35b 100644 --- a/src/test/codegen/vec-shrink-panik.rs +++ b/src/test/codegen/vec-shrink-panik.rs @@ -18,11 +18,11 @@ pub fn shrink_to_fit(vec: &mut Vec<u32>) { pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> { // CHECK-NOT: panic - // Call to panic_no_unwind in case of double-panic is expected, + // Call to panic_cannot_unwind in case of double-panic is expected, // but other panics are not. // CHECK: cleanup - // CHECK-NEXT: ; call core::panicking::panic_no_unwind - // CHECK-NEXT: panic_no_unwind + // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind + // CHECK-NEXT: panic_cannot_unwind // CHECK-NOT: panic vec.into_boxed_slice() @@ -33,15 +33,15 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> { pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> { // CHECK-NOT: panic - // Call to panic_no_unwind in case of double-panic is expected, + // Call to panic_cannot_unwind in case of double-panic is expected, // but other panics are not. // CHECK: cleanup - // CHECK-NEXT: ; call core::panicking::panic_no_unwind - // CHECK-NEXT: panic_no_unwind + // CHECK-NEXT: ; call core::panicking::panic_cannot_unwind + // CHECK-NEXT: panic_cannot_unwind // CHECK-NOT: panic iter.iter().copied().collect() } -// CHECK: ; core::panicking::panic_no_unwind -// CHECK: declare void @{{.*}}panic_no_unwind +// CHECK: ; core::panicking::panic_cannot_unwind +// CHECK: declare void @{{.*}}panic_cannot_unwind diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs index dd3dce4e720..83737a02200 100644 --- a/src/test/incremental/change_symbol_export_status.rs +++ b/src/test/incremental/change_symbol_export_status.rs @@ -2,8 +2,6 @@ // compile-flags: -Zquery-dep-graph // [rpass1]compile-flags: -Zincremental-ignore-spans // [rpass2]compile-flags: -Zincremental-ignore-spans -// [rpass3]compile-flags: -Zincremental-relative-spans -// [rpass4]compile-flags: -Zincremental-relative-spans #![feature(rustc_attrs)] #![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass2")] diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index f3a7722cdca..65df2e8292a 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index c769246b29b..7bf99f6112e 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 70ef10645f1..db367d07094 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 0f8898c389b..bc83723a908 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -16,9 +16,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs index 87fd21fd1b8..9ac9ae24f81 100644 --- a/src/test/incremental/hashes/exported_vs_not.rs +++ b/src/test/incremental/hashes/exported_vs_not.rs @@ -4,9 +4,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs index 3121abbea36..1906843c7a2 100644 --- a/src/test/incremental/hashes/extern_mods.rs +++ b/src/test/incremental/hashes/extern_mods.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 16d6af01695..193e792c843 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 3ff949fbb3f..182ca7d926c 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(linkage)] diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index cff557dcb74..937fd3ac879 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 9ef46847243..b1ac6f6fa6c 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 1abbff32c6f..285f857c9cb 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index dc878d6827c..3118aa13564 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -12,9 +12,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 01320cd51f4..180bf6fec87 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index ada541e644a..87b86479d07 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs index fa054c7decc..4429df6833e 100644 --- a/src/test/incremental/hashes/match_expressions.rs +++ b/src/test/incremental/hashes/match_expressions.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index 67d87f5c4ed..bb83f8300d0 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index fc9671cb41b..e50e5674c66 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index 7a91722d70f..4a2706b4f01 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -16,9 +16,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index c453eeceb77..b583bee2f24 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -16,9 +16,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index f555f555f92..3b2e18d17a9 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 18fb716353f..58af51eef07 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index 88fd4d89b28..c81b0d0afb8 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs index 9b4d23757b8..c1cc0b62bc2 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -11,9 +11,6 @@ // [cfail1]compile-flags: -Zincremental-ignore-spans // [cfail2]compile-flags: -Zincremental-ignore-spans // [cfail3]compile-flags: -Zincremental-ignore-spans -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs index 639454cc975..38ab2846191 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -1,21 +1,17 @@ // This test makes sure that just changing a definition's location in the // source file also changes its incr. comp. hash, if debuginfo is enabled. -// revisions:rpass1 rpass2 rpass3 rpass4 +// revisions:rpass1 rpass2 // ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g -Z query-dep-graph -// [rpass3]compile-flags: -Zincremental-relative-spans -// [rpass4]compile-flags: -Zincremental-relative-spans #![feature(rustc_attrs)] #![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")] -#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass4")] -#[cfg(any(rpass1, rpass3))] +#[cfg(rpass1)] pub fn main() {} -#[cfg(any(rpass2, rpass4))] -#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")] -#[rustc_clean(cfg = "rpass4")] +#[cfg(rpass2)] +#[rustc_clean(cfg = "rpass2")] pub fn main() {} diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs index 6f51c9729e3..085e4cd78ca 100644 --- a/src/test/incremental/spans_significant_w_panic.rs +++ b/src/test/incremental/spans_significant_w_panic.rs @@ -1,26 +1,22 @@ // This test makes sure that just changing a definition's location in the // source file also changes its incr. comp. hash, if debuginfo is enabled. -// revisions:rpass1 rpass2 rpass3 rpass4 -// [rpass3]compile-flags: -Zincremental-relative-spans -// [rpass4]compile-flags: -Zincremental-relative-spans +// revisions:rpass1 rpass2 // compile-flags: -C overflow-checks=on -Z query-dep-graph #![feature(rustc_attrs)] #![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")] -#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")] -#[cfg(any(rpass1, rpass3))] +#[cfg(rpass1)] pub fn main() { if std::hint::black_box(false) { panic!() } } -#[cfg(any(rpass2, rpass4))] -#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")] -#[rustc_clean(cfg = "rpass4")] +#[cfg(rpass2)] +#[rustc_clean(cfg = "rpass2")] pub fn main() { if std::hint::black_box(false) { panic!() diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index cae7b4aab75..e15a8d18f85 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -1,7 +1,5 @@ -// revisions: cfail1 cfail2 cfail3 cfail4 +// revisions: cfail1 cfail2 // compile-flags: -Z query-dep-graph -// [cfail3]compile-flags: -Zincremental-relative-spans -// [cfail4]compile-flags: -Zincremental-relative-spans // build-pass (FIXME(62277): could be check-pass?) #![allow(warnings)] @@ -13,14 +11,13 @@ // needed even for callers of `x`. pub mod x { - #[cfg(any(cfail1, cfail3))] + #[cfg(cfail1)] pub fn x() { println!("{}", "1"); } - #[cfg(any(cfail2, cfail4))] - #[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg = "cfail2")] - #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail4")] + #[cfg(cfail2)] + #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail2")] pub fn x() { println!("{}", "2"); } @@ -30,7 +27,6 @@ pub mod y { use x; #[rustc_clean(cfg = "cfail2")] - #[rustc_clean(cfg = "cfail4")] pub fn y() { x::x(); } @@ -40,7 +36,6 @@ pub mod z { use y; #[rustc_clean(cfg = "cfail2")] - #[rustc_clean(cfg = "cfail4")] pub fn z() { y::y(); } diff --git a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs index 31f329a7f72..368a726ea90 100644 --- a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs +++ b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs @@ -3,10 +3,7 @@ // ends up with any spans in its LLVM bitecode, so LLVM is able to skip // re-building any modules which import 'inlined_fn' -// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6 -// [cfail4]compile-flags: -Zincremental-relative-spans -// [cfail5]compile-flags: -Zincremental-relative-spans -// [cfail6]compile-flags: -Zincremental-relative-spans +// revisions: cfail1 cfail2 cfail3 // compile-flags: -Z query-dep-graph -O // build-pass (FIXME(62277): could be check-pass?) @@ -19,16 +16,6 @@ kind = "post-lto" )] #![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-foo", - cfg = "cfail5", - kind = "post-lto" -)] -#![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-foo", - cfg = "cfail6", - kind = "post-lto" -)] -#![rustc_expected_cgu_reuse( module = "cgu_keeps_identical_fn-bar", cfg = "cfail2", kind = "post-lto" @@ -38,16 +25,6 @@ cfg = "cfail3", kind = "post-lto" )] -#![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-bar", - cfg = "cfail5", - kind = "post-lto" -)] -#![rustc_expected_cgu_reuse( - module = "cgu_keeps_identical_fn-bar", - cfg = "cfail6", - kind = "post-lto" -)] mod foo { diff --git a/src/test/mir-opt/inline/cycle.g.Inline.diff b/src/test/mir-opt/inline/cycle.g.Inline.diff index afe157ccd7f..5f3ee467c88 100644 --- a/src/test/mir-opt/inline/cycle.g.Inline.diff +++ b/src/test/mir-opt/inline/cycle.g.Inline.diff @@ -10,6 +10,8 @@ + let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 + let mut _4: &fn() {main}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 + let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8 ++ } + } bb0: { @@ -27,10 +29,7 @@ + StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 + _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 + StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ _3 = <fn() {main} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ // mir::Constant -+ // + span: $DIR/cycle.rs:6:5: 6:6 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {main}, ()) -> <fn() {main} as FnOnce<()>>::Output {<fn() {main} as Fn<()>>::call}, val: Value(<ZST>) } ++ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb1: { @@ -40,19 +39,19 @@ return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 + } + -+ bb2: { -+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 -+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ bb2 (cleanup): { ++ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + + bb3 (cleanup): { -+ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 + } + -+ bb4 (cleanup): { -+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 ++ bb4: { ++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 ++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 } } diff --git a/src/test/mir-opt/inline/cycle.main.Inline.diff b/src/test/mir-opt/inline/cycle.main.Inline.diff index bd89e09ecd1..6b4c63bbd91 100644 --- a/src/test/mir-opt/inline/cycle.main.Inline.diff +++ b/src/test/mir-opt/inline/cycle.main.Inline.diff @@ -10,6 +10,8 @@ + let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 + let mut _4: &fn() {g}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 + let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8 ++ } + } bb0: { @@ -27,10 +29,7 @@ + StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 + _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 + StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ _3 = <fn() {g} as Fn<()>>::call(move _4, move _5) -> [return: bb2, unwind: bb3]; // scope 1 at $DIR/cycle.rs:6:5: 6:8 -+ // mir::Constant -+ // + span: $DIR/cycle.rs:6:5: 6:6 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {g}, ()) -> <fn() {g} as FnOnce<()>>::Output {<fn() {g} as Fn<()>>::call}, val: Value(<ZST>) } ++ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb1: { @@ -40,19 +39,19 @@ return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 + } + -+ bb2: { -+ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 -+ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 -+ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ bb2 (cleanup): { ++ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + + bb3 (cleanup): { -+ drop(_2) -> bb4; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 + } + -+ bb4 (cleanup): { -+ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 ++ bb4: { ++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 ++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 } } diff --git a/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff index d9fd7b324c7..7fd62be7ab9 100644 --- a/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff +++ b/src/test/mir-opt/inline/exponential_runtime.main.Inline.diff @@ -8,43 +8,68 @@ + let _2: (); // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 + let _3: (); // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 + let _4: (); // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:73:9: 73:25 ++ let _5: (); // in scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 ++ let _6: (); // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ let _7: (); // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ } + } bb0: { StorageLive(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 - _1 = <() as G>::call() -> bb1; // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 + StorageLive(_2); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 -+ _2 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 ++ StorageLive(_5); // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 ++ _5 = <() as E>::call() -> bb3; // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 // mir::Constant - // + span: $DIR/exponential_runtime.rs:86:5: 86:20 - // + literal: Const { ty: fn() {<() as G>::call}, val: Value(<ZST>) } -+ // + span: $DIR/exponential_runtime.rs:73:9: 73:23 -+ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } ++ // + span: $DIR/exponential_runtime.rs:61:9: 61:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } } bb1: { -+ StorageDead(_2); // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26 -+ StorageLive(_3); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 -+ _3 = <() as F>::call() -> bb2; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 -+ // mir::Constant -+ // + span: $DIR/exponential_runtime.rs:74:9: 74:23 -+ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } -+ } -+ -+ bb2: { + StorageDead(_3); // scope 1 at $DIR/exponential_runtime.rs:74:25: 74:26 + StorageLive(_4); // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 -+ _4 = <() as F>::call() -> bb3; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ _4 = <() as F>::call() -> bb2; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 + // mir::Constant + // + span: $DIR/exponential_runtime.rs:75:9: 75:23 + // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } + } + -+ bb3: { ++ bb2: { + StorageDead(_4); // scope 1 at $DIR/exponential_runtime.rs:75:25: 75:26 StorageDead(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:22: +1:23 _0 = const (); // scope 0 at $DIR/exponential_runtime.rs:+0:11: +2:2 return; // scope 0 at $DIR/exponential_runtime.rs:+2:2: +2:2 ++ } ++ ++ bb3: { ++ StorageDead(_5); // scope 2 at $DIR/exponential_runtime.rs:61:25: 61:26 ++ StorageLive(_6); // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ _6 = <() as E>::call() -> bb4; // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:62:9: 62:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } ++ } ++ ++ bb4: { ++ StorageDead(_6); // scope 2 at $DIR/exponential_runtime.rs:62:25: 62:26 ++ StorageLive(_7); // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ _7 = <() as E>::call() -> bb5; // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:63:9: 63:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } ++ } ++ ++ bb5: { ++ StorageDead(_7); // scope 2 at $DIR/exponential_runtime.rs:63:25: 63:26 ++ StorageDead(_2); // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26 ++ StorageLive(_3); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ _3 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:74:9: 74:23 ++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } } } diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff index f54a1a747d4..5510cd7bc8c 100644 --- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff @@ -5,17 +5,20 @@ let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 + scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24 ++ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23 ++ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31 ++ } ++ } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 -+ _1 = <A<C> as Call>::call() -> bb1; // scope 1 at $DIR/inline_cycle.rs:43:9: 43:23 ++ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28 // mir::Constant - // + span: $DIR/inline_cycle.rs:14:5: 14:22 -- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } -+ // + span: $DIR/inline_cycle.rs:43:9: 43:21 -+ // + literal: Const { ty: fn() {<A<C> as Call>::call}, val: Value(<ZST>) } ++ // + span: $DIR/inline_cycle.rs:36:9: 36:26 + // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } } bb1: { diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff index a940848c269..64c0065b543 100644 --- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff @@ -9,6 +9,8 @@ + debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23 + let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 + let mut _4: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8 ++ } + } bb0: { @@ -24,10 +26,7 @@ // + literal: Const { ty: fn() {f}, val: Value(<ZST>) } + StorageLive(_3); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 + StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, move _4) -> bb1; // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 -+ // mir::Constant -+ // + span: $DIR/inline_cycle.rs:54:5: 54:6 -+ // + literal: Const { ty: extern "rust-call" fn(fn() {f}, ()) -> <fn() {f} as FnOnce<()>>::Output {<fn() {f} as FnOnce<()>>::call_once}, val: Value(<ZST>) } ++ _3 = move _2() -> bb1; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL } bb1: { diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff index 04de3e61e5f..52debab4dd1 100644 --- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -6,18 +6,21 @@ let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 + scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24 + scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31 ++ scope 3 (inlined <A as Call>::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31 ++ } ++ } + } + } bb0: { StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 - _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 -+ _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28 // mir::Constant - // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22 -- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } + // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26 -+ // + literal: Const { ty: fn() {<A as Call>::call}, val: Value(<ZST>) } + // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } } bb1: { diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index a01bcf1645b..f82fcf4c821 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -20,6 +20,8 @@ + debug b => _9; // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10 + } + } ++ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16 ++ } + } bb0: { @@ -38,25 +40,10 @@ + StorageLive(_4); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 + _4 = &_2; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 + StorageLive(_5); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 -+ _3 = <fn() -> ! {sleep} as Fn<()>>::call(move _4, move _5) -> [return: bb1, unwind: bb5]; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 -+ // mir::Constant -+ // + span: $DIR/inline_diverging.rs:27:13: 27:14 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) } ++ _3 = move (*_4)() -> [return: bb6, unwind: bb4]; // scope 4 at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + + bb1: { -+ StorageDead(_5); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 -+ StorageDead(_4); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 -+ StorageLive(_6); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 -+ _6 = &_2; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 -+ StorageLive(_7); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 -+ _9 = <fn() -> ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb2, unwind: bb4]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 -+ // mir::Constant -+ // + span: $DIR/inline_diverging.rs:28:13: 28:14 -+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) } -+ } -+ -+ bb2: { + StorageDead(_7); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 + StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 + StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 @@ -66,23 +53,35 @@ + (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 + StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11 + StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 -+ drop(_2) -> bb3; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_2) -> bb2; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 + } + -+ bb3: { ++ bb2: { + unreachable; // scope 0 at $DIR/inline_diverging.rs:30:2: 30:2 + } + ++ bb3 (cleanup): { ++ drop(_3) -> bb4; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ + bb4 (cleanup): { -+ drop(_3) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_2) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 + } + + bb5 (cleanup): { -+ drop(_2) -> bb6; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ resume; // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2 + } + -+ bb6 (cleanup): { -+ resume; // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2 ++ bb6: { ++ StorageDead(_5); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageDead(_4); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageLive(_6); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ _6 = &_2; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ StorageLive(_7); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ _9 = <fn() -> ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb1, unwind: bb3]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ // mir::Constant ++ // + span: $DIR/inline_diverging.rs:28:13: 28:14 ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) } } } diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index bd21405f14b..f27b64c3054 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -7,7 +7,7 @@ let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 -+ let mut _7: bool; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ let mut _7: bool; // in scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 scope 1 { debug _r => _1; // in scope 1 at $DIR/inline_generator.rs:+1:9: +1:11 } @@ -23,7 +23,7 @@ + } + } + } -+ scope 6 (inlined g::{closure#0}) { // at $DIR/inline_generator.rs:9:14: 9:46 ++ scope 6 (inlined g::{closure#0}) { // at $DIR/inline_generator.rs:9:33: 9:46 + debug a => _7; // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7 + let mut _8: i32; // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39 + let mut _9: u32; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 @@ -68,8 +68,8 @@ - // mir::Constant - // + span: $DIR/inline_generator.rs:9:33: 9:39 - // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(<ZST>) } -+ StorageLive(_7); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 -+ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageLive(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 ++ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 + _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + _9 = discriminant((*_10)); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + switchInt(move _9) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 @@ -77,7 +77,7 @@ - bb3: { + bb1: { -+ StorageDead(_7); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 ++ StorageDead(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 StorageDead(_2); // scope 0 at $DIR/inline_generator.rs:+1:45: +1:46 StorageDead(_4); // scope 0 at $DIR/inline_generator.rs:+1:46: +1:47 _0 = const (); // scope 0 at $DIR/inline_generator.rs:+0:11: +2:2 diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff index 969573ba325..09dd35c4c68 100644 --- a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff @@ -5,7 +5,7 @@ debug f => _1; // in scope 0 at $DIR/inline_shims.rs:+0:20: +0:21 let mut _0: fn(A, B); // return place in scope 0 at $DIR/inline_shims.rs:+0:36: +0:44 let mut _2: &fn(A, B); // in scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 -+ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline_shims.rs:6:5: 6:14 ++ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline_shims.rs:6:7: 6:14 + } bb0: { diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir index 777681e1ce7..dc0c3235043 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -6,7 +6,7 @@ fn a(_1: &mut [T]) -> &mut [T] { let mut _2: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _4: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:5: 3:15 + scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:7: 3:15 debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir index 83545c99100..b6aff30149f 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -6,7 +6,7 @@ fn b(_1: &mut Box<T>) -> &mut T { let mut _2: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:5: 8:15 + scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15 debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir index ed4e9927ce9..af830d2494e 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir @@ -5,7 +5,7 @@ fn c(_1: &[T]) -> &[T] { let mut _0: &[T]; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:25: +0:29 let _2: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:13:5: 13:15 + scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:13:7: 13:15 debug self => _3; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL } diff --git a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir index 18a2670be21..4f9342247d7 100644 --- a/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +++ b/src/test/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -5,7 +5,7 @@ fn d(_1: &Box<T>) -> &T { let mut _0: &T; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:28: +0:30 let _2: &T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 - scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:5: 18:15 + scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:7: 18:15 debug self => _3; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _4: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL let mut _5: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/src/test/mir-opt/issue_101973.inner.ConstProp.diff b/src/test/mir-opt/issue_101973.inner.ConstProp.diff index 8fe60a0245d..b2706e5a436 100644 --- a/src/test/mir-opt/issue_101973.inner.ConstProp.diff +++ b/src/test/mir-opt/issue_101973.inner.ConstProp.diff @@ -23,7 +23,7 @@ debug out => _4; // in scope 2 at $DIR/issue_101973.rs:6:9: 6:16 } } - scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:5: 14:58 + scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:18: 14:58 debug self => _4; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL debug n => _6; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL let mut _15: u32; // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index e0d6b58f229..c17d221f86a 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -4,9 +4,9 @@ fn num_to_digit(_1: char) -> u32 { debug num => _1; // in scope 0 at $DIR/issue_59352.rs:+0:21: +0:24 let mut _0: u32; // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38 let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41 - let mut _3: u32; // in scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + let mut _3: u32; // in scope 0 at $DIR/issue_59352.rs:+2:12: +2:23 let mut _9: isize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:8: 14:23 + scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:12: 14:23 debug self => _1; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL debug radix => _3; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL let mut _4: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL @@ -16,7 +16,7 @@ fn num_to_digit(_1: char) -> u32 { debug self => _4; // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL } } - scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:26: 14:50 + scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:42: 14:50 debug self => _2; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _7: isize; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL let mut _8: !; // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL @@ -26,7 +26,7 @@ fn num_to_digit(_1: char) -> u32 { } bb0: { - StorageLive(_3); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + StorageLive(_3); // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23 StorageLive(_4); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageLive(_5); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageLive(_6); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL @@ -65,7 +65,7 @@ fn num_to_digit(_1: char) -> u32 { _9 = discriminant((*_4)); // scope 2 at $SRC_DIR/core/src/option.rs:LL:COL StorageDead(_4); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL StorageDead(_5); // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 + StorageDead(_3); // scope 0 at $DIR/issue_59352.rs:+2:12: +2:23 switchInt(move _9) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23 } diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index 6ae16bdb5b8..e57544e09e2 100644 --- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -22,6 +22,9 @@ let mut _18: i32; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL scope 9 { debug e => _16; // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL + debug t => _18; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + } } } } @@ -92,11 +95,18 @@ StorageLive(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL StorageLive(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL _18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL -- _17 = <i32 as From<i32>>::from(move _18) -> bb8; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL -+ _17 = <i32 as From<i32>>::from(move _18) -> bb7; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - // mir::Constant - // + span: $SRC_DIR/core/src/result.rs:LL:COL - // + literal: Const { ty: fn(i32) -> i32 {<i32 as From<i32>>::from}, val: Value(<ZST>) } + _17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL + StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 + StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 + StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 + StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 + return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 } - bb5: { @@ -142,20 +152,5 @@ + _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 + switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10 } - -- bb8: { -+ bb7: { - StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL - StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10 - StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11 - StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2 - return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2 - } } diff --git a/src/test/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir b/src/test/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir new file mode 100644 index 00000000000..916f99049c6 --- /dev/null +++ b/src/test/mir-opt/simple_option_map_e2e.ezmap.PreCodegen.after.mir @@ -0,0 +1,52 @@ +// MIR for `ezmap` after PreCodegen + +fn ezmap(_1: Option<i32>) -> Option<i32> { + debug x => _1; // in scope 0 at $DIR/simple_option_map_e2e.rs:+0:14: +0:15 + let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/simple_option_map_e2e.rs:+0:33: +0:44 + let mut _2: [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]; // in scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 + scope 1 (inlined map::<i32, i32, [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]>) { // at $DIR/simple_option_map_e2e.rs:14:5: 14:22 + debug slf => _1; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:17: 2:20 + debug f => _2; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:33: 2:34 + let mut _3: isize; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:9: 7:16 + let mut _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + let mut _5: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + scope 2 { + debug x => _5; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 + scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + debug n => _5; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14 + } + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21 + _3 = discriminant(_1); // scope 1 at $DIR/simple_option_map_e2e.rs:6:11: 6:14 + switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 1 at $DIR/simple_option_map_e2e.rs:6:5: 6:14 + } + + bb1: { + Deinit(_0); // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 + discriminant(_0) = 0; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 + goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21 + } + + bb2: { + unreachable; // scope 1 at $DIR/simple_option_map_e2e.rs:6:11: 6:14 + } + + bb3: { + _5 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15 + StorageLive(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29 + _4 = Add(move _5, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21 + Deinit(_0); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + ((_0 as Some).0: i32) = move _4; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + discriminant(_0) = 1; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30 + StorageDead(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30 + goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2 + } + + bb4: { + StorageDead(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:21: +1:22 + return; // scope 0 at $DIR/simple_option_map_e2e.rs:+2:2: +2:2 + } +} diff --git a/src/test/mir-opt/simple_option_map_e2e.rs b/src/test/mir-opt/simple_option_map_e2e.rs new file mode 100644 index 00000000000..2acd2a227b8 --- /dev/null +++ b/src/test/mir-opt/simple_option_map_e2e.rs @@ -0,0 +1,19 @@ +#[inline(always)] +fn map<T, U, F>(slf: Option<T>, f: F) -> Option<U> +where + F: FnOnce(T) -> U, +{ + match slf { + Some(x) => Some(f(x)), + None => None, + } +} + +// EMIT_MIR simple_option_map_e2e.ezmap.PreCodegen.after.mir +pub fn ezmap(x: Option<i32>) -> Option<i32> { + map(x, |n| n + 1) +} + +fn main() { + assert_eq!(None, ezmap(None)); +} diff --git a/src/test/run-make-fulldeps/save-analysis/foo.rs b/src/test/run-make-fulldeps/save-analysis/foo.rs index 74aaabfbf1b..384589de3b4 100644 --- a/src/test/run-make-fulldeps/save-analysis/foo.rs +++ b/src/test/run-make-fulldeps/save-analysis/foo.rs @@ -5,6 +5,11 @@ extern crate rustc_graphviz; // A simple rust project +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + extern crate krate2; extern crate krate2 as krate3; diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml index aab27394eb1..d4443f821d2 100644 --- a/src/test/rustdoc-gui/codeblock-tooltip.goml +++ b/src/test/rustdoc-gui/codeblock-tooltip.goml @@ -34,7 +34,6 @@ define-function: ( ".docblock .example-wrap.compile_fail .tooltip::after", { "content": '"This example deliberately fails to compile"', - "text-align": "center", "padding": "5px 3px 3px", "background-color": |background|, "color": |color|, @@ -74,7 +73,6 @@ define-function: ( ".docblock .example-wrap.should_panic .tooltip::after", { "content": '"This example panics"', - "text-align": "center", "padding": "5px 3px 3px", "background-color": |background|, "color": |color|, @@ -114,7 +112,6 @@ define-function: ( ".docblock .example-wrap.ignore .tooltip::after", { "content": '"This example is not tested"', - "text-align": "center", "padding": "5px 3px 3px", "background-color": |background|, "color": |color|, diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml index b094c483876..a3ed008719c 100644 --- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -1,23 +1,53 @@ // Checks that the setting "line numbers" is working as expected. goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html" +// Otherwise, we can't check text color +show-text: true + // We check that without this setting, there is no line number displayed. assert-false: "pre.example-line-numbers" -// We now set the setting to show the line numbers on code examples. -local-storage: {"rustdoc-line-numbers": "true" } -// We reload to make the line numbers appear. -reload: - -// We wait for them to be added into the DOM by the JS... -wait-for: "pre.example-line-numbers" -// If the test didn't fail, it means that it was found! // Let's now check some CSS properties... -assert-css: ("pre.example-line-numbers", { - "margin": "0px", - "padding": "13px 8px", - "text-align": "right", +define-function: ( + "check-colors", + (theme, color), + [ + // We now set the setting to show the line numbers on code examples. + ("local-storage", { + "rustdoc-theme": |theme|, + "rustdoc-use-system-theme": "false", + "rustdoc-line-numbers": "true" + }), + // We reload to make the line numbers appear and change theme. + ("reload"), + // We wait for them to be added into the DOM by the JS... + ("wait-for", "pre.example-line-numbers"), + // If the test didn't fail, it means that it was found! + ("assert-css", ( + "pre.example-line-numbers", + { + "color": |color|, + "margin": "0px", + "padding": "14px 8px", + "text-align": "right", + }, + ALL, + )), + ], +) +call-function: ("check-colors", { + "theme": "ayu", + "color": "rgb(92, 103, 115)", }) +call-function: ("check-colors", { + "theme": "dark", + "color": "rgb(59, 145, 226)", +}) +call-function: ("check-colors", { + "theme": "light", + "color": "rgb(198, 126, 45)", +}) + // The first code block has two lines so let's check its `<pre>` elements lists both of them. assert-text: ("pre.example-line-numbers", "1\n2") diff --git a/src/test/rustdoc-gui/docblock-table.goml b/src/test/rustdoc-gui/docblock-table.goml index 8645c1b1949..6f9209e0ab4 100644 --- a/src/test/rustdoc-gui/docblock-table.goml +++ b/src/test/rustdoc-gui/docblock-table.goml @@ -1,3 +1,4 @@ +// This test checks the appearance of the tables in the doc comments. goto: "file://" + |DOC_PATH| + "/test_docs/doc_block_table/struct.DocBlockTable.html#method.func" compare-elements-css: (".impl-items .docblock table th", ".top-doc .docblock table th", ["border"]) diff --git a/src/test/rustdoc-gui/links-color.goml b/src/test/rustdoc-gui/links-color.goml index 839629ad982..9402c09eb69 100644 --- a/src/test/rustdoc-gui/links-color.goml +++ b/src/test/rustdoc-gui/links-color.goml @@ -4,82 +4,95 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" // This is needed so that the text color is computed. show-text: true -// Ayu theme -local-storage: { - "rustdoc-theme": "ayu", - "rustdoc-use-system-theme": "false", -} -reload: - -assert-css: (".item-table .mod", {"color": "rgb(57, 175, 215)"}, ALL) -assert-css: (".item-table .macro", {"color": "rgb(163, 122, 204)"}, ALL) -assert-css: (".item-table .struct", {"color": "rgb(255, 160, 165)"}, ALL) -assert-css: (".item-table .enum", {"color": "rgb(255, 160, 165)"}, ALL) -assert-css: (".item-table .trait", {"color": "rgb(57, 175, 215)"}, ALL) -assert-css: (".item-table .fn", {"color": "rgb(253, 214, 135)"}, ALL) -assert-css: (".item-table .type", {"color": "rgb(255, 160, 165)"}, ALL) -assert-css: (".item-table .union", {"color": "rgb(255, 160, 165)"}, ALL) -assert-css: (".item-table .keyword", {"color": "rgb(57, 175, 215)"}, ALL) - -assert-css: ( - ".sidebar-elems a:not(.current)", - {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"}, - ALL, -) -assert-css: ( - ".sidebar-elems a.current", - {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "500"}, - ALL, +define-function: ( + "check-colors", + (theme, mod, macro, struct, enum, trait, fn, type, union, keyword, + sidebar, sidebar_current, sidebar_current_background), + [ + ("local-storage", { + "rustdoc-theme": |theme|, + "rustdoc-use-system-theme": "false", + }), + ("reload"), + // Checking results colors. + ("assert-css", (".item-table .mod", {"color": |mod|}, ALL)), + ("assert-css", (".item-table .macro", {"color": |macro|}, ALL)), + ("assert-css", (".item-table .struct", {"color": |struct|}, ALL)), + ("assert-css", (".item-table .enum", {"color": |enum|}, ALL)), + ("assert-css", (".item-table .trait", {"color": |trait|}, ALL)), + ("assert-css", (".item-table .fn", {"color": |fn|}, ALL)), + ("assert-css", (".item-table .type", {"color": |type|}, ALL)), + ("assert-css", (".item-table .union", {"color": |union|}, ALL)), + ("assert-css", (".item-table .keyword", {"color": |keyword|}, ALL)), + // Checking sidebar elements. + ("assert-css", ( + ".sidebar-elems a:not(.current)", + {"color": |sidebar|, "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"}, + ALL, + )), + ("assert-css", ( + ".sidebar-elems a.current", + { + "color": |sidebar_current|, + "background-color": |sidebar_current_background|, + "font-weight": "500", + }, + ALL, + )), + ], ) - -// Dark theme -local-storage: {"rustdoc-theme": "dark"} -reload: - -assert-css: (".item-table .mod", {"color": "rgb(210, 153, 29)"}, ALL) -assert-css: (".item-table .macro", {"color": "rgb(9, 189, 0)"}, ALL) -assert-css: (".item-table .struct", {"color": "rgb(45, 191, 184)"}, ALL) -assert-css: (".item-table .enum", {"color": "rgb(45, 191, 184)"}, ALL) -assert-css: (".item-table .trait", {"color": "rgb(183, 140, 242)"}, ALL) -assert-css: (".item-table .fn", {"color": "rgb(43, 171, 99)"}, ALL) -assert-css: (".item-table .type", {"color": "rgb(45, 191, 184)"}, ALL) -assert-css: (".item-table .union", {"color": "rgb(45, 191, 184)"}, ALL) -assert-css: (".item-table .keyword", {"color": "rgb(210, 153, 29)"}, ALL) - -assert-css: ( - ".sidebar-elems a:not(.current)", - {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"}, - ALL, +call-function: ( + "check-colors", + { + "theme": "ayu", + "mod": "rgb(57, 175, 215)", + "macro": "rgb(163, 122, 204)", + "struct": "rgb(255, 160, 165)", + "enum": "rgb(255, 160, 165)", + "trait": "rgb(57, 175, 215)", + "fn": "rgb(253, 214, 135)", + "type": "rgb(255, 160, 165)", + "union": "rgb(255, 160, 165)", + "keyword": "rgb(57, 175, 215)", + "sidebar": "rgb(83, 177, 219)", + "sidebar_current": "rgb(255, 180, 76)", + "sidebar_current_background": "rgba(0, 0, 0, 0)", + }, ) -assert-css: ( - ".sidebar-elems a.current", - {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)", "font-weight": "500"}, - ALL, -) - - -// Light theme -local-storage: {"rustdoc-theme": "light"} -reload: - -assert-css: (".item-table .mod", {"color": "rgb(56, 115, 173)"}, ALL) -assert-css: (".item-table .macro", {"color": "rgb(6, 128, 0)"}, ALL) -assert-css: (".item-table .struct", {"color": "rgb(173, 55, 138)"}, ALL) -assert-css: (".item-table .enum", {"color": "rgb(173, 55, 138)"}, ALL) -assert-css: (".item-table .trait", {"color": "rgb(110, 79, 201)"}, ALL) -assert-css: (".item-table .fn", {"color": "rgb(173, 124, 55)"}, ALL) -assert-css: (".item-table .type", {"color": "rgb(173, 55, 138)"}, ALL) -assert-css: (".item-table .union", {"color": "rgb(173, 55, 138)"}, ALL) -assert-css: (".item-table .keyword", {"color": "rgb(56, 115, 173)"}, ALL) - -assert-css: ( - ".sidebar-elems a:not(.current)", - {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"}, - ALL, +call-function: ( + "check-colors", + { + "theme": "dark", + "mod": "rgb(210, 153, 29)", + "macro": "rgb(9, 189, 0)", + "struct": "rgb(45, 191, 184)", + "enum": "rgb(45, 191, 184)", + "trait": "rgb(183, 140, 242)", + "fn": "rgb(43, 171, 99)", + "type": "rgb(45, 191, 184)", + "union": "rgb(45, 191, 184)", + "keyword": "rgb(210, 153, 29)", + "sidebar": "rgb(253, 191, 53)", + "sidebar_current": "rgb(253, 191, 53)", + "sidebar_current_background": "rgb(68, 68, 68)", + }, ) -assert-css: ( - ".sidebar-elems a.current", - {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)", "font-weight": "500"}, - ALL, +call-function: ( + "check-colors", + { + "theme": "light", + "mod": "rgb(56, 115, 173)", + "macro": "rgb(6, 128, 0)", + "struct": "rgb(173, 55, 138)", + "enum": "rgb(173, 55, 138)", + "trait": "rgb(110, 79, 201)", + "fn": "rgb(173, 124, 55)", + "type": "rgb(173, 55, 138)", + "union": "rgb(173, 55, 138)", + "keyword": "rgb(56, 115, 173)", + "sidebar": "rgb(53, 109, 164)", + "sidebar_current": "rgb(53, 109, 164)", + "sidebar_current_background": "rgb(255, 255, 255)", + }, ) diff --git a/src/test/rustdoc-gui/scrape-examples-color.goml b/src/test/rustdoc-gui/scrape-examples-color.goml new file mode 100644 index 00000000000..360e2af8ba4 --- /dev/null +++ b/src/test/rustdoc-gui/scrape-examples-color.goml @@ -0,0 +1,60 @@ +// Check that scrape example code blocks have the expected colors. +goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" +show-text: true + +define-function: ( + "check-colors", + (theme, highlight, highlight_focus, help_border, help_color, help_hover_border, + help_hover_color), + [ + ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }), + ("reload"), + ("wait-for", ".more-examples-toggle"), + ("assert-css", (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { + "background-color": |highlight|, + }, ALL)), + ("assert-css", (".scraped-example .example-wrap .rust span.highlight.focus", { + "background-color": |highlight_focus|, + }, ALL)), + + ("assert-css", (".scraped-example-list .scrape-help", { + "border-color": |help_border|, + "color": |help_color|, + })), + ("move-cursor-to", ".scraped-example-list .scrape-help"), + ("assert-css", (".scraped-example-list .scrape-help:hover", { + "border-color": |help_hover_border|, + "color": |help_hover_color|, + })), + // Moving the cursor to another item to not break next runs. + ("move-cursor-to", ".search-input"), + ] +) + +call-function: ("check-colors", { + "theme": "ayu", + "highlight": "rgb(91, 59, 1)", + "highlight_focus": "rgb(124, 75, 15)", + "help_border": "rgb(170, 170, 170)", + "help_color": "rgb(238, 238, 238)", + "help_hover_border": "rgb(255, 255, 255)", + "help_hover_color": "rgb(255, 255, 255)", +}) +call-function: ("check-colors", { + "theme": "dark", + "highlight": "rgb(91, 59, 1)", + "highlight_focus": "rgb(124, 75, 15)", + "help_border": "rgb(170, 170, 170)", + "help_color": "rgb(238, 238, 238)", + "help_hover_border": "rgb(255, 255, 255)", + "help_hover_color": "rgb(255, 255, 255)", +}) +call-function: ("check-colors", { + "theme": "light", + "highlight": "rgb(252, 255, 214)", + "highlight_focus": "rgb(246, 253, 176)", + "help_border": "rgb(85, 85, 85)", + "help_color": "rgb(51, 51, 51)", + "help_hover_border": "rgb(0, 0, 0)", + "help_hover_color": "rgb(0, 0, 0)", +}) diff --git a/src/test/rustdoc-gui/scrape-examples-fonts.goml b/src/test/rustdoc-gui/scrape-examples-fonts.goml index b7d7f4ccb4a..142f337cb74 100644 --- a/src/test/rustdoc-gui/scrape-examples-fonts.goml +++ b/src/test/rustdoc-gui/scrape-examples-fonts.goml @@ -1,3 +1,4 @@ +// This test ensures that the correct font is used in scraped examples. goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" store-value: (font, '"Fira Sans", Arial, NanumBarunGothic, sans-serif') diff --git a/src/test/rustdoc-gui/scrape-examples-layout.goml b/src/test/rustdoc-gui/scrape-examples-layout.goml index fde9a0ab0bc..95102528ec1 100644 --- a/src/test/rustdoc-gui/scrape-examples-layout.goml +++ b/src/test/rustdoc-gui/scrape-examples-layout.goml @@ -33,3 +33,17 @@ assert-property: ( ".more-scraped-examples .scraped-example:nth-child(6) .code-wrapper .src-line-numbers", {"clientWidth": |clientWidth|} ) + +// Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed +// correctly. + +store-value: (offset_y, 4) + +// First with desktop +assert-position: (".scraped-example .code-wrapper", {"y": 255}) +assert-position: (".scraped-example .code-wrapper .prev", {"y": 255 + |offset_y|}) + +// Then with mobile +size: (600, 600) +assert-position: (".scraped-example .code-wrapper", {"y": 314}) +assert-position: (".scraped-example .code-wrapper .prev", {"y": 314 + |offset_y|}) diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml index a0b696ee336..8c84fbc0c30 100644 --- a/src/test/rustdoc-gui/scrape-examples-toggle.goml +++ b/src/test/rustdoc-gui/scrape-examples-toggle.goml @@ -1,10 +1,46 @@ // This tests checks that the "scraped examples" toggle is working as expected. goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" -// Clicking "More examples..." will open additional examples -assert-attribute-false: (".more-examples-toggle", {"open": ""}) -click: ".more-examples-toggle" -assert-attribute: (".more-examples-toggle", {"open": ""}) +// Checking the color of the toggle line. +show-text: true +define-function: ( + "check-color", + (theme, toggle_line_color, toggle_line_hover_color), + [ + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + + // Clicking "More examples..." will open additional examples + ("assert-attribute-false", (".more-examples-toggle", {"open": ""})), + ("click", ".more-examples-toggle"), + ("assert-attribute", (".more-examples-toggle", {"open": ""})), + + ("assert-css", (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL)), + ("move-cursor-to", ".toggle-line"), + ("assert-css", ( + ".toggle-line:hover .toggle-line-inner", + {"background-color": |toggle_line_hover_color|}, + )), + // Moving cursor away from the toggle line to prevent disrupting next test. + ("move-cursor-to", ".search-input"), + ], +) + +call-function: ("check-color", { + "theme": "ayu", + "toggle_line_color": "rgb(153, 153, 153)", + "toggle_line_hover_color": "rgb(197, 197, 197)", +}) +call-function: ("check-color", { + "theme": "dark", + "toggle_line_color": "rgb(153, 153, 153)", + "toggle_line_hover_color": "rgb(197, 197, 197)", +}) +call-function: ("check-color", { + "theme": "light", + "toggle_line_color": "rgb(204, 204, 204)", + "toggle_line_hover_color": "rgb(153, 153, 153)", +}) // Toggling all docs will close additional examples click: "#toggle-all-docs" diff --git a/src/test/rustdoc-gui/search-tab.goml b/src/test/rustdoc-gui/search-tab.goml new file mode 100644 index 00000000000..c2634a04c8a --- /dev/null +++ b/src/test/rustdoc-gui/search-tab.goml @@ -0,0 +1,76 @@ +// Checking the colors of the search tab headers. +goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html?search=something" +show-text: true + +define-function: ( + "check-colors", + (theme, background, background_selected, background_hover, border_bottom, + border_bottom_selected, border_bottom_hover, border_top, border_top_selected, + border_top_hover), + [ + // Setting the theme. + ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + ("reload"), + + // These two commands are used to be sure the search will be run. + ("focus", ".search-input"), + ("press-key", "Enter"), + + ("wait-for", "#search-tabs"), + ("assert-css", ("#search-tabs > button:not(.selected)", { + "background-color": |background|, + "border-bottom": |border_bottom|, + "border-top": |border_top|, + })), + ("assert-css", ("#search-tabs > button.selected", { + "background-color": |background_selected|, + "border-bottom": |border_bottom_selected|, + "border-top": |border_top_selected|, + })), + ("move-cursor-to", "#search-tabs > button:not(.selected)"), + ("assert-css", ("#search-tabs > button:not(.selected):hover", { + "background-color": |background_hover|, + "border-bottom": |border_bottom_hover|, + "border-top": |border_top_hover|, + })), + // To prevent disrupting next run of this function. + ("move-cursor-to", ".search-input"), + ], +) + +call-function: ("check-colors", { + "theme": "ayu", + "background": "rgba(0, 0, 0, 0)", + "background_selected": "rgb(20, 25, 32)", + "background_hover": "rgba(0, 0, 0, 0)", + "border_bottom": "0px none rgb(197, 197, 197)", + "border_bottom_selected": "1px solid rgb(255, 180, 76)", + "border_bottom_hover": "1px solid rgba(242, 151, 24, 0.3)", + "border_top": "0px none rgb(197, 197, 197)", + "border_top_selected": "0px none rgb(197, 197, 197)", + "border_top_hover": "0px none rgb(197, 197, 197)", +}) +call-function: ("check-colors", { + "theme": "dark", + "background": "rgb(37, 37, 37)", + "background_selected": "rgb(53, 53, 53)", + "background_hover": "rgb(53, 53, 53)", + "border_bottom": "0px none rgb(221, 221, 221)", + "border_bottom_selected": "0px none rgb(221, 221, 221)", + "border_bottom_hover": "0px none rgb(221, 221, 221)", + "border_top": "2px solid rgb(37, 37, 37)", + "border_top_selected": "2px solid rgb(0, 137, 255)", + "border_top_hover": "2px solid rgb(0, 137, 255)", +}) +call-function: ("check-colors", { + "theme": "light", + "background": "rgb(230, 230, 230)", + "background_selected": "rgb(255, 255, 255)", + "background_hover": "rgb(255, 255, 255)", + "border_bottom": "0px none rgb(0, 0, 0)", + "border_bottom_selected": "0px none rgb(0, 0, 0)", + "border_bottom_hover": "0px none rgb(0, 0, 0)", + "border_top": "2px solid rgb(230, 230, 230)", + "border_top_selected": "2px solid rgb(0, 137, 255)", + "border_top_hover": "2px solid rgb(0, 137, 255)", +}) diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 36e4d555b8e..d5f57ed6102 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -1,7 +1,52 @@ // The goal of this test is to ensure that the sidebar is working as expected in the source // code pages. goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" -// First: desktop mode. +show-text: true + +// First, check the sidebar colors. +define-function: ( + "check-colors", + (theme, color, background_color), + [ + ("local-storage", { + "rustdoc-theme": |theme|, + "rustdoc-use-system-theme": "false", + }), + ("reload"), + // Checking results colors. + ("assert-css", (".source .sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL)), + ], +) + +call-function: ( + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } +) +call-function: ( + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } +) +call-function: ( + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } +) + +// Next, desktop mode layout. size: (1100, 800) // We check that the sidebar isn't expanded and has the expected width. assert-css: ("nav.sidebar", {"width": "50px"}) diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index 5058630f469..bfd7567a224 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -2,6 +2,50 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" assert-property: (".sidebar", {"clientWidth": "200"}) show-text: true + +// First, check the sidebar colors. +define-function: ( + "check-colors", + (theme, color, background_color), + [ + ("local-storage", { + "rustdoc-theme": |theme|, + "rustdoc-use-system-theme": "false", + }), + ("reload"), + // Checking results colors. + ("assert-css", (".sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL)), + ], +) + +call-function: ( + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } +) +call-function: ( + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } +) +call-function: ( + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } +) + local-storage: {"rustdoc-theme": "light"} // We reload the page so the local storage settings are being used. reload: diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index 25da74e5173..aa792196960 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -89,9 +89,9 @@ assert-css: (".src-line-numbers", {"text-align": "right"}) // do anything (and certainly not add a `#NaN` to the URL!). goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" // We use this assert-position to know where we will click. -assert-position: ("//*[@id='1']", {"x": 104, "y": 112}) +assert-position: ("//*[@id='1']", {"x": 88, "y": 112}) // We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`. -click: (103, 103) +click: (87, 103) assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH) // Checking the source code sidebar. @@ -111,8 +111,57 @@ assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) click: "#source-sidebar details:first-of-type > summary" assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) -// Check the spacing. -assert-css: ("#source-sidebar > details.dir-entry", {"padding-left": "4px"}) +// And open it again, since it'll be the reference we use to check positions. +click: "#source-sidebar details:first-of-type > summary" +assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) + +// Check the sidebar directory entries have a marker and spacing (desktop). +store-property: ( + link_height, + "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", + "offsetHeight" +) +define-function: ( + "check-sidebar-dir-entry", + (x, y), + [ + ("assert", "details:first-of-type.dir-entry[open] > summary::marker"), + ("assert-css", ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"})), + // This check ensures that the summary is only one line. + ("assert-property", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > summary", + {"offsetHeight": |link_height|} + )), + ("assert-position", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > summary", + {"x": |x|, "y": |y|} + )), + ("assert-property", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", + {"offsetHeight": |link_height|} + )), + ("assert-position", ( + "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", + // left margin + {"x": |x| + 27, "y": |y| + |link_height|} + )), + ] +) +store-property: ( + source_sidebar_title_height, + "#source-sidebar > .title", + "offsetHeight" +) +store-property: ( + source_sidebar_title_y, + "#source-sidebar > .title", + "offsetTop" +) +call-function: ("check-sidebar-dir-entry", { + "x": 0, + // border + margin = 6 + "y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6, +}) // Check the search form assert-css: ("nav.sub", {"flex-direction": "row"}) @@ -125,13 +174,45 @@ assert-property: ("nav.sub form", {"offsetTop": 28, "offsetHeight": 34}) assert-property: ("#main-content", {"offsetTop": 90}) // 28 = 90 - 34 - 28 -// Now do the same check on moderately-sized mobile. +// Now do the same check on moderately-sized, tablet mobile. size: (700, 700) assert-css: ("nav.sub", {"flex-direction": "row"}) assert-property: ("nav.sub form", {"offsetTop": 21, "offsetHeight": 34}) assert-property: ("#main-content", {"offsetTop": 76}) // 21 = 76 - 34 - 21 -// Tiny mobile gets a different display where the logo is stacked on top. +// Check the sidebar directory entries have a marker and spacing (tablet). +store-property: ( + source_sidebar_title_height, + "#source-sidebar > .title", + "offsetHeight" +) +store-property: ( + source_sidebar_title_y, + "#source-sidebar > .title", + "offsetTop" +) +call-function: ("check-sidebar-dir-entry", { + "x": 0, + "y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6, +}) + +// Tiny, phone mobile gets a different display where the logo is stacked on top. size: (450, 700) assert-css: ("nav.sub", {"flex-direction": "column"}) + +// Check the sidebar directory entries have a marker and spacing (phone). +store-property: ( + source_sidebar_title_height, + "#source-sidebar > .title", + "offsetHeight" +) +store-property: ( + source_sidebar_title_y, + "#source-sidebar > .title", + "offsetTop" +) +call-function: ("check-sidebar-dir-entry", { + "x": 0, + "y": |source_sidebar_title_y| + |source_sidebar_title_height| + 6, +}) diff --git a/src/test/rustdoc-json/enums/discriminant/basic.rs b/src/test/rustdoc-json/enums/discriminant/basic.rs index 8c221615aa7..06906df3b2c 100644 --- a/src/test/rustdoc-json/enums/discriminant/basic.rs +++ b/src/test/rustdoc-json/enums/discriminant/basic.rs @@ -1,12 +1,12 @@ #[repr(i8)] pub enum Ordering { - // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.expr" '"-1"' - // @is "$.index[*][?(@.name=='Less')].inner.variant_inner.value" '"-1"' + // @is "$.index[*][?(@.name=='Less')].inner.discriminant.expr" '"-1"' + // @is "$.index[*][?(@.name=='Less')].inner.discriminant.value" '"-1"' Less = -1, - // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.expr" '"0"' - // @is "$.index[*][?(@.name=='Equal')].inner.variant_inner.value" '"0"' + // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.expr" '"0"' + // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.value" '"0"' Equal = 0, - // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.expr" '"1"' - // @is "$.index[*][?(@.name=='Greater')].inner.variant_inner.value" '"1"' + // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.expr" '"1"' + // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.value" '"1"' Greater = 1, } diff --git a/src/test/rustdoc-json/enums/discriminant/expr.rs b/src/test/rustdoc-json/enums/discriminant/expr.rs index 235b0b47381..e639965e79b 100644 --- a/src/test/rustdoc-json/enums/discriminant/expr.rs +++ b/src/test/rustdoc-json/enums/discriminant/expr.rs @@ -1,30 +1,30 @@ pub enum Foo { - // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='Addition')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.expr" '"{ _ }"' Addition = 0 + 0, - // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.value" '"1"' - // @is "$.index[*][?(@.name=='Bin')].inner.variant_inner.expr" '"0b1"' + // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.value" '"1"' + // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.expr" '"0b1"' Bin = 0b1, - // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.value" '"2"' - // @is "$.index[*][?(@.name=='Oct')].inner.variant_inner.expr" '"0o2"' + // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.value" '"2"' + // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.expr" '"0o2"' Oct = 0o2, - // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.value" '"3"' - // @is "$.index[*][?(@.name=='PubConst')].inner.variant_inner.expr" '"THREE"' + // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.value" '"3"' + // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.expr" '"THREE"' PubConst = THREE, - // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.value" '"4"' - // @is "$.index[*][?(@.name=='Hex')].inner.variant_inner.expr" '"0x4"' + // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.value" '"4"' + // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.expr" '"0x4"' Hex = 0x4, - // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.value" '"5"' - // @is "$.index[*][?(@.name=='Cast')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.value" '"5"' + // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.expr" '"{ _ }"' Cast = 5 as isize, - // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.value" '"6"' - // @is "$.index[*][?(@.name=='PubCall')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.value" '"6"' + // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.expr" '"{ _ }"' PubCall = six(), - // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.value" '"7"' - // @is "$.index[*][?(@.name=='PrivCall')].inner.variant_inner.expr" '"{ _ }"' + // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.value" '"7"' + // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.expr" '"{ _ }"' PrivCall = seven(), - // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.value" '"8"' - // @is "$.index[*][?(@.name=='PrivConst')].inner.variant_inner.expr" '"EIGHT"' + // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.value" '"8"' + // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.expr" '"EIGHT"' PrivConst = EIGHT, } diff --git a/src/test/rustdoc-json/enums/discriminant/limits.rs b/src/test/rustdoc-json/enums/discriminant/limits.rs index 8df73d78d23..e56d5594f2f 100644 --- a/src/test/rustdoc-json/enums/discriminant/limits.rs +++ b/src/test/rustdoc-json/enums/discriminant/limits.rs @@ -4,40 +4,40 @@ #[repr(u64)] pub enum U64 { - // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='U64Min')].inner.variant_inner.expr" '"u64::MIN"' + // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.expr" '"u64::MIN"' U64Min = u64::MIN, - // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.value" '"18446744073709551615"' - // @is "$.index[*][?(@.name=='U64Max')].inner.variant_inner.expr" '"u64::MAX"' + // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.value" '"18446744073709551615"' + // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.expr" '"u64::MAX"' U64Max = u64::MAX, } #[repr(i64)] pub enum I64 { - // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.value" '"-9223372036854775808"' - // @is "$.index[*][?(@.name=='I64Min')].inner.variant_inner.expr" '"i64::MIN"' + // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.value" '"-9223372036854775808"' + // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.expr" '"i64::MIN"' I64Min = i64::MIN, - // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.value" '"9223372036854775807"' - // @is "$.index[*][?(@.name=='I64Max')].inner.variant_inner.expr" '"i64::MAX"' + // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.value" '"9223372036854775807"' + // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.expr" '"i64::MAX"' I64Max = i64::MAX, } #[repr(u128)] pub enum U128 { - // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='U128Min')].inner.variant_inner.expr" '"u128::MIN"' + // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.expr" '"u128::MIN"' U128Min = u128::MIN, - // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.value" '"340282366920938463463374607431768211455"' - // @is "$.index[*][?(@.name=='U128Max')].inner.variant_inner.expr" '"u128::MAX"' + // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.value" '"340282366920938463463374607431768211455"' + // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.expr" '"u128::MAX"' U128Max = u128::MAX, } #[repr(i128)] pub enum I128 { - // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.value" '"-170141183460469231731687303715884105728"' - // @is "$.index[*][?(@.name=='I128Min')].inner.variant_inner.expr" '"i128::MIN"' + // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.value" '"-170141183460469231731687303715884105728"' + // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.expr" '"i128::MIN"' I128Min = i128::MIN, - // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.value" '"170141183460469231731687303715884105727"' - // @is "$.index[*][?(@.name=='I128Max')].inner.variant_inner.expr" '"i128::MAX"' + // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.value" '"170141183460469231731687303715884105727"' + // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.expr" '"i128::MAX"' I128Max = i128::MAX, } diff --git a/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs index 3417baa0760..6889b305ffb 100644 --- a/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs +++ b/src/test/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs @@ -1,15 +1,15 @@ #[repr(u32)] pub enum Foo { - // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.value" '"0"' - // @is "$.index[*][?(@.name=='Basic')].inner.variant_inner.expr" '"0"' + // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.value" '"0"' + // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.expr" '"0"' Basic = 0, - // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.value" '"10"' - // @is "$.index[*][?(@.name=='Suffix')].inner.variant_inner.expr" '"10u32"' + // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.value" '"10"' + // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.expr" '"10u32"' Suffix = 10u32, - // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.value" '"100"' - // @is "$.index[*][?(@.name=='Underscore')].inner.variant_inner.expr" '"1_0_0"' + // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.value" '"100"' + // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.expr" '"1_0_0"' Underscore = 1_0_0, - // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.value" '"1000"' - // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant_inner.expr" '"1_0_0_0u32"' + // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.value" '"1000"' + // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.expr" '"1_0_0_0u32"' SuffixUnderscore = 1_0_0_0u32, } diff --git a/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs index 6af944a2219..6a4f54de617 100644 --- a/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs +++ b/src/test/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs @@ -1,10 +1,10 @@ pub enum Foo { - // @is "$.index[*][?(@.name=='Has')].inner.variant_inner" '{"expr":"0", "value":"0"}' + // @is "$.index[*][?(@.name=='Has')].inner.discriminant" '{"expr":"0", "value":"0"}' Has = 0, - // @is "$.index[*][?(@.name=='Doesnt')].inner.variant_inner" null + // @is "$.index[*][?(@.name=='Doesnt')].inner.discriminant" null Doesnt, - // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant_inner" null + // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.discriminant" null AlsoDoesnt, - // @is "$.index[*][?(@.name=='AlsoHas')].inner.variant_inner" '{"expr":"44", "value":"44"}' + // @is "$.index[*][?(@.name=='AlsoHas')].inner.discriminant" '{"expr":"44", "value":"44"}' AlsoHas = 44, } diff --git a/src/test/rustdoc-json/enums/discriminant/struct.rs b/src/test/rustdoc-json/enums/discriminant/struct.rs new file mode 100644 index 00000000000..e91a632a3b3 --- /dev/null +++ b/src/test/rustdoc-json/enums/discriminant/struct.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength + +#[repr(i32)] +// @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(i32)]"]' +pub enum Foo { + // @is "$.index[*][?(@.name=='Struct')].inner.discriminant" null + // @count "$.index[*][?(@.name=='Struct')].inner.kind.struct.fields[*]" 0 + Struct {}, + // @is "$.index[*][?(@.name=='StructWithDiscr')].inner.discriminant" '{"expr": "42", "value": "42"}' + // @count "$.index[*][?(@.name=='StructWithDiscr')].inner.kind.struct.fields[*]" 1 + StructWithDiscr { x: i32 } = 42, + // @is "$.index[*][?(@.name=='StructWithHexDiscr')].inner.discriminant" '{"expr": "0x42", "value": "66"}' + // @count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.kind.struct.fields[*]" 2 + StructWithHexDiscr { x: i32, y: bool } = 0x42, +} diff --git a/src/test/rustdoc-json/enums/discriminant/tuple.rs b/src/test/rustdoc-json/enums/discriminant/tuple.rs new file mode 100644 index 00000000000..b94d5739eab --- /dev/null +++ b/src/test/rustdoc-json/enums/discriminant/tuple.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength + +#[repr(u32)] +// @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(u32)]"]' +pub enum Foo { + // @is "$.index[*][?(@.name=='Tuple')].inner.discriminant" null + // @count "$.index[*][?(@.name=='Tuple')].inner.kind.tuple[*]" 0 + Tuple(), + // @is "$.index[*][?(@.name=='TupleWithDiscr')].inner.discriminant" '{"expr": "1", "value": "1"}' + // @count "$.index[*][?(@.name=='TupleWithDiscr')].inner.kind.tuple[*]" 1 + TupleWithDiscr(i32) = 1, + // @is "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.discriminant" '{"expr": "0b10", "value": "2"}' + // @count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.kind.tuple[*]" 2 + TupleWithBinDiscr(i32, i32) = 0b10, +} diff --git a/src/test/rustdoc-json/enums/field_hidden.rs b/src/test/rustdoc-json/enums/field_hidden.rs index e6310cc3b99..78a05431472 100644 --- a/src/test/rustdoc-json/enums/field_hidden.rs +++ b/src/test/rustdoc-json/enums/field_hidden.rs @@ -5,8 +5,8 @@ // @has "$.index[*][?(@.name=='ParseError')]" // @has "$.index[*][?(@.name=='UnexpectedEndTag')]" -// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_kind" '"tuple"' -// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant_inner" [null] +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.kind.tuple" [null] +// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.discriminant" null pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), diff --git a/src/test/rustdoc-json/enums/kind.rs b/src/test/rustdoc-json/enums/kind.rs index e9ea3ae23c2..1787a859c8b 100644 --- a/src/test/rustdoc-json/enums/kind.rs +++ b/src/test/rustdoc-json/enums/kind.rs @@ -5,27 +5,22 @@ pub enum Foo { // @set Unit = "$.index[*][?(@.name=='Unit')].id" - // @is "$.index[*][?(@.name=='Unit')].inner.variant_kind" '"plain"' - // @is "$.index[*][?(@.name=='Unit')].inner.variant_inner" null + // @is "$.index[*][?(@.name=='Unit')].inner.kind" '"plain"' Unit, // @set Named = "$.index[*][?(@.name=='Named')].id" - // @is "$.index[*][?(@.name=='Named')].inner.variant_kind" '"struct"' - // @is "$.index[*][?(@.name=='Named')].inner.variant_inner" '{"fields": [], "fields_stripped": false}' + // @is "$.index[*][?(@.name=='Named')].inner.kind.struct" '{"fields": [], "fields_stripped": false}' Named {}, // @set Tuple = "$.index[*][?(@.name=='Tuple')].id" - // @is "$.index[*][?(@.name=='Tuple')].inner.variant_kind" '"tuple"' - // @is "$.index[*][?(@.name=='Tuple')].inner.variant_inner" [] + // @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" [] Tuple(), // @set NamedField = "$.index[*][?(@.name=='NamedField')].id" // @set x = "$.index[*][?(@.name=='x' && @.kind=='struct_field')].id" - // @is "$.index[*][?(@.name=='NamedField')].inner.variant_kind" '"struct"' - // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields[*]" $x - // @is "$.index[*][?(@.name=='NamedField')].inner.variant_inner.fields_stripped" false + // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields[*]" $x + // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields_stripped" false NamedField { x: i32 }, // @set TupleField = "$.index[*][?(@.name=='TupleField')].id" - // @is "$.index[*][?(@.name=='TupleField')].inner.variant_kind" '"tuple"' // @set tup_field = "$.index[*][?(@.name=='0' && @.kind=='struct_field')].id" - // @is "$.index[*][?(@.name=='TupleField')].inner.variant_inner[*]" $tup_field + // @is "$.index[*][?(@.name=='TupleField')].inner.kind.tuple[*]" $tup_field TupleField(i32), } diff --git a/src/test/rustdoc-json/enums/struct_field_hidden.rs b/src/test/rustdoc-json/enums/struct_field_hidden.rs index f612a34a492..de939cde2e7 100644 --- a/src/test/rustdoc-json/enums/struct_field_hidden.rs +++ b/src/test/rustdoc-json/enums/struct_field_hidden.rs @@ -9,9 +9,8 @@ pub enum Foo { // @set y = "$.index[*][?(@.name=='y')].id" y: i32, }, - // @is "$.index[*][?(@.name=='Variant')].inner.variant_kind" '"struct"' - // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields_stripped" true - // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[0]" $b - // @is "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[1]" $y - // @count "$.index[*][?(@.name=='Variant')].inner.variant_inner.fields[*]" 2 + // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields_stripped" true + // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[0]" $b + // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[1]" $y + // @count "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[*]" 2 } diff --git a/src/test/rustdoc-json/enums/tuple_fields_hidden.rs b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs index f546eaa0d17..70bfbb81826 100644 --- a/src/test/rustdoc-json/enums/tuple_fields_hidden.rs +++ b/src/test/rustdoc-json/enums/tuple_fields_hidden.rs @@ -14,61 +14,50 @@ // @set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id" pub enum EnumWithStrippedTupleVariants { - // @is "$.index[*][?(@.name=='None')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='None')].inner.variant_inner[*]" 0 + // @count "$.index[*][?(@.name=='None')].inner.kind.tuple[*]" 0 None(), - // @is "$.index[*][?(@.name=='One')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='One')].inner.variant_inner[*]" 1 - // @is "$.index[*][?(@.name=='One')].inner.variant_inner[0]" $1.1.0 + // @count "$.index[*][?(@.name=='One')].inner.kind.tuple[*]" 1 + // @is "$.index[*][?(@.name=='One')].inner.kind.tuple[0]" $1.1.0 One(/** 1.1.0*/ bool), - // @is "$.index[*][?(@.name=='OneHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[*]" 1 - // @is "$.index[*][?(@.name=='OneHidden')].inner.variant_inner[0]" null + // @count "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[*]" 1 + // @is "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[0]" null OneHidden(#[doc(hidden)] bool), - // @is "$.index[*][?(@.name=='Two')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Two')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='Two')].inner.variant_inner[0]" $2.1.0 - // @is "$.index[*][?(@.name=='Two')].inner.variant_inner[1]" $2.1.1 + // @count "$.index[*][?(@.name=='Two')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='Two')].inner.kind.tuple[0]" $2.1.0 + // @is "$.index[*][?(@.name=='Two')].inner.kind.tuple[1]" $2.1.1 Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool), - // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[0]" null - // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant_inner[1]" $2.2.1 + // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[0]" null + // @is "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[1]" $2.2.1 TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool), - // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[0]" $2.3.0 - // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant_inner[1]" null + // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[0]" $2.3.0 + // @is "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[1]" null TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool), - // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[*]" 2 - // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[0]" null - // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant_inner[1]" null + // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[*]" 2 + // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[0]" null + // @is "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[1]" null TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool), - // @is "$.index[*][?(@.name=='Three1')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Three1')].inner.variant_inner[*]" 3 - // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[0]" null - // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[1]" $3.1.1 - // @is "$.index[*][?(@.name=='Three1')].inner.variant_inner[2]" $3.1.2 + // @count "$.index[*][?(@.name=='Three1')].inner.kind.tuple[*]" 3 + // @is "$.index[*][?(@.name=='Three1')].inner.kind.tuple[0]" null + // @is "$.index[*][?(@.name=='Three1')].inner.kind.tuple[1]" $3.1.1 + // @is "$.index[*][?(@.name=='Three1')].inner.kind.tuple[2]" $3.1.2 Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool), - // @is "$.index[*][?(@.name=='Three2')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Three2')].inner.variant_inner[*]" 3 - // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[0]" $3.2.0 - // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[1]" null - // @is "$.index[*][?(@.name=='Three2')].inner.variant_inner[2]" $3.2.2 + // @count "$.index[*][?(@.name=='Three2')].inner.kind.tuple[*]" 3 + // @is "$.index[*][?(@.name=='Three2')].inner.kind.tuple[0]" $3.2.0 + // @is "$.index[*][?(@.name=='Three2')].inner.kind.tuple[1]" null + // @is "$.index[*][?(@.name=='Three2')].inner.kind.tuple[2]" $3.2.2 Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool), - // @is "$.index[*][?(@.name=='Three3')].inner.variant_kind" '"tuple"' - // @count "$.index[*][?(@.name=='Three3')].inner.variant_inner[*]" 3 - // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[0]" $3.3.0 - // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[1]" $3.3.1 - // @is "$.index[*][?(@.name=='Three3')].inner.variant_inner[2]" null + // @count "$.index[*][?(@.name=='Three3')].inner.kind.tuple[*]" 3 + // @is "$.index[*][?(@.name=='Three3')].inner.kind.tuple[0]" $3.3.0 + // @is "$.index[*][?(@.name=='Three3')].inner.kind.tuple[1]" $3.3.1 + // @is "$.index[*][?(@.name=='Three3')].inner.kind.tuple[2]" null Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool), } - // @is "$.index[*][?(@.docs=='1.1.0')].name" '"0"' // @is "$.index[*][?(@.docs=='2.1.0')].name" '"0"' // @is "$.index[*][?(@.docs=='2.1.1')].name" '"1"' diff --git a/src/test/rustdoc-json/enums/variant_struct.rs b/src/test/rustdoc-json/enums/variant_struct.rs index 23b854d8d17..bc870c502a0 100644 --- a/src/test/rustdoc-json/enums/variant_struct.rs +++ b/src/test/rustdoc-json/enums/variant_struct.rs @@ -1,11 +1,10 @@ // @is "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\" // @is "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\" pub enum EnumStruct { - // @is "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\" // @is "$.index[*][?(@.name=='x')].kind" \"struct_field\" + // @set x = "$.index[*][?(@.name=='x')].id" // @is "$.index[*][?(@.name=='y')].kind" \"struct_field\" - VariantS { - x: u32, - y: String, - }, + // @set y = "$.index[*][?(@.name=='y')].id" + // @ismany "$.index[*][?(@.name=='VariantS')].inner.kind.struct.fields[*]" $x $y + VariantS { x: u32, y: String }, } diff --git a/src/test/rustdoc-json/enums/variant_tuple_struct.rs b/src/test/rustdoc-json/enums/variant_tuple_struct.rs index b71ec47a804..d1207bbfb18 100644 --- a/src/test/rustdoc-json/enums/variant_tuple_struct.rs +++ b/src/test/rustdoc-json/enums/variant_tuple_struct.rs @@ -1,8 +1,10 @@ // @is "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\" // @is "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\" pub enum EnumTupleStruct { - // @is "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\" // @is "$.index[*][?(@.name=='0')].kind" \"struct_field\" + // @set f0 = "$.index[*][?(@.name=='0')].id" // @is "$.index[*][?(@.name=='1')].kind" \"struct_field\" + // @set f1 = "$.index[*][?(@.name=='1')].id" + // @ismany "$.index[*][?(@.name=='VariantA')].inner.kind.tuple[*]" $f0 $f1 VariantA(u32, String), } diff --git a/src/test/rustdoc-ui/issue-105334.rs b/src/test/rustdoc-ui/issue-105334.rs new file mode 100644 index 00000000000..ee1adc6a029 --- /dev/null +++ b/src/test/rustdoc-ui/issue-105334.rs @@ -0,0 +1,2 @@ +impl Vec< br##"*.."## > {} +//~^ ERROR diff --git a/src/test/rustdoc-ui/issue-105334.stderr b/src/test/rustdoc-ui/issue-105334.stderr new file mode 100644 index 00000000000..e163bb4db9e --- /dev/null +++ b/src/test/rustdoc-ui/issue-105334.stderr @@ -0,0 +1,9 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/issue-105334.rs:1:11 + | +LL | impl Vec< br##"*.."## > {} + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/rustdoc-ui/issue-105737.rs b/src/test/rustdoc-ui/issue-105737.rs new file mode 100644 index 00000000000..154f069d8ff --- /dev/null +++ b/src/test/rustdoc-ui/issue-105737.rs @@ -0,0 +1,4 @@ +impl Vec<lol> {} +//~^ ERROR + +pub fn lol() {} diff --git a/src/test/rustdoc-ui/issue-105737.stderr b/src/test/rustdoc-ui/issue-105737.stderr new file mode 100644 index 00000000000..2dd9beb17da --- /dev/null +++ b/src/test/rustdoc-ui/issue-105737.stderr @@ -0,0 +1,12 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/issue-105737.rs:1:10 + | +LL | impl Vec<lol> {} + | ^^^ + | + = help: `lol` is a function item, not a type + = help: function item types cannot be named directly + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/rustdoc-ui/issue-105742.rs b/src/test/rustdoc-ui/issue-105742.rs new file mode 100644 index 00000000000..cb1de7433cf --- /dev/null +++ b/src/test/rustdoc-ui/issue-105742.rs @@ -0,0 +1,40 @@ +// compile-flags: -Znormalize-docs + +use std::ops::Index; + +pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR + let _ = s; +} + +pub trait SVec: Index< + <Self as SVec>::Item, +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR +//~^^^^ ERROR + Output = <Index<<Self as SVec>::Item, +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR +//~^^^^ ERROR + Output = <Self as SVec>::Item> as SVec>::Item, +//~^ ERROR +//~^^ ERROR +//~^^^ ERROR +//~^^^^ ERROR +//~^^^^^ ERROR +//~^^^^^^ ERROR +//~^^^^^^^ ERROR +//~^^^^^^^^ ERROR +> { + type Item<'a, T>; + + fn len(&self) -> <Self as SVec>::Item; + //~^ ERROR + //~^^ ERROR + //~^^^ ERROR + //~^^^^ ERROR +} diff --git a/src/test/rustdoc-ui/issue-105742.stderr b/src/test/rustdoc-ui/issue-105742.stderr new file mode 100644 index 00000000000..cc101b7ff37 --- /dev/null +++ b/src/test/rustdoc-ui/issue-105742.stderr @@ -0,0 +1,385 @@ +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | <Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | <Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Index<<Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Index<<Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item<T>> as SVec>::Item, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:5:40 + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<'_> = T, Output = T>) { + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:5:40 + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item<T> = T, Output = T>) { + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | <Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:13:21 + | +LL | <Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | <Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Index<<Self as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:18:37 + | +LL | Output = <Index<<Self as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Index<<Self as SVec>::Item<T>, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item<'a>> as SVec>::Item, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:30 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item<T>> as SVec>::Item, + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<'a>, + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:23:46 + | +LL | Output = <Self as SVec>::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = <Self as SVec>::Item> as SVec>::Item<T>, + | ~~~~~~~ + +error[E0038]: the trait `SVec` cannot be made into an object + --> $DIR/issue-105742.rs:5:31 + | +LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-105742.rs:12:17 + | +LL | pub trait SVec: Index< + | ____________----__^ + | | | + | | this trait cannot be made into an object... +LL | | <Self as SVec>::Item, +LL | | +LL | | +... | +LL | |/ Output = <Index<<Self as SVec>::Item, +LL | || +LL | || +LL | || +LL | || +LL | || Output = <Self as SVec>::Item> as SVec>::Item, + | ||_________________________________________________^ ...because it uses `Self` as a type parameter +... | +LL | | +LL | | > { + | |__^ ...because it uses `Self` as a type parameter + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn len(&self) -> <Self as SVec>::Item<'_>; + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | fn len(&self) -> <Self as SVec>::Item<T>; + | ~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | fn len(&self) -> <Self as SVec>::Item<'_>; + | ~~~~~~~~ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:35:38 + | +LL | fn len(&self) -> <Self as SVec>::Item; + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:33:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | fn len(&self) -> <Self as SVec>::Item<T>; + | ~~~~~~~ + +error: aborting due to 23 previous errors + +Some errors have detailed explanations: E0038, E0107. +For more information about an error, try `rustc --explain E0038`. diff --git a/src/test/rustdoc-ui/issue-106213.rs b/src/test/rustdoc-ui/issue-106213.rs new file mode 100644 index 00000000000..6d51846b7d0 --- /dev/null +++ b/src/test/rustdoc-ui/issue-106213.rs @@ -0,0 +1,7 @@ +// compile-flags: --document-private-items +// edition:2021 + +fn use_avx() -> dyn { + //~^ ERROR at least one trait is required for an object type + !( ident_error ) +} diff --git a/src/test/rustdoc-ui/issue-106213.stderr b/src/test/rustdoc-ui/issue-106213.stderr new file mode 100644 index 00000000000..0a4ff69bafb --- /dev/null +++ b/src/test/rustdoc-ui/issue-106213.stderr @@ -0,0 +1,9 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/issue-106213.rs:4:17 + | +LL | fn use_avx() -> dyn { + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0224`. diff --git a/src/test/rustdoc-ui/issue-106226.rs b/src/test/rustdoc-ui/issue-106226.rs new file mode 100644 index 00000000000..71b497a9adc --- /dev/null +++ b/src/test/rustdoc-ui/issue-106226.rs @@ -0,0 +1,3 @@ +// This is a regression test for <https://github.com/rust-lang/rust/issues/106226>. +type F = [_; ()]; +//~^ ERROR diff --git a/src/test/rustdoc-ui/issue-106226.stderr b/src/test/rustdoc-ui/issue-106226.stderr new file mode 100644 index 00000000000..2beffbc125b --- /dev/null +++ b/src/test/rustdoc-ui/issue-106226.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-106226.rs:2:14 + | +LL | type F = [_; ()]; + | ^^ expected `usize`, found `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/rustdoc-ui/issue-96287.rs b/src/test/rustdoc-ui/issue-96287.rs new file mode 100644 index 00000000000..8d8b4456e63 --- /dev/null +++ b/src/test/rustdoc-ui/issue-96287.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] + +pub trait TraitWithAssoc { + type Assoc; +} + +pub type Foo<V> = impl Trait<V::Assoc>; +//~^ ERROR +//~^^ ERROR + +pub trait Trait<U> {} + +impl<W> Trait<W> for () {} + +pub fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T> { + () +} diff --git a/src/test/rustdoc-ui/issue-96287.stderr b/src/test/rustdoc-ui/issue-96287.stderr new file mode 100644 index 00000000000..0236b9fe647 --- /dev/null +++ b/src/test/rustdoc-ui/issue-96287.stderr @@ -0,0 +1,15 @@ +error[E0220]: associated type `Assoc` not found for `V` + --> $DIR/issue-96287.rs:7:33 + | +LL | pub type Foo<V> = impl Trait<V::Assoc>; + | ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc` + +error[E0220]: associated type `Assoc` not found for `V` + --> $DIR/issue-96287.rs:7:33 + | +LL | pub type Foo<V> = impl Trait<V::Assoc>; + | ^^^^^ there is a similarly named associated type `Assoc` in the trait `TraitWithAssoc` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 0277501de09..af765c51ace 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -59,7 +59,7 @@ pub async fn const_generics<const N: usize>(_: impl Trait<N>) {} // @has - '//pre[@class="rust fn"]' 'pub async fn elided(foo: &str) -> &str' pub async fn elided(foo: &str) -> &str {} // This should really be shown as written, but for implementation reasons it's difficult. -// See `impl Clean for TyKind::Rptr`. +// See `impl Clean for TyKind::Ref`. // @has async_fn/fn.user_elided.html // @has - '//pre[@class="rust fn"]' 'pub async fn user_elided(foo: &str) -> &str' pub async fn user_elided(foo: &'_ str) -> &str {} diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs index a4b911878e0..1c376f59e51 100644 --- a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs +++ b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs @@ -6,6 +6,11 @@ extern crate rustc_macros; extern crate rustc_serialize; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::{Decodable, Encodable, Encoder}; diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs index 580c85f9b78..844d40f2ecd 100644 --- a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs @@ -8,6 +8,11 @@ extern crate rustc_macros; extern crate rustc_serialize; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::{Decodable, Encodable, Encoder}; diff --git a/src/test/ui-fulldeps/deriving-global.rs b/src/test/ui-fulldeps/deriving-global.rs index 921767af981..214bb4368ff 100644 --- a/src/test/ui-fulldeps/deriving-global.rs +++ b/src/test/ui-fulldeps/deriving-global.rs @@ -5,6 +5,11 @@ extern crate rustc_macros; extern crate rustc_serialize; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + mod submod { use rustc_macros::{Decodable, Encodable}; diff --git a/src/test/ui-fulldeps/deriving-hygiene.rs b/src/test/ui-fulldeps/deriving-hygiene.rs index 8486b8b6e48..e1084a08fec 100644 --- a/src/test/ui-fulldeps/deriving-hygiene.rs +++ b/src/test/ui-fulldeps/deriving-hygiene.rs @@ -7,6 +7,11 @@ extern crate rustc_serialize; use rustc_macros::{Decodable, Encodable}; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + pub const other: u8 = 1; pub const f: u8 = 1; pub const d: u8 = 1; diff --git a/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs b/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs index 187f9a24a90..ffad80171da 100644 --- a/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs +++ b/src/test/ui-fulldeps/dropck_tarena_sound_drop.rs @@ -14,6 +14,11 @@ extern crate rustc_arena; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_arena::TypedArena; trait HasId { fn count(&self) -> usize; } diff --git a/src/test/ui-fulldeps/empty-struct-braces-derive.rs b/src/test/ui-fulldeps/empty-struct-braces-derive.rs index 6e5eb54629c..10e8beaa7b1 100644 --- a/src/test/ui-fulldeps/empty-struct-braces-derive.rs +++ b/src/test/ui-fulldeps/empty-struct-braces-derive.rs @@ -6,6 +6,11 @@ extern crate rustc_macros; extern crate rustc_serialize; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_macros::{Decodable, Encodable}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)] diff --git a/src/test/ui-fulldeps/issue-14021.rs b/src/test/ui-fulldeps/issue-14021.rs index 215dfaed7ab..309b5c4a03d 100644 --- a/src/test/ui-fulldeps/issue-14021.rs +++ b/src/test/ui-fulldeps/issue-14021.rs @@ -7,6 +7,11 @@ extern crate rustc_macros; extern crate rustc_serialize; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::{Decodable, Encodable, Encoder}; diff --git a/src/test/ui-fulldeps/missing-rustc-driver-error.rs b/src/test/ui-fulldeps/missing-rustc-driver-error.rs new file mode 100644 index 00000000000..654cd6f6dc9 --- /dev/null +++ b/src/test/ui-fulldeps/missing-rustc-driver-error.rs @@ -0,0 +1,11 @@ +// Test that we get the following hint when trying to use a compiler crate without rustc_driver. +// error-pattern: try adding `extern crate rustc_driver;` at the top level of this crate +// compile-flags: --emit link +// The exactly list of required crates depends on the target. as such only test Unix targets. +// only-unix + +#![feature(rustc_private)] + +extern crate rustc_serialize; + +fn main() {} diff --git a/src/test/ui-fulldeps/missing-rustc-driver-error.stderr b/src/test/ui-fulldeps/missing-rustc-driver-error.stderr new file mode 100644 index 00000000000..ad03ba0103c --- /dev/null +++ b/src/test/ui-fulldeps/missing-rustc-driver-error.stderr @@ -0,0 +1,24 @@ +error: crate `rustc_serialize` required to be available in rlib format, but was not found in this form + | + = help: try adding `extern crate rustc_driver;` at the top level of this crate + +error: crate `smallvec` required to be available in rlib format, but was not found in this form + +error: crate `thin_vec` required to be available in rlib format, but was not found in this form + +error: crate `indexmap` required to be available in rlib format, but was not found in this form + +error: crate `hashbrown` required to be available in rlib format, but was not found in this form + +error: crate `ahash` required to be available in rlib format, but was not found in this form + +error: crate `once_cell` required to be available in rlib format, but was not found in this form + +error: crate `getrandom` required to be available in rlib format, but was not found in this form + +error: crate `cfg_if` required to be available in rlib format, but was not found in this form + +error: crate `libc` required to be available in rlib format, but was not found in this form + +error: aborting due to 10 previous errors + diff --git a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs index bb246de0e57..ff1be080415 100644 --- a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -10,6 +10,11 @@ extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_parse::new_parser_from_file; use rustc_session::parse::ParseSess; use rustc_span::source_map::FilePathMapping; diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index a93ba87470a..6dbabc8eb34 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -27,6 +27,11 @@ extern crate rustc_session; extern crate rustc_span; extern crate thin_vec; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_ast::mut_visit::{self, visit_clobber, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::*; diff --git a/src/test/ui-fulldeps/regions-mock-tcx.rs b/src/test/ui-fulldeps/regions-mock-tcx.rs index 30e62723240..63975ef62c5 100644 --- a/src/test/ui-fulldeps/regions-mock-tcx.rs +++ b/src/test/ui-fulldeps/regions-mock-tcx.rs @@ -14,6 +14,11 @@ extern crate rustc_arena; extern crate libc; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use TypeStructure::{TypeInt, TypeFunction}; use AstKind::{ExprInt, ExprVar, ExprLambda}; use rustc_arena::TypedArena; diff --git a/src/test/ui-fulldeps/rustc_encodable_hygiene.rs b/src/test/ui-fulldeps/rustc_encodable_hygiene.rs index 452110a65e4..509a6b1d22c 100644 --- a/src/test/ui-fulldeps/rustc_encodable_hygiene.rs +++ b/src/test/ui-fulldeps/rustc_encodable_hygiene.rs @@ -6,6 +6,11 @@ extern crate rustc_macros; #[allow(dead_code)] extern crate rustc_serialize; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use rustc_macros::{Decodable, Encodable}; #[derive(Decodable, Encodable, Debug)] diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr index dd3665f22ac..59192a1ecc3 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -3,10 +3,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______- arguments to this function are incorrect @@ -29,10 +26,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: &Layout, LL | || ) -> () | ||_______^ expected `!`, found `()` diff --git a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr index 2673ee9f937..7d23c2fc05a 100644 --- a/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr +++ b/src/test/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr @@ -3,10 +3,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: Layout, LL | || ) { | ||_- arguments to this function are incorrect @@ -36,10 +33,7 @@ error[E0308]: mismatched types | LL | #[alloc_error_handler] | ---------------------- in this procedural macro expansion -LL | fn oom( - | __^ - | | _| - | || +LL | // fn oom( LL | || info: Layout, LL | || ) { | ||_^ expected `!`, found `()` diff --git a/src/test/ui/argument-suggestions/extern-fn-arg-names.rs b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs new file mode 100644 index 00000000000..6c925a3d653 --- /dev/null +++ b/src/test/ui/argument-suggestions/extern-fn-arg-names.rs @@ -0,0 +1,9 @@ +extern "Rust" { + fn dstfn(src: i32, dst: err); + //~^ ERROR cannot find type `err` in this scope +} + +fn main() { + dstfn(1); + //~^ ERROR this function takes 2 arguments but 1 argument was supplied +} diff --git a/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr b/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr new file mode 100644 index 00000000000..f6bc84c1203 --- /dev/null +++ b/src/test/ui/argument-suggestions/extern-fn-arg-names.stderr @@ -0,0 +1,26 @@ +error[E0412]: cannot find type `err` in this scope + --> $DIR/extern-fn-arg-names.rs:2:29 + | +LL | fn dstfn(src: i32, dst: err); + | ^^^ not found in this scope + +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/extern-fn-arg-names.rs:7:5 + | +LL | dstfn(1); + | ^^^^^--- an argument is missing + | +note: function defined here + --> $DIR/extern-fn-arg-names.rs:2:8 + | +LL | fn dstfn(src: i32, dst: err); + | ^^^^^ +help: provide the argument + | +LL | dstfn(1, /* dst */); + | ~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0061, E0412. +For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/array-slice-vec/slice-mut-2.stderr b/src/test/ui/array-slice-vec/slice-mut-2.stderr index bad0268772b..5b040d3e4d3 100644 --- a/src/test/ui/array-slice-vec/slice-mut-2.stderr +++ b/src/test/ui/array-slice-vec/slice-mut-2.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/slice-mut-2.rs:7:18 | -LL | let x: &[isize] = &[1, 2, 3, 4, 5]; - | ---------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4, 5]` -... LL | let _ = &mut x[2..4]; | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let x: &[isize] = &mut [1, 2, 3, 4, 5]; + | ~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/asm/aarch64/interpolated-idents.stderr b/src/test/ui/asm/aarch64/interpolated-idents.stderr index 2df17f2e036..f6c50c2e1fd 100644 --- a/src/test/ui/asm/aarch64/interpolated-idents.stderr +++ b/src/test/ui/asm/aarch64/interpolated-idents.stderr @@ -30,12 +30,7 @@ error: asm outputs are not allowed with the `noreturn` option LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ... -LL | m!(in out lateout inout inlateout const sym - | _____- - | |_____| - | |_____| - | |_____| - | | +LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack options); | | - diff --git a/src/test/ui/asm/aarch64/type-check-2-2.rs b/src/test/ui/asm/aarch64/type-check-2-2.rs index 0ce1f1d8f7f..89f2b3bb7d0 100644 --- a/src/test/ui/asm/aarch64/type-check-2-2.rs +++ b/src/test/ui/asm/aarch64/type-check-2-2.rs @@ -25,12 +25,10 @@ fn main() { // Outputs require mutable places - let v: Vec<u64> = vec![0, 1, 2]; + let v: Vec<u64> = vec![0, 1, 2]; //~ ERROR cannot borrow `v` as mutable asm!("{}", in(reg) v[0]); asm!("{}", out(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable asm!("{}", inout(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable // Sym operands must point to a function or static } diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr index eef16a165a8..41f7c01dc82 100644 --- a/src/test/ui/asm/aarch64/type-check-2-2.stderr +++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr @@ -25,24 +25,22 @@ LL | let mut y: u64 = 0; | +++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-2-2.rs:30:29 + --> $DIR/type-check-2-2.rs:28:13 | LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` + | ^ not mutable LL | asm!("{}", in(reg) v[0]); LL | asm!("{}", out(reg) v[0]); - | ^ cannot borrow as mutable - -error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-2-2.rs:32:31 - | -LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` -... + | - cannot borrow as mutable LL | asm!("{}", inout(reg) v[0]); - | ^ cannot borrow as mutable + | - cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec<u64> = vec![0, 1, 2]; + | +++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0381, E0596. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/asm/x86_64/interpolated-idents.stderr b/src/test/ui/asm/x86_64/interpolated-idents.stderr index 6ac2ac5a779..80a8c8c77cf 100644 --- a/src/test/ui/asm/x86_64/interpolated-idents.stderr +++ b/src/test/ui/asm/x86_64/interpolated-idents.stderr @@ -30,12 +30,7 @@ error: asm outputs are not allowed with the `noreturn` option LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ... -LL | m!(in out lateout inout inlateout const sym - | _____- - | |_____| - | |_____| - | |_____| - | | +LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); | | - diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs index 8198df91095..1d579ccc90e 100644 --- a/src/test/ui/asm/x86_64/type-check-5.rs +++ b/src/test/ui/asm/x86_64/type-check-5.rs @@ -22,11 +22,10 @@ fn main() { // Outputs require mutable places let v: Vec<u64> = vec![0, 1, 2]; + //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable asm!("{}", in(reg) v[0]); asm!("{}", out(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable asm!("{}", inout(reg) v[0]); - //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable // Sym operands must point to a function or static diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr index bd90461e52c..7970e76d6a1 100644 --- a/src/test/ui/asm/x86_64/type-check-5.stderr +++ b/src/test/ui/asm/x86_64/type-check-5.stderr @@ -25,24 +25,22 @@ LL | let mut y: u64 = 0; | +++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-5.rs:26:29 + --> $DIR/type-check-5.rs:24:13 | LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` -LL | asm!("{}", in(reg) v[0]); -LL | asm!("{}", out(reg) v[0]); - | ^ cannot borrow as mutable - -error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable - --> $DIR/type-check-5.rs:28:31 - | -LL | let v: Vec<u64> = vec![0, 1, 2]; - | - help: consider changing this to be mutable: `mut v` + | ^ not mutable ... +LL | asm!("{}", out(reg) v[0]); + | - cannot borrow as mutable LL | asm!("{}", inout(reg) v[0]); - | ^ cannot borrow as mutable + | - cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec<u64> = vec![0, 1, 2]; + | +++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0381, E0596. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/async-await/issue-105501.rs b/src/test/ui/async-await/issue-105501.rs new file mode 100644 index 00000000000..f30d2a9d81a --- /dev/null +++ b/src/test/ui/async-await/issue-105501.rs @@ -0,0 +1,165 @@ +// check-pass +// edition:2018 + +// This is a regression test for https://github.com/rust-lang/rust/issues/105501. +// It was minified from the published `msf-ice:0.2.1` crate which failed in a crater run. +// A faulty compiler was triggering a `higher-ranked lifetime error`: +// +// > could not prove `[async block@...]: Send` + +use mini_futures::Stream; + +fn is_send(_: impl Send) {} + +pub fn main() { + let fut = async { + let mut stream = mini_futures::iter([()]) + .then(|_| async {}) + .map(|_| async { None }) + .buffered() + .filter_map(std::future::ready); + + stream.next().await + }; + + is_send(async move { + let _: Option<()> = fut.await; + }); +} + +// this is a simplified subset of `futures::StreamExt` and related types +mod mini_futures { + use std::future::Future; + use std::pin::Pin; + use std::task::{Context, Poll}; + + pub fn iter<I>(_: I) -> Iter<I::IntoIter> + where + I: IntoIterator, + { + todo!() + } + + pub trait Stream { + type Item; + + fn then<Fut, F>(self, _: F) -> Then<Self, Fut, F> + where + F: FnMut(Self::Item) -> Fut, + Fut: Future, + Self: Sized, + { + todo!() + } + + fn map<T, F>(self, _: F) -> Map<Self, F> + where + F: FnMut(Self::Item) -> T, + Self: Sized, + { + todo!() + } + + fn buffered(self) -> Buffered<Self> + where + Self::Item: Future, + Self: Sized, + { + todo!() + } + + fn filter_map<Fut, T, F>(self, _: F) -> FilterMap<Self, Fut, F> + where + F: FnMut(Self::Item) -> Fut, + Fut: Future<Output = Option<T>>, + Self: Sized, + { + todo!() + } + + fn next(&mut self) -> Next<'_, Self> { + todo!() + } + } + + pub struct Iter<I> { + __: I, + } + impl<I> Stream for Iter<I> + where + I: Iterator, + { + type Item = I::Item; + } + + pub struct Then<St, Fut, F> { + __: (St, Fut, F), + } + impl<St, Fut, F> Stream for Then<St, Fut, F> + where + St: Stream, + F: FnMut(St::Item) -> Fut, + Fut: Future, + { + type Item = Fut::Output; + } + + pub struct Map<St, F> { + __: (St, F), + } + impl<St, F> Stream for Map<St, F> + where + St: Stream, + F: FnMut1<St::Item>, + { + type Item = F::Output; + } + + pub trait FnMut1<A> { + type Output; + } + impl<T, A, R> FnMut1<A> for T + where + T: FnMut(A) -> R, + { + type Output = R; + } + + pub struct Buffered<St> + where + St: Stream, + St::Item: Future, + { + __: (St, St::Item), + } + impl<St> Stream for Buffered<St> + where + St: Stream, + St::Item: Future, + { + type Item = <St::Item as Future>::Output; + } + + pub struct FilterMap<St, Fut, F> { + __: (St, Fut, F), + } + impl<St, Fut, F, T> Stream for FilterMap<St, Fut, F> + where + St: Stream, + F: FnMut1<St::Item, Output = Fut>, + Fut: Future<Output = Option<T>>, + { + type Item = T; + } + + pub struct Next<'a, St: ?Sized> { + __: &'a mut St, + } + impl<St: ?Sized + Stream> Future for Next<'_, St> { + type Output = Option<St::Item>; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> { + todo!() + } + } +} diff --git a/src/test/ui/async-await/issue-61452.stderr b/src/test/ui/async-await/issue-61452.stderr index 2d3bb48e03b..bf504432880 100644 --- a/src/test/ui/async-await/issue-61452.stderr +++ b/src/test/ui/async-await/issue-61452.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/issue-61452.rs:4:5 | -LL | pub async fn f(x: Option<usize>) { - | - help: consider changing this to be mutable: `mut x` LL | x.take(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | pub async fn f(mut x: Option<usize>) { + | +++ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/issue-61452.rs:9:5 diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr index 163053471b5..e58f7454689 100644 --- a/src/test/ui/async-await/issues/issue-61187.stderr +++ b/src/test/ui/async-await/issues/issue-61187.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable --> $DIR/issue-61187.rs:6:5 | -LL | async fn response(data: Vec<u8>) { - | ---- help: consider changing this to be mutable: `mut data` LL | data.reverse(); | ^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | async fn response(mut data: Vec<u8>) { + | +++ error: aborting due to previous error diff --git a/src/test/ui/attributes/issue-105594-invalid-attr-validation.rs b/src/test/ui/attributes/issue-105594-invalid-attr-validation.rs new file mode 100644 index 00000000000..6c68e6b046f --- /dev/null +++ b/src/test/ui/attributes/issue-105594-invalid-attr-validation.rs @@ -0,0 +1,13 @@ +// This checks that the attribute validation ICE in issue #105594 doesn't +// recur. +// +// ignore-thumbv8m.base +#![feature(cmse_nonsecure_entry)] + +fn main() {} + +#[track_caller] //~ ERROR attribute should be applied to a function +static _A: () = (); + +#[cmse_nonsecure_entry] //~ ERROR attribute should be applied to a function +static _B: () = (); //~| ERROR #[cmse_nonsecure_entry]` is only valid for targets diff --git a/src/test/ui/attributes/issue-105594-invalid-attr-validation.stderr b/src/test/ui/attributes/issue-105594-invalid-attr-validation.stderr new file mode 100644 index 00000000000..c6b2d6e7813 --- /dev/null +++ b/src/test/ui/attributes/issue-105594-invalid-attr-validation.stderr @@ -0,0 +1,26 @@ +error[E0739]: attribute should be applied to a function definition + --> $DIR/issue-105594-invalid-attr-validation.rs:9:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | static _A: () = (); + | ------------------- not a function definition + +error: attribute should be applied to a function definition + --> $DIR/issue-105594-invalid-attr-validation.rs:12:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | static _B: () = (); + | ------------------- not a function definition + +error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension + --> $DIR/issue-105594-invalid-attr-validation.rs:12:1 + | +LL | #[cmse_nonsecure_entry] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0739, E0775. +For more information about an error, try `rustc --explain E0739`. diff --git a/src/test/ui/z-crate-attr.rs b/src/test/ui/attributes/z-crate-attr.rs index 1021774fc5f..1021774fc5f 100644 --- a/src/test/ui/z-crate-attr.rs +++ b/src/test/ui/attributes/z-crate-attr.rs diff --git a/src/test/ui/augmented-assignments.rs b/src/test/ui/augmented-assignments.rs index 1b4ac6edcb0..20c7fb3a983 100644 --- a/src/test/ui/augmented-assignments.rs +++ b/src/test/ui/augmented-assignments.rs @@ -19,7 +19,7 @@ fn main() { let y = Int(2); //~^ HELP consider changing this to be mutable - //~| SUGGESTION mut y + //~| SUGGESTION mut y //~ ERROR cannot borrow `y` as mutable, as it is not declared as mutable //~| cannot borrow as mutable += diff --git a/src/test/ui/augmented-assignments.stderr b/src/test/ui/augmented-assignments.stderr index ce555da8975..2910c910d55 100644 --- a/src/test/ui/augmented-assignments.stderr +++ b/src/test/ui/augmented-assignments.stderr @@ -10,11 +10,13 @@ LL | x; error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/augmented-assignments.rs:23:5 | -LL | let y = Int(2); - | - help: consider changing this to be mutable: `mut y` -... LL | y | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut y = Int(2); + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr index 5963dab9f4a..4cc1d821d0a 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13 | -LL | let x = &0; - | -- help: consider changing this to be a mutable reference: `&mut 0` -LL | LL | let q = &raw mut *x; | ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let x = &mut 0; + | ~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13 | -LL | let x = &0 as *const i32; - | -- help: consider changing this to be a mutable pointer: `&mut 0` -LL | LL | let q = &raw mut *x; | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | let x = &mut 0 as *const i32; + | ~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr index 869375cb2c6..a7748209187 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrow-raw-address-of-mutability.rs:5:13 | -LL | let x = 0; - | - help: consider changing this to be mutable: `mut x` LL | let y = &raw mut x; | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 0; + | +++ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrow-raw-address-of-mutability.rs:11:17 @@ -18,13 +21,16 @@ LL | let y = &raw mut x; error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable --> $DIR/borrow-raw-address-of-mutability.rs:21:5 | -LL | let f = || { - | - help: consider changing this to be mutable: `mut f` LL | let y = &raw mut x; | - calling `f` requires mutable binding due to mutable borrow of `x` LL | }; LL | f(); | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = || { + | +++ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:29:17 diff --git a/src/test/ui/borrowck/borrowck-access-permissions.stderr b/src/test/ui/borrowck/borrowck-access-permissions.stderr index e3a35c38a7c..26f3e2bbdb7 100644 --- a/src/test/ui/borrowck/borrowck-access-permissions.stderr +++ b/src/test/ui/borrowck/borrowck-access-permissions.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-access-permissions.rs:9:19 | -LL | let x = 1; - | - help: consider changing this to be mutable: `mut x` -... LL | let _y1 = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 1; + | +++ error[E0596]: cannot borrow immutable static item `static_x` as mutable --> $DIR/borrowck-access-permissions.rs:14:19 @@ -16,37 +18,46 @@ LL | let _y1 = &mut static_x; error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable --> $DIR/borrowck-access-permissions.rs:22:19 | -LL | let box_x = Box::new(1); - | ----- help: consider changing this to be mutable: `mut box_x` -... LL | let _y1 = &mut *box_x; | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut box_x = Box::new(1); + | +++ error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-access-permissions.rs:30:19 | -LL | let ref_x = &x; - | -- help: consider changing this to be a mutable reference: `&mut x` -... LL | let _y1 = &mut *ref_x; | ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let ref_x = &mut x; + | ~~~~~~ error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer --> $DIR/borrowck-access-permissions.rs:39:23 | -LL | let ptr_x : *const _ = &x; - | -- help: consider changing this to be a mutable pointer: `&mut x` -... LL | let _y1 = &mut *ptr_x; | ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | let ptr_x : *const _ = &mut x; + | ~~~~~~ error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference --> $DIR/borrowck-access-permissions.rs:48:18 | -LL | let foo_ref = &foo; - | ---- help: consider changing this to be a mutable reference: `&mut foo` LL | let _y = &mut *foo_ref.f; | ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let foo_ref = &mut foo; + | ~~~~~~~~ error: aborting due to 6 previous errors diff --git a/src/test/ui/borrowck/borrowck-argument.stderr b/src/test/ui/borrowck/borrowck-argument.stderr index d4d646e390c..1c992dfcceb 100644 --- a/src/test/ui/borrowck/borrowck-argument.stderr +++ b/src/test/ui/borrowck/borrowck-argument.stderr @@ -1,34 +1,46 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:10:5 | -LL | fn func(arg: S) { - | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn func(mut arg: S) { + | +++ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:15:9 | -LL | fn method(&self, arg: S) { - | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn method(&self, mut arg: S) { + | +++ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:21:9 | -LL | fn default(&self, arg: S) { - | --- help: consider changing this to be mutable: `mut arg` LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn default(&self, mut arg: S) { + | +++ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/borrowck-argument.rs:32:17 | LL | (|arg: S| { arg.mutate() })(s); - | --- ^^^^^^^^^^^^ cannot borrow as mutable - | | - | help: consider changing this to be mutable: `mut arg` + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | (|mut arg: S| { arg.mutate() })(s); + | +++ error: aborting due to 4 previous errors diff --git a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr index 0475df44744..cbacc87a0e8 100644 --- a/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr +++ b/src/test/ui/borrowck/borrowck-assign-to-andmut-in-aliasable-loc.stderr @@ -1,18 +1,24 @@ error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:9:5 | -LL | fn a(s: &S) { - | -- help: consider changing this to be a mutable reference: `&mut S<'_>` LL | *s.pointer += 1; | ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn a(s: &mut S<'_>) { + | ~~~~~~~~~~ error[E0594]: cannot assign to `*s.pointer`, which is behind a `&` reference --> $DIR/borrowck-assign-to-andmut-in-aliasable-loc.rs:17:5 | -LL | fn c(s: & &mut S) { - | -------- help: consider changing this to be a mutable reference: `&mut &mut S<'_>` LL | *s.pointer += 1; | ^^^^^^^^^^^^^^^ `s` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn c(s: &mut &mut S<'_>) { + | ~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr index 186ecddd6d6..19ef0301a2d 100644 --- a/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr +++ b/src/test/ui/borrowck/borrowck-auto-mut-ref-to-immut-var.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-auto-mut-ref-to-immut-var.rs:15:5 | -LL | let x = Foo { x: 3 }; - | - help: consider changing this to be mutable: `mut x` LL | x.printme(); | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = Foo { x: 3 }; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr index e00d69f89d3..c2351aacdae 100644 --- a/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.stderr @@ -105,10 +105,13 @@ LL | *bar1; error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable --> $DIR/borrowck-borrow-from-owned-ptr.rs:122:16 | -LL | let foo = make_foo(); - | --- help: consider changing this to be mutable: `mut foo` LL | let bar1 = &mut foo.bar1; | ^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = make_foo(); + | +++ error: aborting due to 11 previous errors diff --git a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr index ce5ce56dea2..8fcaaa883b2 100644 --- a/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-from-stack-variable.stderr @@ -105,10 +105,13 @@ LL | *bar1; error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable --> $DIR/borrowck-borrow-from-stack-variable.rs:120:16 | -LL | let foo = make_foo(); - | --- help: consider changing this to be mutable: `mut foo` LL | let bar1 = &mut foo.bar1; | ^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut foo = make_foo(); + | +++ error: aborting due to 11 previous errors diff --git a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr index 237071e16fc..3c28ff56e41 100644 --- a/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-immut-deref-of-box-as-mut.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*a` as mutable, as `a` is not declared as mutable --> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:12:5 | -LL | let a: Box<_> = Box::new(A); - | - help: consider changing this to be mutable: `mut a` LL | a.foo(); | ^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut a: Box<_> = Box::new(A); + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr index c99c0f77982..ce9f7aa050a 100644 --- a/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr +++ b/src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr @@ -20,10 +20,13 @@ LL | **t1 = 22; error[E0596]: cannot borrow `**t0` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:19:26 | -LL | fn foo4(t0: & &mut isize) { - | ------------ help: consider changing this to be a mutable reference: `&mut &mut isize` LL | let x: &mut isize = &mut **t0; | ^^^^^^^^^ `t0` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo4(t0: &mut &mut isize) { + | ~~~~~~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-issue-14498.stderr b/src/test/ui/borrowck/borrowck-issue-14498.stderr index 4c0e46d4531..42a55b7a854 100644 --- a/src/test/ui/borrowck/borrowck-issue-14498.stderr +++ b/src/test/ui/borrowck/borrowck-issue-14498.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `***p`, which is behind a `&` reference --> $DIR/borrowck-issue-14498.rs:16:5 | -LL | let p = &y; - | -- help: consider changing this to be a mutable reference: `&mut y` LL | ***p = 2; | ^^^^^^^^ `p` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let p = &mut y; + | ~~~~~~ error[E0506]: cannot assign to `**y` because it is borrowed --> $DIR/borrowck-issue-14498.rs:25:5 diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr index ecf5382e863..87135f0bb43 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr @@ -9,6 +9,10 @@ LL | let _x = Rc::new(vec![1, 2]).into_iter(); | note: `into_iter` takes ownership of the receiver `self`, which moves value --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | let _x = Rc::new(vec![1, 2]).clone().into_iter(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr index d58548f2204..20528e3f0ee 100644 --- a/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr +++ b/src/test/ui/borrowck/borrowck-mut-addr-of-imm-var.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-mut-addr-of-imm-var.rs:3:25 | -LL | let x: isize = 3; - | - help: consider changing this to be mutable: `mut x` LL | let y: &mut isize = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x: isize = 3; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr index 8e7ffdc6819..8ab472e64c7 100644 --- a/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr +++ b/src/test/ui/borrowck/borrowck-mut-slice-of-imm-vec.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/borrowck-mut-slice-of-imm-vec.rs:7:11 | -LL | let v = vec![1, 2, 3]; - | - help: consider changing this to be mutable: `mut v` LL | write(&mut v); | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v = vec![1, 2, 3]; + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-overloaded-call.stderr b/src/test/ui/borrowck/borrowck-overloaded-call.stderr index ddb63b5ec0f..723b19f4124 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-call.stderr +++ b/src/test/ui/borrowck/borrowck-overloaded-call.stderr @@ -11,11 +11,13 @@ LL | use_mut(sp); error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable --> $DIR/borrowck-overloaded-call.rs:67:5 | -LL | let s = SFnMut { - | - help: consider changing this to be mutable: `mut s` -... LL | s(3); | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut s = SFnMut { + | +++ error[E0382]: use of moved value: `s` --> $DIR/borrowck-overloaded-call.rs:75:5 diff --git a/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr b/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr index 284cab29608..d9590e446c7 100644 --- a/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr +++ b/src/test/ui/borrowck/borrowck-reborrow-from-mut.stderr @@ -105,10 +105,13 @@ LL | use_imm(_bar1); error[E0596]: cannot borrow `foo.bar1` as mutable, as it is behind a `&` reference --> $DIR/borrowck-reborrow-from-mut.rs:88:17 | -LL | fn borrow_mut_from_imm(foo: &Foo) { - | ---- help: consider changing this to be a mutable reference: `&mut Foo` LL | let _bar1 = &mut foo.bar1; | ^^^^^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn borrow_mut_from_imm(foo: &mut Foo) { + | ~~~~~~~~ error: aborting due to 11 previous errors diff --git a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr index e744fc6b54b..5cfd81bd004 100644 --- a/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr +++ b/src/test/ui/borrowck/borrowck-ref-mut-of-imm.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable --> $DIR/borrowck-ref-mut-of-imm.rs:4:12 | -LL | fn destructure(x: Option<isize>) -> isize { - | - help: consider changing this to be mutable: `mut x` -... LL | Some(ref mut v) => *v | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn destructure(mut x: Option<isize>) -> isize { + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr index d46ef126da4..3634676463c 100644 --- a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr +++ b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr @@ -11,10 +11,13 @@ LL | use_mut(g); error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable --> $DIR/borrowck-unboxed-closures.rs:7:5 | -LL | fn b<F:FnMut(isize, isize) -> isize>(f: F) { - | - help: consider changing this to be mutable: `mut f` LL | f(1, 2); | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn b<F:FnMut(isize, isize) -> isize>(mut f: F) { + | +++ error[E0382]: use of moved value: `f` --> $DIR/borrowck-unboxed-closures.rs:12:5 diff --git a/src/test/ui/borrowck/immut-function-arguments.stderr b/src/test/ui/borrowck/immut-function-arguments.stderr index 7238dd14433..d5392e7d66f 100644 --- a/src/test/ui/borrowck/immut-function-arguments.stderr +++ b/src/test/ui/borrowck/immut-function-arguments.stderr @@ -1,18 +1,24 @@ error[E0594]: cannot assign to `*y`, as `y` is not declared as mutable --> $DIR/immut-function-arguments.rs:2:5 | -LL | fn f(y: Box<isize>) { - | - help: consider changing this to be mutable: `mut y` LL | *y = 5; | ^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | fn f(mut y: Box<isize>) { + | +++ error[E0594]: cannot assign to `*q`, as `q` is not declared as mutable --> $DIR/immut-function-arguments.rs:6:35 | LL | let _frob = |q: Box<isize>| { *q = 2; }; - | - ^^^^^^ cannot assign - | | - | help: consider changing this to be mutable: `mut q` + | ^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let _frob = |mut q: Box<isize>| { *q = 2; }; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr index b7623a54056..774b6cf0ea6 100644 --- a/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr +++ b/src/test/ui/borrowck/issue-54499-field-mutation-of-moved-out.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `t.0`, as `t` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:13:9 | -LL | let t: Tuple = (S(0), 0); - | - help: consider changing this to be mutable: `mut t` -LL | drop(t); LL | t.0 = S(1); | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut t: Tuple = (S(0), 0); + | +++ error[E0382]: assign to part of moved value: `t` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:13:9 @@ -20,20 +22,24 @@ LL | t.0 = S(1); error[E0594]: cannot assign to `t.1`, as `t` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:16:9 | -LL | let t: Tuple = (S(0), 0); - | - help: consider changing this to be mutable: `mut t` -... LL | t.1 = 2; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut t: Tuple = (S(0), 0); + | +++ error[E0594]: cannot assign to `u.0`, as `u` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:24:9 | -LL | let u: Tpair = Tpair(S(0), 0); - | - help: consider changing this to be mutable: `mut u` -LL | drop(u); LL | u.0 = S(1); | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut u: Tpair = Tpair(S(0), 0); + | +++ error[E0382]: assign to part of moved value: `u` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:24:9 @@ -48,20 +54,24 @@ LL | u.0 = S(1); error[E0594]: cannot assign to `u.1`, as `u` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:27:9 | -LL | let u: Tpair = Tpair(S(0), 0); - | - help: consider changing this to be mutable: `mut u` -... LL | u.1 = 2; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut u: Tpair = Tpair(S(0), 0); + | +++ error[E0594]: cannot assign to `v.x`, as `v` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:35:9 | -LL | let v: Spair = Spair { x: S(0), y: 0 }; - | - help: consider changing this to be mutable: `mut v` -LL | drop(v); LL | v.x = S(1); | ^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | +++ error[E0382]: assign to part of moved value: `v` --> $DIR/issue-54499-field-mutation-of-moved-out.rs:35:9 @@ -76,11 +86,13 @@ LL | v.x = S(1); error[E0594]: cannot assign to `v.y`, as `v` is not declared as mutable --> $DIR/issue-54499-field-mutation-of-moved-out.rs:38:9 | -LL | let v: Spair = Spair { x: S(0), y: 0 }; - | - help: consider changing this to be mutable: `mut v` -... LL | v.y = 2; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut v: Spair = Spair { x: S(0), y: 0 }; + | +++ error: aborting due to 9 previous errors diff --git a/src/test/ui/borrowck/issue-85765.stderr b/src/test/ui/borrowck/issue-85765.stderr index 13033962142..7da7dba68ab 100644 --- a/src/test/ui/borrowck/issue-85765.stderr +++ b/src/test/ui/borrowck/issue-85765.stderr @@ -10,11 +10,13 @@ LL | rofl.push(Vec::new()); error[E0594]: cannot assign to `*r`, which is behind a `&` reference --> $DIR/issue-85765.rs:12:5 | -LL | let r = &mutvar; - | ------- help: consider changing this to be a mutable reference: `&mut mutvar` -LL | LL | *r = 0; | ^^^^^^ `r` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let r = &mut mutvar; + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/issue-85765.rs:19:5 diff --git a/src/test/ui/borrowck/issue-93093.stderr b/src/test/ui/borrowck/issue-93093.stderr index 031128af476..afa76594f0b 100644 --- a/src/test/ui/borrowck/issue-93093.stderr +++ b/src/test/ui/borrowck/issue-93093.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `self.foo`, which is behind a `&` reference --> $DIR/issue-93093.rs:8:9 | -LL | async fn bar(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` -LL | LL | self.foo += 1; | ^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | async fn bar(&mut self) { + | ~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/borrowck/many-mutable-borrows.rs b/src/test/ui/borrowck/many-mutable-borrows.rs new file mode 100644 index 00000000000..3e6ea9d25d9 --- /dev/null +++ b/src/test/ui/borrowck/many-mutable-borrows.rs @@ -0,0 +1,18 @@ +fn main() { + let v = Vec::new(); //~ ERROR cannot borrow `v` as mutable, as it is not declared as mutable + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); + v.push(0); +} diff --git a/src/test/ui/borrowck/many-mutable-borrows.stderr b/src/test/ui/borrowck/many-mutable-borrows.stderr new file mode 100644 index 00000000000..aa0cbcffd95 --- /dev/null +++ b/src/test/ui/borrowck/many-mutable-borrows.stderr @@ -0,0 +1,33 @@ +error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable + --> $DIR/many-mutable-borrows.rs:2:9 + | +LL | let v = Vec::new(); + | ^ not mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable +LL | v.push(0); + | --------- cannot borrow as mutable + | + = note: ...and 5 other attempted mutable borrows +help: consider changing this to be mutable + | +LL | let mut v = Vec::new(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs b/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs index 7cdb16b282d..477a2aa48d5 100644 --- a/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs +++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs @@ -2,15 +2,14 @@ #![crate_type = "rlib"] pub fn f(b: &mut i32) { - //~^ NOTE the binding is already a mutable borrow + //~^ ERROR cannot borrow + //~| NOTE not mutable //~| NOTE the binding is already a mutable borrow h(&mut b); - //~^ ERROR cannot borrow - //~| NOTE cannot borrow as mutable + //~^ NOTE cannot borrow as mutable //~| HELP try removing `&mut` here g(&mut &mut b); - //~^ ERROR cannot borrow - //~| NOTE cannot borrow as mutable + //~^ NOTE cannot borrow as mutable //~| HELP try removing `&mut` here } diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr index 7782047574c..c6f75b1c0d0 100644 --- a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr +++ b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr @@ -1,8 +1,14 @@ error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:7:7 + --> $DIR/mut-borrow-of-mut-ref.rs:4:10 | +LL | pub fn f(b: &mut i32) { + | ^ not mutable +... LL | h(&mut b); - | ^^^^^^ cannot borrow as mutable + | ------ cannot borrow as mutable +... +LL | g(&mut &mut b); + | ------ cannot borrow as mutable | note: the binding is already a mutable borrow --> $DIR/mut-borrow-of-mut-ref.rs:4:13 @@ -14,18 +20,6 @@ help: try removing `&mut` here LL - h(&mut b); LL + h(b); | - -error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:11:12 - | -LL | g(&mut &mut b); - | ^^^^^^ cannot borrow as mutable - | -note: the binding is already a mutable borrow - --> $DIR/mut-borrow-of-mut-ref.rs:4:13 - | -LL | pub fn f(b: &mut i32) { - | ^^^^^^^^ help: try removing `&mut` here | LL - g(&mut &mut b); @@ -33,13 +27,13 @@ LL + g(&mut b); | error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:18:12 + --> $DIR/mut-borrow-of-mut-ref.rs:17:12 | LL | h(&mut &mut b); | ^^^^^^ cannot borrow as mutable | note: the binding is already a mutable borrow - --> $DIR/mut-borrow-of-mut-ref.rs:17:13 + --> $DIR/mut-borrow-of-mut-ref.rs:16:13 | LL | pub fn g(b: &mut i32) { | ^^^^^^^^ @@ -50,7 +44,7 @@ LL + h(&mut b); | error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable - --> $DIR/mut-borrow-of-mut-ref.rs:35:5 + --> $DIR/mut-borrow-of-mut-ref.rs:34:5 | LL | f.bar(); | ^^^^^^^ cannot borrow as mutable @@ -60,6 +54,6 @@ help: consider making the binding mutable LL | pub fn baz(mut f: &mut String) { | +++ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/mutability-errors.rs b/src/test/ui/borrowck/mutability-errors.rs index 5be0df13761..82116425f06 100644 --- a/src/test/ui/borrowck/mutability-errors.rs +++ b/src/test/ui/borrowck/mutability-errors.rs @@ -50,9 +50,9 @@ fn ref_closure(mut x: (i32,)) { }); } -fn imm_local(x: (i32,)) { - &mut x; //~ ERROR - &mut x.0; //~ ERROR +fn imm_local(x: (i32,)) { //~ ERROR + &mut x; + &mut x.0; } fn imm_capture(x: (i32,)) { diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr index dd29ae492d6..d7c602718f1 100644 --- a/src/test/ui/borrowck/mutability-errors.stderr +++ b/src/test/ui/borrowck/mutability-errors.stderr @@ -1,37 +1,46 @@ error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/mutability-errors.rs:9:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` LL | *x = (1,); | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to `x.0`, which is behind a `&` reference --> $DIR/mutability-errors.rs:10:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` -LL | *x = (1,); LL | x.0 = 1; | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/mutability-errors.rs:11:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` -... LL | &mut *x; | ^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `&` reference --> $DIR/mutability-errors.rs:12:5 | -LL | fn named_ref(x: &(i32,)) { - | ------- help: consider changing this to be a mutable reference: `&mut (i32,)` -... LL | &mut x.0; | ^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn named_ref(x: &mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to data in a `&` reference --> $DIR/mutability-errors.rs:16:5 @@ -60,37 +69,46 @@ LL | &mut f().0; error[E0594]: cannot assign to `*x`, which is behind a `*const` pointer --> $DIR/mutability-errors.rs:23:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` LL | *x = (1,); | ^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to `x.0`, which is behind a `*const` pointer --> $DIR/mutability-errors.rs:24:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` -LL | *x = (1,); LL | (*x).0 = 1; | ^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be written + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer --> $DIR/mutability-errors.rs:25:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` -... LL | &mut *x; | ^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `x.0` as mutable, as it is behind a `*const` pointer --> $DIR/mutability-errors.rs:26:5 | -LL | unsafe fn named_ptr(x: *const (i32,)) { - | ------------- help: consider changing this to be a mutable pointer: `*mut (i32,)` -... LL | &mut (*x).0; | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable pointer + | +LL | unsafe fn named_ptr(x: *mut (i32,)) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to data in a `*const` pointer --> $DIR/mutability-errors.rs:30:5 @@ -227,21 +245,19 @@ LL | &mut x.0; | ^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/mutability-errors.rs:54:5 + --> $DIR/mutability-errors.rs:53:14 | LL | fn imm_local(x: (i32,)) { - | - help: consider changing this to be mutable: `mut x` -LL | &mut x; - | ^^^^^^ cannot borrow as mutable - -error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable - --> $DIR/mutability-errors.rs:55:5 - | -LL | fn imm_local(x: (i32,)) { - | - help: consider changing this to be mutable: `mut x` + | ^ not mutable LL | &mut x; + | ------ cannot borrow as mutable LL | &mut x.0; - | ^^^^^^^^ cannot borrow as mutable + | -------- cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn imm_local(mut x: (i32,)) { + | +++ error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/mutability-errors.rs:60:9 @@ -339,7 +355,7 @@ error[E0596]: cannot borrow `X.0` as mutable, as `X` is an immutable static item LL | &mut X.0; | ^^^^^^^^ cannot borrow as mutable -error: aborting due to 38 previous errors +error: aborting due to 37 previous errors Some errors have detailed explanations: E0594, E0596. For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr index a3885b5f5ca..81e5bc45d4d 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_overlapping.stderr @@ -11,11 +11,13 @@ LL | x.a = 1; error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable --> $DIR/reassignment_immutable_fields_overlapping.rs:13:5 | -LL | let x: Foo; - | - help: consider changing this to be mutable: `mut x` -LL | x.a = 1; LL | x.b = 22; | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut x: Foo; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr index 49c81adad49..ba0457809ad 100644 --- a/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr +++ b/src/test/ui/borrowck/reassignment_immutable_fields_twice.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable --> $DIR/reassignment_immutable_fields_twice.rs:7:5 | -LL | let x: (u32, u32); - | - help: consider changing this to be mutable: `mut x` -LL | x = (22, 44); LL | x.0 = 1; | ^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut x: (u32, u32); + | +++ error[E0381]: partially assigned binding `x` isn't fully initialized --> $DIR/reassignment_immutable_fields_twice.rs:12:5 diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed new file mode 100644 index 00000000000..b0c5376105b --- /dev/null +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed @@ -0,0 +1,15 @@ +// run-rustfix +// Test that a by-ref `FnMut` closure gets an error when it tries to +// consume a value. + +fn call<F>(f: F) where F : Fn() { + f(); +} + +fn main() { + let y = vec![format!("World")]; + call(|| { + y.clone().into_iter(); + //~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure + }); +} diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs index d54b09c5da9..4666b8a3373 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.rs @@ -1,3 +1,4 @@ +// run-rustfix // Test that a by-ref `FnMut` closure gets an error when it tries to // consume a value. diff --git a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index b1367c65218..f033d53bf8e 100644 --- a/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure - --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9 + --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:12:9 | LL | let y = vec![format!("World")]; | - captured outer variable @@ -12,6 +12,10 @@ LL | y.into_iter(); | note: `into_iter` takes ownership of the receiver `self`, which moves `y` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | y.clone().into_iter(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr index 481d7e58529..95f36fc042c 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr @@ -1,14 +1,16 @@ error[E0596]: cannot borrow `**ref_mref_x` as mutable, as it is behind a `&` reference --> $DIR/mut_ref.rs:12:13 | -LL | let ref_mref_x = &mref_x; - | ------- help: consider changing this to be a mutable reference: `&mut mref_x` -LL | LL | let c = || { | ^^ `ref_mref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable LL | LL | **ref_mref_x = y; | ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure + | +help: consider changing this to be a mutable reference + | +LL | let ref_mref_x = &mut mref_x; + | ~~~~~~~~~~~ error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference --> $DIR/mut_ref.rs:26:13 diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr index bf9e1febdbb..239f071ca92 100644 --- a/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutable-borrow-in-closure.rs:6:5 | -LL | let callback = || { - | -------- help: consider changing this to be mutable: `mut callback` LL | &mut my_var; | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr index b67cec6a609..1ec279f03ef 100644 --- a/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutable-borrow-in-move-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutable-borrow-in-move-closure.rs:6:5 | -LL | let callback = move || { - | -------- help: consider changing this to be mutable: `mut callback` LL | &mut my_var; | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = move || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-80313-mutation-in-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr index 6e98549f6b8..22a62ce7350 100644 --- a/src/test/ui/closures/issue-80313-mutation-in-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutation-in-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutation-in-closure.rs:6:5 | -LL | let callback = || { - | -------- help: consider changing this to be mutable: `mut callback` LL | my_var = true; | ------ calling `callback` requires mutable binding due to mutable borrow of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr index edd55422a0b..a2222f8cc95 100644 --- a/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr +++ b/src/test/ui/closures/issue-80313-mutation-in-move-closure.stderr @@ -1,13 +1,16 @@ error[E0596]: cannot borrow `callback` as mutable, as it is not declared as mutable --> $DIR/issue-80313-mutation-in-move-closure.rs:6:5 | -LL | let callback = move || { - | -------- help: consider changing this to be mutable: `mut callback` LL | my_var = true; | ------ calling `callback` requires mutable binding due to possible mutation of `my_var` LL | }; LL | callback(); | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut callback = move || { + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-81700-mut-borrow.stderr b/src/test/ui/closures/issue-81700-mut-borrow.stderr index 3f564afff58..03b18c3f70c 100644 --- a/src/test/ui/closures/issue-81700-mut-borrow.stderr +++ b/src/test/ui/closures/issue-81700-mut-borrow.stderr @@ -2,11 +2,14 @@ error[E0596]: cannot borrow `bar` as mutable, as it is not declared as mutable --> $DIR/issue-81700-mut-borrow.rs:3:5 | LL | let bar = || { foo(x); }; - | --- - calling `bar` requires mutable binding due to mutable borrow of `x` - | | - | help: consider changing this to be mutable: `mut bar` + | - calling `bar` requires mutable binding due to mutable borrow of `x` LL | bar(); | ^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut bar = || { foo(x); }; + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-82438-mut-without-upvar.stderr b/src/test/ui/closures/issue-82438-mut-without-upvar.stderr index 802284b2658..f0951b7d108 100644 --- a/src/test/ui/closures/issue-82438-mut-without-upvar.stderr +++ b/src/test/ui/closures/issue-82438-mut-without-upvar.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `c` as mutable, as it is not declared as mutable --> $DIR/issue-82438-mut-without-upvar.rs:27:27 | -LL | let c = |a, b, c, d| {}; - | - help: consider changing this to be mutable: `mut c` -LL | LL | A.f(participant_name, &mut c); | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut c = |a, b, c, d| {}; + | +++ error: aborting due to previous error diff --git a/src/test/ui/closures/issue-84044-drop-non-mut.stderr b/src/test/ui/closures/issue-84044-drop-non-mut.stderr index c0bfad263f1..5335a056cd8 100644 --- a/src/test/ui/closures/issue-84044-drop-non-mut.stderr +++ b/src/test/ui/closures/issue-84044-drop-non-mut.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable --> $DIR/issue-84044-drop-non-mut.rs:5:10 | -LL | let f = || {}; - | - help: consider changing this to be mutable: `mut f` LL | drop(&mut f); | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = || {}; + | +++ error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr index a60f1c77a58..9f8ce3b6183 100644 --- a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr +++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/huge_multispan_highlight.rs:90:13 | -LL | let x = "foo"; - | - help: consider changing this to be mutable: `mut x` -... LL | let y = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = "foo"; + | +++ error: aborting due to previous error diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr index e0e369124a4..17bea2f366f 100644 --- a/src/test/ui/codemap_tests/tab_3.stderr +++ b/src/test/ui/codemap_tests/tab_3.stderr @@ -12,10 +12,10 @@ LL | println!("{:?}", some_vec); note: `into_iter` takes ownership of the receiver `self`, which moves `some_vec` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider cloning the value if the performance cost is acceptable +help: you can `clone` the value and consume it, but this might not be your desired behavior | LL | some_vec.clone().into_iter(); - | ++++++++ + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/command/command-argv0-debug.rs b/src/test/ui/command/command-argv0-debug.rs deleted file mode 100644 index 4aba1229f29..00000000000 --- a/src/test/ui/command/command-argv0-debug.rs +++ /dev/null @@ -1,21 +0,0 @@ -// run-pass - -// ignore-windows - this is a unix-specific test -// ignore-emscripten no processes -// ignore-sgx no processes -use std::os::unix::process::CommandExt; -use std::process::Command; - -fn main() { - let mut command = Command::new("some-boring-name"); - - assert_eq!(format!("{:?}", command), r#""some-boring-name""#); - - command.args(&["1", "2", "3"]); - - assert_eq!(format!("{:?}", command), r#""some-boring-name" "1" "2" "3""#); - - command.arg0("exciting-name"); - - assert_eq!(format!("{:?}", command), r#"["some-boring-name"] "exciting-name" "1" "2" "3""#); -} diff --git a/src/test/ui/compare-method/region-extra-2.stderr b/src/test/ui/compare-method/region-extra-2.stderr index f01d7f4710c..eb19d57ab05 100644 --- a/src/test/ui/compare-method/region-extra-2.stderr +++ b/src/test/ui/compare-method/region-extra-2.stderr @@ -6,6 +6,11 @@ LL | fn renew<'b: 'a>(self) -> &'b mut [T]; ... LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b { | ^^ impl has extra requirement `'a: 'b` + | +help: copy the `where` clause predicates from the trait + | +LL | fn renew<'b: 'a>(self) -> &'b mut [T] where 'b: 'a { + | ~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/compare-method/region-extra.stderr b/src/test/ui/compare-method/region-extra.stderr index 4a3af65e904..1a471e18d9d 100644 --- a/src/test/ui/compare-method/region-extra.stderr +++ b/src/test/ui/compare-method/region-extra.stderr @@ -6,6 +6,12 @@ LL | fn foo(); ... LL | fn foo() where 'a: 'b { } | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - fn foo() where 'a: 'b { } +LL + fn foo() { } + | error: aborting due to previous error diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs b/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs new file mode 100644 index 00000000000..f797beda8e6 --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/issue-99647.rs @@ -0,0 +1,15 @@ +// edition:2018 +// run-pass + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +#[allow(unused)] +async fn foo<'a>() { + let _data = &mut [0u8; { 1 + 4 }]; + bar().await +} + +async fn bar() {} + +fn main() {} diff --git a/src/test/ui/consts/promoted_const_call.rs b/src/test/ui/consts/promoted_const_call.rs new file mode 100644 index 00000000000..30ae730535c --- /dev/null +++ b/src/test/ui/consts/promoted_const_call.rs @@ -0,0 +1,19 @@ +#![feature(const_mut_refs)] +#![feature(const_trait_impl)] +struct Panic; +impl const Drop for Panic { fn drop(&mut self) { panic!(); } } +pub const fn id<T>(x: T) -> T { x } +pub const C: () = { + let _: &'static _ = &id(&Panic); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed +}; + +fn main() { + let _: &'static _ = &id(&Panic); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + let _: &'static _ = &&(Panic, 0).1; + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/promoted_const_call.stderr b/src/test/ui/consts/promoted_const_call.stderr new file mode 100644 index 00000000000..83cc16f6f94 --- /dev/null +++ b/src/test/ui/consts/promoted_const_call.stderr @@ -0,0 +1,65 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:7:26 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:7:30 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:13:26 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:13:30 + | +LL | let _: &'static _ = &id(&Panic); + | ---------- ^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:16:26 + | +LL | let _: &'static _ = &&(Panic, 0).1; + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call.rs:16:27 + | +LL | let _: &'static _ = &&(Panic, 0).1; + | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/promoted_const_call2.rs b/src/test/ui/consts/promoted_const_call2.rs new file mode 100644 index 00000000000..f332cd18cea --- /dev/null +++ b/src/test/ui/consts/promoted_const_call2.rs @@ -0,0 +1,14 @@ +#![feature(const_precise_live_drops)] +pub const fn id<T>(x: T) -> T { x } +pub const C: () = { + let _: &'static _ = &id(&String::new()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + //~| ERROR: destructor of `String` cannot be evaluated at compile-time +}; + +fn main() { + let _: &'static _ = &id(&String::new()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/promoted_const_call2.stderr b/src/test/ui/consts/promoted_const_call2.stderr new file mode 100644 index 00000000000..13d864ed3db --- /dev/null +++ b/src/test/ui/consts/promoted_const_call2.stderr @@ -0,0 +1,50 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:4:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:4:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:11:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call2.rs:11:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call2.rs:4:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/promoted_const_call3.rs b/src/test/ui/consts/promoted_const_call3.rs new file mode 100644 index 00000000000..6d68a2de70e --- /dev/null +++ b/src/test/ui/consts/promoted_const_call3.rs @@ -0,0 +1,26 @@ +pub const fn id<T>(x: T) -> T { x } +pub const C: () = { + let _: &'static _ = &String::new(); + //~^ ERROR: destructor of `String` cannot be evaluated at compile-time + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &id(&String::new()); + //~^ ERROR: destructor of `String` cannot be evaluated at compile-time + //~| ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + //~^ ERROR: temporary value dropped while borrowed +}; + +fn main() { + let _: &'static _ = &String::new(); + //~^ ERROR: temporary value dropped while borrowed + + let _: &'static _ = &id(&String::new()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/promoted_const_call3.stderr b/src/test/ui/consts/promoted_const_call3.stderr new file mode 100644 index 00000000000..af17457a10a --- /dev/null +++ b/src/test/ui/consts/promoted_const_call3.stderr @@ -0,0 +1,105 @@ +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call3.rs:7:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call3.rs:3:26 + | +LL | let _: &'static _ = &String::new(); + | ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants +... +LL | }; + | - value is dropped here + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:3:26 + | +LL | let _: &'static _ = &String::new(); + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:7:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:7:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:12:26 + | +LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:17:26 + | +LL | let _: &'static _ = &String::new(); + | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:20:26 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:20:30 + | +LL | let _: &'static _ = &id(&String::new()); + | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | type annotation requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call3.rs:24:26 + | +LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/promoted_const_call4.rs b/src/test/ui/consts/promoted_const_call4.rs new file mode 100644 index 00000000000..82a17b7bf86 --- /dev/null +++ b/src/test/ui/consts/promoted_const_call4.rs @@ -0,0 +1,18 @@ +// run-pass + +use std::sync::atomic::*; + +static FLAG: AtomicBool = AtomicBool::new(false); + +struct NoisyDrop(&'static str); +impl Drop for NoisyDrop { + fn drop(&mut self) { + FLAG.store(true, Ordering::SeqCst); + } +} +fn main() { + { + let _val = &&(NoisyDrop("drop!"), 0).1; + } + assert!(FLAG.load(Ordering::SeqCst)); +} diff --git a/src/test/ui/consts/promoted_const_call5.rs b/src/test/ui/consts/promoted_const_call5.rs new file mode 100644 index 00000000000..3ac8d358ce4 --- /dev/null +++ b/src/test/ui/consts/promoted_const_call5.rs @@ -0,0 +1,42 @@ +#![feature(rustc_attrs)] +#![feature(staged_api)] +#![stable(feature = "a", since = "1.0.0")] + +#[rustc_promotable] +#[stable(feature = "a", since = "1.0.0")] +#[rustc_const_stable(feature = "a", since = "1.0.0")] +pub const fn id<T>(x: &'static T) -> &'static T { x } + +#[rustc_promotable] +#[stable(feature = "a", since = "1.0.0")] +#[rustc_const_stable(feature = "a", since = "1.0.0")] +pub const fn new_string() -> String { + String::new() +} + +#[rustc_promotable] +#[stable(feature = "a", since = "1.0.0")] +#[rustc_const_stable(feature = "a", since = "1.0.0")] +pub const fn new_manually_drop<T>(t: T) -> std::mem::ManuallyDrop<T> { + std::mem::ManuallyDrop::new(t) +} + + +const C: () = { + let _: &'static _ = &id(&new_string()); + //~^ ERROR destructor of `String` cannot be evaluated at compile-time + //~| ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &new_manually_drop(new_string()); + //~^ ERROR: temporary value dropped while borrowed +}; + +fn main() { + let _: &'static _ = &id(&new_string()); + //~^ ERROR: temporary value dropped while borrowed + //~| ERROR: temporary value dropped while borrowed + + let _: &'static _ = &new_manually_drop(new_string()); + //~^ ERROR: temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/promoted_const_call5.stderr b/src/test/ui/consts/promoted_const_call5.stderr new file mode 100644 index 00000000000..f736220b183 --- /dev/null +++ b/src/test/ui/consts/promoted_const_call5.stderr @@ -0,0 +1,74 @@ +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call5.rs:26:30 + | +LL | let _: &'static _ = &id(&new_string()); + | ^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:26:26 + | +LL | let _: &'static _ = &id(&new_string()); + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:26:30 + | +LL | let _: &'static _ = &id(&new_string()); + | ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:31:26 + | +LL | let _: &'static _ = &new_manually_drop(new_string()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:36:26 + | +LL | let _: &'static _ = &id(&new_string()); + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +... +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:36:30 + | +LL | let _: &'static _ = &id(&new_string()); + | ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary value which is freed while still in use + | argument requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promoted_const_call5.rs:40:26 + | +LL | let _: &'static _ = &new_manually_drop(new_string()); + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0493, E0716. +For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs index a00a19e46d5..bd9c8483ec2 100644 --- a/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-1.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-1 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs index 71cc0a12ea3..bd0f08f45b6 100644 --- a/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-2.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-2 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs b/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs index 921687d4c3b..1226c2fbb46 100644 --- a/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs +++ b/src/test/ui/crate-loading/auxiliary/crateresolve1-3.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-3 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/crate-loading/crateresolve1.rs b/src/test/ui/crate-loading/crateresolve1.rs index f4795e9536a..f5477f244dd 100644 --- a/src/test/ui/crate-loading/crateresolve1.rs +++ b/src/test/ui/crate-loading/crateresolve1.rs @@ -9,7 +9,6 @@ // NOTE: This test is duplicated at `src/test/ui/error-codes/E0464.rs`. extern crate crateresolve1; -//~^ ERROR multiple matching crates for `crateresolve1` +//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found -fn main() { -} +fn main() {} diff --git a/src/test/ui/crate-loading/crateresolve1.stderr b/src/test/ui/crate-loading/crateresolve1.stderr index 0d7538eafd8..7b840b52628 100644 --- a/src/test/ui/crate-loading/crateresolve1.stderr +++ b/src/test/ui/crate-loading/crateresolve1.stderr @@ -1,13 +1,12 @@ -error[E0464]: multiple matching crates for `crateresolve1` +error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found --> $DIR/crateresolve1.rs:11:1 | LL | extern crate crateresolve1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: candidates: - crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-1.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib + = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-1.somelib + = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-2.somelib + = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve1/auxiliary/libcrateresolve1-3.somelib error: aborting due to previous error diff --git a/src/test/ui/crate-loading/crateresolve2.rs b/src/test/ui/crate-loading/crateresolve2.rs index 5a4fee7ed6a..0774c0dfd32 100644 --- a/src/test/ui/crate-loading/crateresolve2.rs +++ b/src/test/ui/crate-loading/crateresolve2.rs @@ -8,7 +8,6 @@ // normalize-stderr-test: "\\\?\\" -> "" extern crate crateresolve2; -//~^ ERROR multiple matching crates for `crateresolve2` +//~^ ERROR multiple candidates for `rmeta` dependency `crateresolve2` found -fn main() { -} +fn main() {} diff --git a/src/test/ui/crate-loading/crateresolve2.stderr b/src/test/ui/crate-loading/crateresolve2.stderr index afd3702de7f..a36f4f02265 100644 --- a/src/test/ui/crate-loading/crateresolve2.stderr +++ b/src/test/ui/crate-loading/crateresolve2.stderr @@ -1,13 +1,12 @@ -error[E0464]: multiple matching crates for `crateresolve2` +error[E0464]: multiple candidates for `rmeta` dependency `crateresolve2` found --> $DIR/crateresolve2.rs:10:1 | LL | extern crate crateresolve2; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: candidates: - crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta - crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta - crate `crateresolve2`: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta + = note: candidate #1: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-1.rmeta + = note: candidate #2: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-2.rmeta + = note: candidate #3: $TEST_BUILD_DIR/crate-loading/crateresolve2/auxiliary/libcrateresolve2-3.rmeta error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr index 9562d94509e..1670da55957 100644 --- a/src/test/ui/did_you_mean/issue-35937.stderr +++ b/src/test/ui/did_you_mean/issue-35937.stderr @@ -1,26 +1,35 @@ error[E0596]: cannot borrow `f.v` as mutable, as `f` is not declared as mutable --> $DIR/issue-35937.rs:7:5 | -LL | let f = Foo { v: Vec::new() }; - | - help: consider changing this to be mutable: `mut f` LL | f.v.push("cat".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut f = Foo { v: Vec::new() }; + | +++ error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable --> $DIR/issue-35937.rs:16:5 | -LL | let s = S { x: 42 }; - | - help: consider changing this to be mutable: `mut s` LL | s.x += 1; | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut s = S { x: 42 }; + | +++ error[E0594]: cannot assign to `s.x`, as `s` is not declared as mutable --> $DIR/issue-35937.rs:20:5 | -LL | fn bar(s: S) { - | - help: consider changing this to be mutable: `mut s` LL | s.x += 1; | ^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | fn bar(mut s: S) { + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/did_you_mean/issue-38147-1.stderr b/src/test/ui/did_you_mean/issue-38147-1.stderr index dd193458b37..74fb1c2eca3 100644 --- a/src/test/ui/did_you_mean/issue-38147-1.stderr +++ b/src/test/ui/did_you_mean/issue-38147-1.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*self.s` as mutable, as it is behind a `&` reference --> $DIR/issue-38147-1.rs:17:9 | -LL | fn f(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` LL | self.s.push('x'); | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f(&mut self) { + | ~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-38147-4.stderr b/src/test/ui/did_you_mean/issue-38147-4.stderr index a2d162f08a1..d3339989361 100644 --- a/src/test/ui/did_you_mean/issue-38147-4.stderr +++ b/src/test/ui/did_you_mean/issue-38147-4.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*f.s` as mutable, as it is behind a `&` reference --> $DIR/issue-38147-4.rs:6:5 | -LL | fn f(x: usize, f: &Foo) { - | ---- help: consider changing this to be a mutable reference: `&mut Foo<'_>` LL | f.s.push('x'); | ^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f(x: usize, f: &mut Foo<'_>) { + | ~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr index 68180eaee03..8dc0512a945 100644 --- a/src/test/ui/did_you_mean/issue-39544.stderr +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -1,94 +1,123 @@ error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable --> $DIR/issue-39544.rs:11:13 | -LL | let z = Z { x: X::Y }; - | - help: consider changing this to be mutable: `mut z` LL | let _ = &mut z.x; | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut z = Z { x: X::Y }; + | +++ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:16:17 | -LL | fn foo<'z>(&'z self) { - | -------- help: consider changing this to be a mutable reference: `&'z mut self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo<'z>(&'z mut self) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:20:17 | -LL | fn foo1(&self, other: &Z) { - | ----- help: consider changing this to be a mutable reference: `&mut self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo1(&mut self, other: &Z) { + | ~~~~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:21:17 | -LL | fn foo1(&self, other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut self.x; LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo1(&self, other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:25:17 | -LL | fn foo2<'a>(&'a self, other: &Z) { - | -------- help: consider changing this to be a mutable reference: `&'a mut self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo2<'a>(&'a mut self, other: &Z) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:26:17 | -LL | fn foo2<'a>(&'a self, other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut self.x; LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo2<'a>(&'a self, other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:30:17 | -LL | fn foo3<'a>(self: &'a Self, other: &Z) { - | -------- help: consider changing this to be a mutable reference: `&'a mut Self` LL | let _ = &mut self.x; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo3<'a>(self: &'a mut Self, other: &Z) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:31:17 | -LL | fn foo3<'a>(self: &'a Self, other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut self.x; LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo3<'a>(self: &'a Self, other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `other.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:35:17 | -LL | fn foo4(other: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` LL | let _ = &mut other.x; | ^^^^^^^^^^^^ `other` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo4(other: &mut Z) { + | ~~~~~~ error[E0596]: cannot borrow `z.x` as mutable, as `z` is not declared as mutable --> $DIR/issue-39544.rs:41:13 | -LL | pub fn with_arg(z: Z, w: &Z) { - | - help: consider changing this to be mutable: `mut z` LL | let _ = &mut z.x; | ^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | pub fn with_arg(mut z: Z, w: &Z) { + | +++ error[E0596]: cannot borrow `w.x` as mutable, as it is behind a `&` reference --> $DIR/issue-39544.rs:42:13 | -LL | pub fn with_arg(z: Z, w: &Z) { - | -- help: consider changing this to be a mutable reference: `&mut Z` -LL | let _ = &mut z.x; LL | let _ = &mut w.x; | ^^^^^^^^ `w` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn with_arg(z: Z, w: &mut Z) { + | ~~~~~~ error[E0594]: cannot assign to `*x.0`, which is behind a `&` reference --> $DIR/issue-39544.rs:48:5 diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr index 67703a1497f..aadd698891e 100644 --- a/src/test/ui/did_you_mean/issue-40823.stderr +++ b/src/test/ui/did_you_mean/issue-40823.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*buf` as mutable, as it is behind a `&` reference --> $DIR/issue-40823.rs:3:5 | -LL | let mut buf = &[1, 2, 3, 4]; - | ------------- help: consider changing this to be a mutable reference: `&mut [1, 2, 3, 4]` LL | buf.iter_mut(); | ^^^^^^^^^^^^^^ `buf` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | let mut buf = &mut [1, 2, 3, 4]; + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/dyn-star/align.normal.stderr b/src/test/ui/dyn-star/align.normal.stderr index 983d7bf6e7e..53c2cbeac32 100644 --- a/src/test/ui/dyn-star/align.normal.stderr +++ b/src/test/ui/dyn-star/align.normal.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/align.over_aligned.stderr b/src/test/ui/dyn-star/align.over_aligned.stderr index 6b6fc55d805..62e28efab58 100644 --- a/src/test/ui/dyn-star/align.over_aligned.stderr +++ b/src/test/ui/dyn-star/align.over_aligned.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default error[E0277]: `AlignedUsize` needs to be a pointer-sized type diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr index fdf74aa7efe..cb9c7815814 100644 --- a/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr +++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr index 933c133831a..bcd014f8dc3 100644 --- a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr +++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/feature-gate-dyn_star.stderr b/src/test/ui/dyn-star/feature-gate-dyn_star.stderr index 2767e9478e2..c3449b6278b 100644 --- a/src/test/ui/dyn-star/feature-gate-dyn_star.stderr +++ b/src/test/ui/dyn-star/feature-gate-dyn_star.stderr @@ -4,7 +4,7 @@ error[E0658]: dyn* trait objects are unstable LL | pub fn dyn_star_parameter(_: &dyn* Send) { | ^^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr index 687d7db0464..eb9c933055a 100644 --- a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr +++ b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr @@ -4,7 +4,7 @@ error[E0658]: dyn* trait objects are unstable LL | let dyn_i: dyn* Debug = i as dyn* Debug; | ^^^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable error[E0658]: dyn* trait objects are unstable @@ -13,7 +13,7 @@ error[E0658]: dyn* trait objects are unstable LL | let dyn_i: dyn* Debug = i as dyn* Debug; | ^^^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = help: add `#![feature(dyn_star)]` to the crate attributes to enable error[E0606]: casting `usize` as `dyn* Debug` is invalid diff --git a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr index 2fc751b3b4a..c7f1a4b9ae1 100644 --- a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr +++ b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star, trait_upcasting)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types diff --git a/src/test/ui/dyn-star/return.stderr b/src/test/ui/dyn-star/return.stderr index e000351a68f..9c265682904 100644 --- a/src/test/ui/dyn-star/return.stderr +++ b/src/test/ui/dyn-star/return.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default warning: 1 warning emitted diff --git a/src/test/ui/dyn-star/upcast.stderr b/src/test/ui/dyn-star/upcast.stderr index 6a95f7754e6..74ccd6a1889 100644 --- a/src/test/ui/dyn-star/upcast.stderr +++ b/src/test/ui/dyn-star/upcast.stderr @@ -4,7 +4,7 @@ warning: the feature `dyn_star` is incomplete and may not be safe to use and/or LL | #![feature(dyn_star, trait_upcasting)] | ^^^^^^^^ | - = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information = note: `#[warn(incomplete_features)]` on by default error[E0277]: `dyn* Foo` needs to be a pointer-sized type diff --git a/src/test/ui/error-codes/E0033-teach.rs b/src/test/ui/error-codes/E0033-teach.rs index 19439651394..289561bad8a 100644 --- a/src/test/ui/error-codes/E0033-teach.rs +++ b/src/test/ui/error-codes/E0033-teach.rs @@ -1,13 +1,13 @@ // compile-flags: -Z teach - trait SomeTrait { - fn foo(); //~ associated function `foo` has no `self` parameter + fn foo(&self); +} +struct S; +impl SomeTrait for S { + fn foo(&self) {} } - fn main() { - let trait_obj: &dyn SomeTrait = SomeTrait; - //~^ ERROR expected value, found trait `SomeTrait` - //~| ERROR E0038 + let trait_obj: &dyn SomeTrait = &S; let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033-teach.stderr b/src/test/ui/error-codes/E0033-teach.stderr index 3b68abbb4a0..31bc6719a56 100644 --- a/src/test/ui/error-codes/E0033-teach.stderr +++ b/src/test/ui/error-codes/E0033-teach.stderr @@ -1,31 +1,3 @@ -error[E0423]: expected value, found trait `SomeTrait` - --> $DIR/E0033-teach.rs:8:37 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^ not a value - -error[E0038]: the trait `SomeTrait` cannot be made into an object - --> $DIR/E0033-teach.rs:8:20 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/E0033-teach.rs:4:8 - | -LL | trait SomeTrait { - | --------- this trait cannot be made into an object... -LL | fn foo(); - | ^^^ ...because associated function `foo` has no `self` parameter -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self); - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized; - | +++++++++++++++++ - error[E0033]: type `&dyn SomeTrait` cannot be dereferenced --> $DIR/E0033-teach.rs:12:9 | @@ -36,7 +8,6 @@ LL | let &invalid = trait_obj; You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0033, E0038, E0423. -For more information about an error, try `rustc --explain E0033`. +For more information about this error, try `rustc --explain E0033`. diff --git a/src/test/ui/error-codes/E0033.rs b/src/test/ui/error-codes/E0033.rs index e5f0530f45f..bd6ec207223 100644 --- a/src/test/ui/error-codes/E0033.rs +++ b/src/test/ui/error-codes/E0033.rs @@ -1,11 +1,12 @@ trait SomeTrait { - fn foo(); //~ associated function `foo` has no `self` parameter + fn foo(&self); +} +struct S; +impl SomeTrait for S { + fn foo(&self) {} } - fn main() { - let trait_obj: &dyn SomeTrait = SomeTrait; - //~^ ERROR expected value, found trait `SomeTrait` - //~| ERROR E0038 + let trait_obj: &dyn SomeTrait = &S; let &invalid = trait_obj; //~^ ERROR E0033 diff --git a/src/test/ui/error-codes/E0033.stderr b/src/test/ui/error-codes/E0033.stderr index f0645107831..ab2e780ee62 100644 --- a/src/test/ui/error-codes/E0033.stderr +++ b/src/test/ui/error-codes/E0033.stderr @@ -1,38 +1,9 @@ -error[E0423]: expected value, found trait `SomeTrait` - --> $DIR/E0033.rs:6:37 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^ not a value - -error[E0038]: the trait `SomeTrait` cannot be made into an object - --> $DIR/E0033.rs:6:20 - | -LL | let trait_obj: &dyn SomeTrait = SomeTrait; - | ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object - | -note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/E0033.rs:2:8 - | -LL | trait SomeTrait { - | --------- this trait cannot be made into an object... -LL | fn foo(); - | ^^^ ...because associated function `foo` has no `self` parameter -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self); - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() where Self: Sized; - | +++++++++++++++++ - error[E0033]: type `&dyn SomeTrait` cannot be dereferenced - --> $DIR/E0033.rs:10:9 + --> $DIR/E0033.rs:11:9 | LL | let &invalid = trait_obj; | ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0033, E0038, E0423. -For more information about an error, try `rustc --explain E0033`. +For more information about this error, try `rustc --explain E0033`. diff --git a/src/test/ui/error-codes/E0389.stderr b/src/test/ui/error-codes/E0389.stderr index 3d615bd932f..51c4c92addf 100644 --- a/src/test/ui/error-codes/E0389.stderr +++ b/src/test/ui/error-codes/E0389.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference --> $DIR/E0389.rs:8:5 | -LL | let fancy_ref = &(&mut fancy); - | ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)` LL | fancy_ref.num = 6; | ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let fancy_ref = &mut (&mut fancy); + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0464.rs b/src/test/ui/error-codes/E0464.rs index 969115a7d97..554f1ce72d9 100644 --- a/src/test/ui/error-codes/E0464.rs +++ b/src/test/ui/error-codes/E0464.rs @@ -9,7 +9,6 @@ // NOTE: This test is duplicated from `src/test/ui/crate-loading/crateresolve1.rs`. extern crate crateresolve1; -//~^ ERROR multiple matching crates for `crateresolve1` +//~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found -fn main() { -} +fn main() {} diff --git a/src/test/ui/error-codes/E0464.stderr b/src/test/ui/error-codes/E0464.stderr index 3d950ddd28e..574270f94a6 100644 --- a/src/test/ui/error-codes/E0464.stderr +++ b/src/test/ui/error-codes/E0464.stderr @@ -1,13 +1,12 @@ -error[E0464]: multiple matching crates for `crateresolve1` +error[E0464]: multiple candidates for `rlib` dependency `crateresolve1` found --> $DIR/E0464.rs:11:1 | LL | extern crate crateresolve1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: candidates: - crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-1.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib - crate `crateresolve1`: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib + = note: candidate #1: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-1.somelib + = note: candidate #2: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-2.somelib + = note: candidate #3: $TEST_BUILD_DIR/error-codes/E0464/auxiliary/libcrateresolve1-3.somelib error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0519.rs b/src/test/ui/error-codes/E0519.rs new file mode 100644 index 00000000000..269ffd6320d --- /dev/null +++ b/src/test/ui/error-codes/E0519.rs @@ -0,0 +1,8 @@ +// no need to create a new aux file, we can use an existing. +// aux-build: crateresolve1-1.rs + +// set same metadata as `crateresolve1` +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +extern crate crateresolve1; //~ ERROR E0519 diff --git a/src/test/ui/error-codes/E0519.stderr b/src/test/ui/error-codes/E0519.stderr new file mode 100644 index 00000000000..e24fc4aaa70 --- /dev/null +++ b/src/test/ui/error-codes/E0519.stderr @@ -0,0 +1,9 @@ +error[E0519]: the current crate is indistinguishable from one of its dependencies: it has the same crate-name `crateresolve1` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two. + --> $DIR/E0519.rs:8:1 + | +LL | extern crate crateresolve1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0519`. diff --git a/src/test/ui/error-codes/E0596.stderr b/src/test/ui/error-codes/E0596.stderr index 79bc258f1fa..3f9aebcc8ae 100644 --- a/src/test/ui/error-codes/E0596.stderr +++ b/src/test/ui/error-codes/E0596.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/E0596.rs:3:13 | -LL | let x = 1; - | - help: consider changing this to be mutable: `mut x` LL | let y = &mut x; | ^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = 1; + | +++ error: aborting due to previous error diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs index a00a19e46d5..bd9c8483ec2 100644 --- a/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-1.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-1 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs index 71cc0a12ea3..bd0f08f45b6 100644 --- a/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-2.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-2 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs b/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs index 921687d4c3b..1226c2fbb46 100644 --- a/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs +++ b/src/test/ui/error-codes/auxiliary/crateresolve1-3.rs @@ -1,4 +1,5 @@ // compile-flags:-C extra-filename=-3 +// no-prefer-dynamic #![crate_name = "crateresolve1"] #![crate_type = "lib"] diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.rs b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs index e4341e19687..fdec072b8a8 100644 --- a/src/test/ui/expr/malformed_closure/ruby_style_closure.rs +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs @@ -8,7 +8,6 @@ fn main() { let p = Some(45).and_then({ - //~^ expected a `FnOnce<({integer},)>` closure, found `Option<_>` |x| println!("doubling {}", x); Some(x * 2) //~^ ERROR: cannot find value `x` in this scope diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr index 2f9d10d70a2..e8b34121b5f 100644 --- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr +++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr @@ -1,29 +1,9 @@ error[E0425]: cannot find value `x` in this scope - --> $DIR/ruby_style_closure.rs:13:14 + --> $DIR/ruby_style_closure.rs:12:14 | LL | Some(x * 2) | ^ not found in this scope -error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>` - --> $DIR/ruby_style_closure.rs:10:31 - | -LL | let p = Some(45).and_then({ - | ______________________--------_^ - | | | - | | required by a bound introduced by this call -LL | | -LL | | |x| println!("doubling {}", x); -LL | | Some(x * 2) - | | ----------- this tail expression is of type `Option<_>` -LL | | -LL | | }); - | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>` - | - = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>` -note: required by a bound in `Option::<T>::and_then` - --> $SRC_DIR/core/src/option.rs:LL:COL - -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0425. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs b/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs index e44a84776bc..539c8fb27b3 100644 --- a/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs +++ b/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs @@ -5,7 +5,8 @@ extern crate proc_macro; -use proc_macro::{Literal, Span, TokenStream, TokenTree}; +use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; #[proc_macro] pub fn foo_with_input_span(input: TokenStream) -> TokenStream { @@ -26,3 +27,14 @@ pub fn err_with_input_span(input: TokenStream) -> TokenStream { TokenStream::from(TokenTree::Literal(lit)) } + +#[proc_macro] +pub fn respan_to_invalid_format_literal(input: TokenStream) -> TokenStream { + let mut s = Literal::string("{"); + s.set_span(input.into_iter().next().unwrap().span()); + TokenStream::from_iter([ + TokenTree::from(Ident::new("format", Span::call_site())), + TokenTree::from(Punct::new('!', Spacing::Alone)), + TokenTree::from(Group::new(Delimiter::Parenthesis, TokenTree::from(s).into())), + ]) +} diff --git a/src/test/ui/fmt/issue-103826.rs b/src/test/ui/fmt/issue-103826.rs new file mode 100644 index 00000000000..a11ec37a06d --- /dev/null +++ b/src/test/ui/fmt/issue-103826.rs @@ -0,0 +1,8 @@ +fn main() { + format!("{\x7D"); + //~^ ERROR 1 positional argument in format string, but no arguments were given + format!("\x7B\x7D"); + //~^ ERROR 1 positional argument in format string, but no arguments were given + format!("{\x7D {\x7D"); + //~^ ERROR 2 positional arguments in format string, but no arguments were given +} diff --git a/src/test/ui/fmt/issue-103826.stderr b/src/test/ui/fmt/issue-103826.stderr new file mode 100644 index 00000000000..0f27e1930bc --- /dev/null +++ b/src/test/ui/fmt/issue-103826.stderr @@ -0,0 +1,20 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-103826.rs:2:14 + | +LL | format!("{\x7D"); + | ^^^^^ + +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-103826.rs:4:14 + | +LL | format!("\x7B\x7D"); + | ^^^^^^^^ + +error: 2 positional arguments in format string, but no arguments were given + --> $DIR/issue-103826.rs:6:14 + | +LL | format!("{\x7D {\x7D"); + | ^^^^^ ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/fmt/respanned-literal-issue-106191.rs b/src/test/ui/fmt/respanned-literal-issue-106191.rs new file mode 100644 index 00000000000..44642a10fc0 --- /dev/null +++ b/src/test/ui/fmt/respanned-literal-issue-106191.rs @@ -0,0 +1,10 @@ +// aux-build:format-string-proc-macro.rs + +extern crate format_string_proc_macro; + +fn main() { + format_string_proc_macro::respan_to_invalid_format_literal!("¡"); + //~^ ERROR invalid format string: expected `'}'` but string was terminated + format_args!(r#concat!("¡ {")); + //~^ ERROR invalid format string: expected `'}'` but string was terminated +} diff --git a/src/test/ui/fmt/respanned-literal-issue-106191.stderr b/src/test/ui/fmt/respanned-literal-issue-106191.stderr new file mode 100644 index 00000000000..73a3af65a38 --- /dev/null +++ b/src/test/ui/fmt/respanned-literal-issue-106191.stderr @@ -0,0 +1,19 @@ +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/respanned-literal-issue-106191.rs:6:65 + | +LL | format_string_proc_macro::respan_to_invalid_format_literal!("¡"); + | ^^^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + +error: invalid format string: expected `'}'` but string was terminated + --> $DIR/respanned-literal-issue-106191.rs:8:18 + | +LL | format_args!(r#concat!("¡ {")); + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + | + = note: if you intended to print `{`, you can escape it using `{{` + = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/function-pointer/unsized-ret.stderr b/src/test/ui/function-pointer/unsized-ret.stderr index 40bf7a3898a..6f430687e6d 100644 --- a/src/test/ui/function-pointer/unsized-ret.stderr +++ b/src/test/ui/function-pointer/unsized-ret.stderr @@ -23,7 +23,7 @@ LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&() | required by a bound introduced by this call | = help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)` - = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)` + = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn Display + 'a)` note: required by a bound in `foo` --> $DIR/unsized-ret.rs:5:11 | diff --git a/src/test/ui/functions-closures/fn-help-with-err.rs b/src/test/ui/functions-closures/fn-help-with-err.rs index 49a514a8b4e..612fe1b8419 100644 --- a/src/test/ui/functions-closures/fn-help-with-err.rs +++ b/src/test/ui/functions-closures/fn-help-with-err.rs @@ -4,7 +4,6 @@ struct Foo; trait Bar { //~^ NOTE `Bar` defines an item `bar`, perhaps you need to implement it - //~| NOTE `Bar` defines an item `bar`, perhaps you need to implement it fn bar(&self) {} } @@ -15,9 +14,6 @@ fn main() { //~^ ERROR cannot find value `oops` in this scope //~| NOTE not found arc.bar(); - //~^ ERROR no method named `bar` - //~| NOTE method not found - //~| HELP items from traits can only be used if the trait is implemented and in scope let arc2 = std::sync::Arc::new(|| Foo); arc2.bar(); diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr index 463ac7684ec..83a2b1f58f9 100644 --- a/src/test/ui/functions-closures/fn-help-with-err.stderr +++ b/src/test/ui/functions-closures/fn-help-with-err.stderr @@ -1,27 +1,14 @@ error[E0425]: cannot find value `oops` in this scope - --> $DIR/fn-help-with-err.rs:14:35 + --> $DIR/fn-help-with-err.rs:13:35 | LL | let arc = std::sync::Arc::new(oops); | ^^^^ not found in this scope -error[E0599]: no method named `bar` found for struct `Arc<_>` in the current scope - --> $DIR/fn-help-with-err.rs:17:9 - | -LL | arc.bar(); - | ^^^ method not found in `Arc<_>` - | - = help: items from traits can only be used if the trait is implemented and in scope -note: `Bar` defines an item `bar`, perhaps you need to implement it - --> $DIR/fn-help-with-err.rs:5:1 - | -LL | trait Bar { - | ^^^^^^^^^ - -error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:22:36]>` in the current scope - --> $DIR/fn-help-with-err.rs:23:10 +error[E0599]: no method named `bar` found for struct `Arc<[closure@fn-help-with-err.rs:18:36]>` in the current scope + --> $DIR/fn-help-with-err.rs:19:10 | LL | arc2.bar(); - | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:22:36]>` + | ^^^ method not found in `Arc<[closure@fn-help-with-err.rs:18:36]>` | = help: items from traits can only be used if the trait is implemented and in scope note: `Bar` defines an item `bar`, perhaps you need to implement it @@ -34,7 +21,7 @@ help: use parentheses to call this closure LL | arc2().bar(); | ++ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0425, E0599. For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr index ed0628bbbc3..ebf35be581c 100644 --- a/src/test/ui/generator/print/generator-print-verbose-1.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr @@ -35,7 +35,7 @@ note: required because it's used within this generator | LL | || { | ^^ -note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])` +note: required because it appears within the type `Opaque(DefId(0:35 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])` --> $DIR/generator-print-verbose-1.rs:41:30 | LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> { diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs index 01165fcebaf..e45bdcf9213 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.rs +++ b/src/test/ui/generic-associated-types/impl_bounds.rs @@ -15,7 +15,6 @@ impl<T> Foo for Fooy<T> { //~^ ERROR impl has stricter requirements than trait type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; //~^ ERROR impl has stricter requirements than trait - //~| ERROR lifetime bound not satisfied type C = String where Self: Copy; //~^ ERROR the trait bound `T: Copy` is not satisfied fn d() where Self: Copy {} diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr index 442d4f33690..3456b345cc2 100644 --- a/src/test/ui/generic-associated-types/impl_bounds.stderr +++ b/src/test/ui/generic-associated-types/impl_bounds.stderr @@ -15,29 +15,14 @@ LL | type B<'a, 'b> where 'a: 'b; ... LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; | ^^ impl has extra requirement `'b: 'a` - -error[E0478]: lifetime bound not satisfied - --> $DIR/impl_bounds.rs:16:22 | -LL | type B<'a, 'b> where 'a: 'b; - | -------------- definition of `B` from trait -... -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^^^^^^^^^^^^^^ - help: try copying this clause from the trait: `, 'a: 'b` +help: copy the `where` clause predicates from the trait | -note: lifetime parameter instantiated with the lifetime `'a` as defined here - --> $DIR/impl_bounds.rs:16:12 - | -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^ -note: but lifetime parameter must outlive the lifetime `'b` as defined here - --> $DIR/impl_bounds.rs:16:16 - | -LL | type B<'a, 'b> = (&'a(), &'b ()) where 'b: 'a; - | ^^ +LL | type B<'a, 'b> = (&'a(), &'b ()) where 'a: 'b; + | ~~~~~~~~~~~~ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:19:33 + --> $DIR/impl_bounds.rs:18:33 | LL | type C = String where Self: Copy; | ^^^^ the trait `Copy` is not implemented for `T` @@ -62,7 +47,7 @@ LL | impl<T: std::marker::Copy> Foo for Fooy<T> { | +++++++++++++++++++ error[E0277]: the trait bound `T: Copy` is not satisfied - --> $DIR/impl_bounds.rs:21:24 + --> $DIR/impl_bounds.rs:20:24 | LL | fn d() where Self: Copy {} | ^^^^ the trait `Copy` is not implemented for `T` @@ -86,7 +71,7 @@ help: consider restricting type parameter `T` LL | impl<T: std::marker::Copy> Foo for Fooy<T> { | +++++++++++++++++++ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0276, E0277, E0478. +Some errors have detailed explanations: E0276, E0277. For more information about an error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/issue-90014.stderr b/src/test/ui/generic-associated-types/issue-90014.stderr index 2d3f4a6af7e..b4b1bc7da7f 100644 --- a/src/test/ui/generic-associated-types/issue-90014.stderr +++ b/src/test/ui/generic-associated-types/issue-90014.stderr @@ -5,13 +5,17 @@ LL | type Fut<'a> where Self: 'a; | ------------ definition of `Fut` from trait ... LL | type Fut<'a> = impl Future<Output = ()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-90014.rs:13:14 | LL | type Fut<'a> = impl Future<Output = ()>; | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type Fut<'a> = impl Future<Output = ()> where Self: 'a; + | ++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-91883.stderr b/src/test/ui/generic-associated-types/issue-91883.stderr index 1cfc2aaf161..d5db962094c 100644 --- a/src/test/ui/generic-associated-types/issue-91883.stderr +++ b/src/test/ui/generic-associated-types/issue-91883.stderr @@ -5,7 +5,7 @@ LL | type Cursor<'tx>: Cursor<'tx> | ----------------------------- definition of `Cursor` from trait ... LL | type Cursor<'tx> = CursorImpl<'tx>; - | ^^^^^^^^^^^^^^^- help: try copying these clauses from the trait: `where 'db: 'tx, Self: 'tx` + | ^^^^^^^^^^^^^^^ | note: lifetime parameter instantiated with the lifetime `'db` as defined here --> $DIR/issue-91883.rs:29:6 @@ -17,6 +17,10 @@ note: but lifetime parameter must outlive the lifetime `'tx` as defined here | LL | type Cursor<'tx> = CursorImpl<'tx>; | ^^^ +help: copy the `where` clause predicates from the trait + | +LL | type Cursor<'tx> = CursorImpl<'tx> where 'db: 'tx, Self: 'tx; + | +++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-92033.stderr b/src/test/ui/generic-associated-types/issue-92033.stderr index cd7eed25421..ddc420a7b4e 100644 --- a/src/test/ui/generic-associated-types/issue-92033.stderr +++ b/src/test/ui/generic-associated-types/issue-92033.stderr @@ -5,13 +5,17 @@ LL | type TextureIter<'a>: Iterator<Item = &'a Texture> | -------------------------------------------------- definition of `TextureIter` from trait ... LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: try copying this clause from the trait: `where Self: 'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: type must outlive the lifetime `'a` as defined here --> $DIR/issue-92033.rs:20:22 | LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture>; | ^^ +help: copy the `where` clause predicates from the trait + | +LL | type TextureIter<'a> = std::option::IntoIter<&'a Texture> where Self: 'a; + | ++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs new file mode 100644 index 00000000000..8caf5317693 --- /dev/null +++ b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.rs @@ -0,0 +1,12 @@ +trait Foo { + type T<'a1, 'b1> + where + 'a1: 'b1; +} + +impl Foo for () { + type T<'a2, 'b2> = () where 'b2: 'a2; + //~^ ERROR impl has stricter requirements than trait +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr new file mode 100644 index 00000000000..91a03007640 --- /dev/null +++ b/src/test/ui/generic-associated-types/mismatched-where-clause-regions.stderr @@ -0,0 +1,17 @@ +error[E0276]: impl has stricter requirements than trait + --> $DIR/mismatched-where-clause-regions.rs:8:38 + | +LL | type T<'a1, 'b1> + | ---------------- definition of `T` from trait +... +LL | type T<'a2, 'b2> = () where 'b2: 'a2; + | ^^^ impl has extra requirement `'b2: 'a2` + | +help: copy the `where` clause predicates from the trait + | +LL | type T<'a2, 'b2> = () where 'a2: 'b2; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0276`. diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr index ffdba6676bf..8a71fc73a9d 100644 --- a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr +++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr @@ -6,6 +6,12 @@ LL | type Assoc<'a, 'b>; ... LL | type Assoc<'a, 'b> = () where 'a: 'b; | ^^ impl has extra requirement `'a: 'b` + | +help: remove the `where` clause + | +LL - type Assoc<'a, 'b> = () where 'a: 'b; +LL + type Assoc<'a, 'b> = () ; + | error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs new file mode 100644 index 00000000000..4b096be591a --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.rs @@ -0,0 +1,20 @@ +// Test that Fn-family traits with lifetime parameters shouldn't compile and +// we suggest the usage of higher-rank trait bounds instead. + +fn fa(_: impl Fn<'a>(&'a str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +use std::ops::Fn as AliasedFn; +fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} +//~^ ERROR `Fn` traits cannot take lifetime parameters + +fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr new file mode 100644 index 00000000000..e8f6d63b5ab --- /dev/null +++ b/src/test/ui/higher-rank-trait-bounds/hrtb-malformed-lifetime-generics.stderr @@ -0,0 +1,62 @@ +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:4:17 + | +LL | fn fa(_: impl Fn<'a>(&'a str) -> bool) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fa(_: impl Fn<'a>(&'a str) -> bool) {} +LL + fn fa(_: impl for<'a> Fn(&'a str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:7:20 + | +LL | fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} + | ^^^^^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fb(_: impl FnMut<'a, 'b>(&'a str, &'b str) -> bool) {} +LL + fn fb(_: impl for<'a, 'b> FnMut(&'a str, &'b str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:10:41 + | +LL | fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fc(_: impl std::fmt::Display + FnOnce<'a>(&'a str) -> bool + std::fmt::Debug) {} +LL + fn fc(_: impl std::fmt::Display + for<'a> FnOnce(&'a str) -> bool + std::fmt::Debug) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:14:24 + | +LL | fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fd(_: impl AliasedFn<'a>(&'a str) -> bool) {} +LL + fn fd(_: impl for<'a> AliasedFn(&'a str) -> bool) {} + | + +error: `Fn` traits cannot take lifetime parameters + --> $DIR/hrtb-malformed-lifetime-generics.rs:17:27 + | +LL | fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} + | ^^^^ + | +help: consider using a higher-ranked trait bound instead + | +LL - fn fe<F>(_: F) where F: Fn<'a>(&'a str) -> bool {} +LL + fn fe<F>(_: F) where F: for<'a> Fn(&'a str) -> bool {} + | + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/impl-trait/issue-72911.rs b/src/test/ui/impl-trait/issue-72911.rs index be9c643b2d8..63f4898f430 100644 --- a/src/test/ui/impl-trait/issue-72911.rs +++ b/src/test/ui/impl-trait/issue-72911.rs @@ -5,7 +5,6 @@ pub struct Lint {} impl Lint {} pub fn gather_all() -> impl Iterator<Item = Lint> { - //~^ ERROR type annotations needed lint_files().flat_map(|f| gather_from_file(&f)) } diff --git a/src/test/ui/impl-trait/issue-72911.stderr b/src/test/ui/impl-trait/issue-72911.stderr index fc7200c75c2..0e86561aa27 100644 --- a/src/test/ui/impl-trait/issue-72911.stderr +++ b/src/test/ui/impl-trait/issue-72911.stderr @@ -1,22 +1,15 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo` - --> $DIR/issue-72911.rs:12:33 + --> $DIR/issue-72911.rs:11:33 | LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> { | ^^^ use of undeclared crate or module `foo` error[E0433]: failed to resolve: use of undeclared crate or module `foo` - --> $DIR/issue-72911.rs:17:41 + --> $DIR/issue-72911.rs:16:41 | LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> { | ^^^ use of undeclared crate or module `foo` -error[E0282]: type annotations needed - --> $DIR/issue-72911.rs:7:24 - | -LL | pub fn gather_all() -> impl Iterator<Item = Lint> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0433. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index ec3860a322f..1a0104b859e 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -1,9 +1,9 @@ // run-pass -// needs-unwind -// revisions: mir thir strict -// [thir]compile-flags: -Zthir-unsafeck +// revisions: default strict // [strict]compile-flags: -Zstrict-init-checks // ignore-tidy-linelength +// ignore-emscripten spawning processes is not supported +// ignore-sgx no processes // This test checks panic emitted from `mem::{uninitialized,zeroed}`. @@ -12,7 +12,6 @@ use std::{ mem::{self, MaybeUninit, ManuallyDrop}, - panic, ptr::NonNull, num, }; @@ -70,21 +69,42 @@ enum ZeroIsValid { } #[track_caller] -fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { - let err = panic::catch_unwind(op).err(); - assert_eq!( - err.as_ref().and_then(|a| a.downcast_ref::<&str>()), - Some(&msg) - ); +fn test_panic_msg<T, F: (FnOnce() -> T) + 'static>(op: F, msg: &str) { + use std::{panic, env, process}; + + // The tricky part is that we can't just run `op`, as that would *abort* the process. + // So instead, we reinvoke this process with the caller location as argument. + // For the purpose of this test, the line number is unique enough. + // If we are running in such a re-invocation, we skip all the tests *except* for the one with that type name. + let our_loc = panic::Location::caller().line().to_string(); + let mut args = env::args(); + let this = args.next().unwrap(); + if let Some(loc) = args.next() { + if loc == our_loc { + op(); + panic!("we did not abort"); + } else { + // Nothing, we are running another test. + } + } else { + // Invoke new process for actual test, and check result. + let mut cmd = process::Command::new(this); + cmd.arg(our_loc); + let res = cmd.output().unwrap(); + assert!(!res.status.success(), "test did not fail"); + let stderr = String::from_utf8_lossy(&res.stderr); + assert!(stderr.contains(msg), "test did not contain expected output: looking for {:?}, output:\n{}", msg, stderr); + } } #[track_caller] -fn test_panic_msg_only_if_strict<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { - let err = panic::catch_unwind(op).err(); - assert_eq!( - err.as_ref().and_then(|a| a.downcast_ref::<&str>()), - if cfg!(strict) { Some(&msg) } else { None }, - ); +fn test_panic_msg_only_if_strict<T>(op: impl (FnOnce() -> T) + 'static, msg: &str) { + if !cfg!(strict) { + // Just run it. + op(); + } else { + test_panic_msg(op, msg); + } } fn main() { diff --git a/src/test/ui/issues/issue-13497-2.stderr b/src/test/ui/issues/issue-13497-2.stderr index 3abeadf9e4b..a365e24e27e 100644 --- a/src/test/ui/issues/issue-13497-2.stderr +++ b/src/test/ui/issues/issue-13497-2.stderr @@ -1,10 +1,7 @@ error[E0515]: cannot return value referencing local variable `rawLines` --> $DIR/issue-13497-2.rs:3:5 | -LL | rawLines - | ______^ - | | _____| - | || +LL | // rawLines LL | || .iter().map(|l| l.trim()).collect() | ||_______________-___________________________^ returns a value referencing data owned by the current function | |_______________| diff --git a/src/test/ui/issues/issue-21763.stderr b/src/test/ui/issues/issue-21763.stderr index 72c65029746..04379f07ba0 100644 --- a/src/test/ui/issues/issue-21763.stderr +++ b/src/test/ui/issues/issue-21763.stderr @@ -7,7 +7,7 @@ LL | foo::<HashMap<Rc<()>, Rc<()>>>(); = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>` = note: required because it appears within the type `(Rc<()>, Rc<()>)` = note: required for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>` to implement `Send` - = note: required because it appears within the type `hashbrown::map::HashMap<Rc<()>, Rc<()>, RandomState>` + = note: required because it appears within the type `HashMap<Rc<()>, Rc<()>, RandomState>` = note: required because it appears within the type `HashMap<Rc<()>, Rc<()>>` note: required by a bound in `foo` --> $DIR/issue-21763.rs:6:11 diff --git a/src/test/ui/issues/issue-36400.stderr b/src/test/ui/issues/issue-36400.stderr index 3b37578f3c4..5b753c69d5d 100644 --- a/src/test/ui/issues/issue-36400.stderr +++ b/src/test/ui/issues/issue-36400.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable --> $DIR/issue-36400.rs:5:7 | -LL | let x = Box::new(3); - | - help: consider changing this to be mutable: `mut x` LL | f(&mut *x); | ^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = Box::new(3); + | +++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51515.stderr b/src/test/ui/issues/issue-51515.stderr index 067bdef8b67..c4e61e71953 100644 --- a/src/test/ui/issues/issue-51515.stderr +++ b/src/test/ui/issues/issue-51515.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/issue-51515.rs:5:5 | -LL | let foo = &16; - | --- help: consider changing this to be a mutable reference: `&mut 16` -... LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let foo = &mut 16; + | ~~~~~~~ error[E0594]: cannot assign to `*bar`, which is behind a `&` reference --> $DIR/issue-51515.rs:8:5 diff --git a/src/test/ui/issues/issue-61623.stderr b/src/test/ui/issues/issue-61623.stderr index f6546054233..5fcc338557c 100644 --- a/src/test/ui/issues/issue-61623.stderr +++ b/src/test/ui/issues/issue-61623.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*x.1` as mutable, as it is behind a `&` reference --> $DIR/issue-61623.rs:6:19 | -LL | fn f3<'a>(x: &'a ((), &'a mut ())) { - | -------------------- help: consider changing this to be a mutable reference: `&'a mut ((), &'a mut ())` LL | f2(|| x.0, f1(x.1)) | ^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn f3<'a>(x: &'a mut ((), &'a mut ())) { + | ~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-67535.rs b/src/test/ui/issues/issue-67535.rs new file mode 100644 index 00000000000..24f50621310 --- /dev/null +++ b/src/test/ui/issues/issue-67535.rs @@ -0,0 +1,22 @@ +fn main() {} + +impl std::ops::AddAssign for () { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: ()) -> () { + () + } +} + +impl std::ops::AddAssign for [(); 1] { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: [(); 1]) -> [(); 1] { + [()] + } +} + +impl std::ops::AddAssign for &[u8] { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + fn add_assign(&self, other: &[u8]) -> &[u8] { + self + } +} diff --git a/src/test/ui/issues/issue-67535.stderr b/src/test/ui/issues/issue-67535.stderr new file mode 100644 index 00000000000..4d7a02a5096 --- /dev/null +++ b/src/test/ui/issues/issue-67535.stderr @@ -0,0 +1,39 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:3:1 + | +LL | impl std::ops::AddAssign for () { + | ^^^^^-------------------^^^^^-- + | | | | + | | | this is not defined in the current crate because tuples are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:10:1 + | +LL | impl std::ops::AddAssign for [(); 1] { + | ^^^^^-------------------^^^^^------- + | | | | + | | | this is not defined in the current crate because arrays are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/issue-67535.rs:17:1 + | +LL | impl std::ops::AddAssign for &[u8] { + | ^^^^^-------------------^^^^^----- + | | | | + | | | this is not defined in the current crate because slices are always foreign + | | this is not defined in the current crate because this is a foreign trait + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.rs b/src/test/ui/lexer/lex-bad-char-literals-6.rs index 4379b4fa6d7..1b498c0fbca 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.rs +++ b/src/test/ui/lexer/lex-bad-char-literals-6.rs @@ -7,10 +7,8 @@ fn main() { //~^ ERROR: character literal may only contain one codepoint if x == y {} - //~^ ERROR: can't compare `&str` with `char` if y == z {} // no error here if x == z {} - //~^ ERROR: can't compare `&str` with `char` let a: usize = ""; //~^ ERROR: mismatched types diff --git a/src/test/ui/lexer/lex-bad-char-literals-6.stderr b/src/test/ui/lexer/lex-bad-char-literals-6.stderr index ce41942467c..2fe30304a50 100644 --- a/src/test/ui/lexer/lex-bad-char-literals-6.stderr +++ b/src/test/ui/lexer/lex-bad-char-literals-6.stderr @@ -31,49 +31,14 @@ help: if you meant to write a `str` literal, use double quotes LL | let z = "ef"; | ~~~~ -error[E0277]: can't compare `&str` with `char` - --> $DIR/lex-bad-char-literals-6.rs:9:10 - | -LL | if x == y {} - | ^^ no implementation for `&str == char` - | - = help: the trait `PartialEq<char>` is not implemented for `&str` - = help: the following other types implement trait `PartialEq<Rhs>`: - <&'a str as PartialEq<OsString>> - <&'a str as PartialEq<String>> - <&'b str as PartialEq<Cow<'a, str>>> - <str as PartialEq<Cow<'a, str>>> - <str as PartialEq<OsStr>> - <str as PartialEq<OsString>> - <str as PartialEq<String>> - <str as PartialEq> - error[E0308]: mismatched types - --> $DIR/lex-bad-char-literals-6.rs:15:20 + --> $DIR/lex-bad-char-literals-6.rs:13:20 | LL | let a: usize = ""; | ----- ^^ expected `usize`, found `&str` | | | expected due to this -error[E0277]: can't compare `&str` with `char` - --> $DIR/lex-bad-char-literals-6.rs:12:10 - | -LL | if x == z {} - | ^^ no implementation for `&str == char` - | - = help: the trait `PartialEq<char>` is not implemented for `&str` - = help: the following other types implement trait `PartialEq<Rhs>`: - <&'a str as PartialEq<OsString>> - <&'a str as PartialEq<String>> - <&'b str as PartialEq<Cow<'a, str>>> - <str as PartialEq<Cow<'a, str>>> - <str as PartialEq<OsStr>> - <str as PartialEq<OsString>> - <str as PartialEq<String>> - <str as PartialEq> - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index a909c5fa823..cc2447b1877 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -16,10 +16,13 @@ LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/ex3-both-anon-regions-using-fn-items.rs:2:3 | -LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { - | - help: consider changing this to be mutable: `mut y` LL | y.push(z); | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(x:fn(&u8, &u8), mut y: Vec<&u8>, z: &u8) { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index d85ea6529f6..2ba5afa808d 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -16,10 +16,13 @@ LL | fn foo<'a>(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&'a u8>, z: &'a u8) { error[E0596]: cannot borrow `y` as mutable, as it is not declared as mutable --> $DIR/ex3-both-anon-regions-using-trait-objects.rs:2:3 | -LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) { - | - help: consider changing this to be mutable: `mut y` LL | y.push(z); | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , mut y: Vec<&u8>, z: &u8) { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/unused/must-use-box-from-raw.stderr b/src/test/ui/lint/unused/must-use-box-from-raw.stderr index 72118275774..47ab613bec2 100644 --- a/src/test/ui/lint/unused/must-use-box-from-raw.stderr +++ b/src/test/ui/lint/unused/must-use-box-from-raw.stderr @@ -4,7 +4,7 @@ warning: unused return value of `Box::<T>::from_raw` that must be used LL | Box::from_raw(ptr); | ^^^^^^^^^^^^^^^^^^ | - = note: call `drop(from_raw(ptr))` if you intend to drop the `Box` + = note: call `drop(Box::from_raw(ptr))` if you intend to drop the `Box` note: the lint level is defined here --> $DIR/must-use-box-from-raw.rs:5:9 | diff --git a/src/test/ui/lint/unused_braces_macro.rs b/src/test/ui/lint/unused_braces_macro.rs new file mode 100644 index 00000000000..bfee95378bf --- /dev/null +++ b/src/test/ui/lint/unused_braces_macro.rs @@ -0,0 +1,6 @@ +// build-pass +pub fn foo<const BAR: bool> () {} + +fn main() { + foo::<{cfg!(feature = "foo")}>(); +} diff --git a/src/test/ui/macros/best-failure.rs b/src/test/ui/macros/best-failure.rs new file mode 100644 index 00000000000..bbdd465d5ec --- /dev/null +++ b/src/test/ui/macros/best-failure.rs @@ -0,0 +1,11 @@ +macro_rules! number { + (neg false, $self:ident) => { $self }; + ($signed:tt => $ty:ty;) => { + number!(neg $signed, $self); + //~^ ERROR no rules expected the token `$` + }; +} + +number! { false => u8; } + +fn main() {} diff --git a/src/test/ui/macros/best-failure.stderr b/src/test/ui/macros/best-failure.stderr new file mode 100644 index 00000000000..a52fc5e3da6 --- /dev/null +++ b/src/test/ui/macros/best-failure.stderr @@ -0,0 +1,21 @@ +error: no rules expected the token `$` + --> $DIR/best-failure.rs:4:30 + | +LL | macro_rules! number { + | ------------------- when calling this macro +... +LL | number!(neg $signed, $self); + | ^^^^^ no rules expected this token in macro call +... +LL | number! { false => u8; } + | ------------------------ in this macro invocation + | +note: while trying to match meta-variable `$self:ident` + --> $DIR/best-failure.rs:2:17 + | +LL | (neg false, $self:ident) => { $self }; + | ^^^^^^^^^^^ + = note: this error originates in the macro `number` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr index ce3424a8b15..e57347b362d 100644 --- a/src/test/ui/macros/span-covering-argument-1.stderr +++ b/src/test/ui/macros/span-covering-argument-1.stderr @@ -1,8 +1,6 @@ error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable --> $DIR/span-covering-argument-1.rs:5:14 | -LL | let $s = 0; - | -- help: consider changing this to be mutable: `mut foo` LL | *&mut $s = 0; | ^^^^^^^ cannot borrow as mutable ... @@ -10,6 +8,10 @@ LL | bad!(foo whatever); | ------------------ in this macro invocation | = note: this error originates in the macro `bad` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider changing this to be mutable + | +LL | let mut $s = 0; + | +++ error: aborting due to previous error diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs index bc0d4488162..5cd217df6fc 100644 --- a/src/test/ui/macros/stringify.rs +++ b/src/test/ui/macros/stringify.rs @@ -801,7 +801,7 @@ fn test_ty() { assert_eq!(stringify_ty!(*const T), "*const T"); assert_eq!(stringify_ty!(*mut T), "*mut T"); - // TyKind::Rptr + // TyKind::Ref assert_eq!(stringify_ty!(&T), "&T"); assert_eq!(stringify_ty!(&mut T), "&mut T"); assert_eq!(stringify_ty!(&'a T), "&'a T"); diff --git a/src/test/ui/match/single-line.rs b/src/test/ui/match/single-line.rs new file mode 100644 index 00000000000..0f69d089f9a --- /dev/null +++ b/src/test/ui/match/single-line.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = match Some(42) { Some(x) => x, None => "" }; //~ ERROR E0308 +} diff --git a/src/test/ui/match/single-line.stderr b/src/test/ui/match/single-line.stderr new file mode 100644 index 00000000000..ec3b76e3f4d --- /dev/null +++ b/src/test/ui/match/single-line.stderr @@ -0,0 +1,12 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/single-line.rs:2:52 + | +LL | let _ = match Some(42) { Some(x) => x, None => "" }; + | -------------- - ^^ expected integer, found `&str` + | | | + | | this is found to be of type `{integer}` + | `match` arms have incompatible types + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/methods/issues/issue-105732.rs b/src/test/ui/methods/issues/issue-105732.rs index 98b7a8d0d04..d7005065813 100644 --- a/src/test/ui/methods/issues/issue-105732.rs +++ b/src/test/ui/methods/issues/issue-105732.rs @@ -6,7 +6,8 @@ auto trait Foo { trait Bar { fn f(&self) { - self.g(); //~ ERROR the method `g` exists for reference `&Self`, but its trait bounds were not satisfied + // issue #105788 + self.g(); //~ ERROR no method named `g` found for reference `&Self` in the current scope } } diff --git a/src/test/ui/methods/issues/issue-105732.stderr b/src/test/ui/methods/issues/issue-105732.stderr index fb2bdf47de7..7696642548d 100644 --- a/src/test/ui/methods/issues/issue-105732.stderr +++ b/src/test/ui/methods/issues/issue-105732.stderr @@ -6,21 +6,11 @@ LL | auto trait Foo { LL | fn g(&self); | ---^-------- help: remove these associated items -error[E0599]: the method `g` exists for reference `&Self`, but its trait bounds were not satisfied - --> $DIR/issue-105732.rs:9:14 +error[E0599]: no method named `g` found for reference `&Self` in the current scope + --> $DIR/issue-105732.rs:10:14 | LL | self.g(); - | ^ - | - = note: the following trait bounds were not satisfied: - `Self: Foo` - which is required by `&Self: Foo` - `&Self: Foo` - = help: items from traits can only be used if the type parameter is bounded by the trait -help: the following trait defines an item `g`, perhaps you need to add a supertrait for it: - | -LL | trait Bar: Foo { - | +++++ + | ^ help: there is a method with a similar name: `f` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/issues/issue-90315.rs b/src/test/ui/methods/issues/issue-90315.rs index 79cdc41959a..fbecaf9b971 100644 --- a/src/test/ui/methods/issues/issue-90315.rs +++ b/src/test/ui/methods/issues/issue-90315.rs @@ -69,8 +69,7 @@ fn main() { //~^ ERROR `usize` is not an iterator let _res: i32 = ..6.take(2).sum(); - //~^ can't call method `take` on ambiguous numeric type - //~| ERROR mismatched types [E0308] + //~^ ERROR can't call method `take` on ambiguous numeric type //~| HELP you must specify a concrete type for this numeric value // Won't suggest because `RangeTo` dest not implemented `take` } diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr index 8d7b32e025a..4d3c086ff6e 100644 --- a/src/test/ui/methods/issues/issue-90315.stderr +++ b/src/test/ui/methods/issues/issue-90315.stderr @@ -184,18 +184,7 @@ help: you must specify a concrete type for this numeric value, like `i32` LL | let _res: i32 = ..6_i32.take(2).sum(); | ~~~~~ -error[E0308]: mismatched types - --> $DIR/issue-90315.rs:71:21 - | -LL | let _res: i32 = ..6.take(2).sum(); - | --- ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `RangeTo` - | | - | expected due to this - | - = note: expected type `i32` - found struct `RangeTo<_>` - -error: aborting due to 19 previous errors +error: aborting due to 18 previous errors Some errors have detailed explanations: E0308, E0599, E0689. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed index 63b65ab20fe..63b65ab20fe 100644 --- a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.fixed +++ b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.fixed diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.rs index 2ab4e3955f3..2ab4e3955f3 100644 --- a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.rs +++ b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.rs diff --git a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr index 82a7f276372..35871afb58b 100644 --- a/src/test/ui/mismatched_types/suggest-removing-tulpe-struct-field.stderr +++ b/src/test/ui/mismatched_types/suggest-removing-tuple-struct-field.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/suggest-removing-tulpe-struct-field.rs:11:13 + --> $DIR/suggest-removing-tuple-struct-field.rs:11:13 | LL | some_fn(value.0); | ------- ^^^^^^^ expected struct `MyWrapper`, found `u32` @@ -7,7 +7,7 @@ LL | some_fn(value.0); | arguments to this function are incorrect | note: function defined here - --> $DIR/suggest-removing-tulpe-struct-field.rs:15:4 + --> $DIR/suggest-removing-tuple-struct-field.rs:15:4 | LL | fn some_fn(wrapped: MyWrapper) { | ^^^^^^^ ------------------ @@ -18,7 +18,7 @@ LL + some_fn(value); | error[E0308]: mismatched types - --> $DIR/suggest-removing-tulpe-struct-field.rs:12:13 + --> $DIR/suggest-removing-tuple-struct-field.rs:12:13 | LL | some_fn(my_wrapper!(123).0); | ------- ^^^^^^^^^^^^^^^^^^ expected struct `MyWrapper`, found `u32` @@ -26,7 +26,7 @@ LL | some_fn(my_wrapper!(123).0); | arguments to this function are incorrect | note: function defined here - --> $DIR/suggest-removing-tulpe-struct-field.rs:15:4 + --> $DIR/suggest-removing-tuple-struct-field.rs:15:4 | LL | fn some_fn(wrapped: MyWrapper) { | ^^^^^^^ ------------------ diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr index b3f95ee192a..7f69e5dcfb7 100644 --- a/src/test/ui/moves/move-fn-self-receiver.stderr +++ b/src/test/ui/moves/move-fn-self-receiver.stderr @@ -9,6 +9,10 @@ LL | val.0; note: `into_iter` takes ownership of the receiver `self`, which moves `val.0` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL = note: move occurs because `val.0` has type `Vec<bool>`, which does not implement the `Copy` trait +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | val.0.clone().into_iter().next(); + | ++++++++ error[E0382]: use of moved value: `foo` --> $DIR/move-fn-self-receiver.rs:34:5 @@ -93,10 +97,10 @@ note: `Foo::use_rc_self` takes ownership of the receiver `self`, which moves `rc | LL | fn use_rc_self(self: Rc<Self>) {} | ^^^^ -help: consider cloning the value if the performance cost is acceptable +help: you can `clone` the value and consume it, but this might not be your desired behavior | LL | rc_foo.clone().use_rc_self(); - | ++++++++ + | ++++++++ error[E0382]: use of moved value: `foo_add` --> $DIR/move-fn-self-receiver.rs:59:5 @@ -136,10 +140,10 @@ LL | for _val in explicit_into_iter.into_iter() {} LL | explicit_into_iter; | ^^^^^^^^^^^^^^^^^^ value used here after move | -help: consider cloning the value if the performance cost is acceptable +help: you can `clone` the value and consume it, but this might not be your desired behavior | LL | for _val in explicit_into_iter.clone().into_iter() {} - | ++++++++ + | ++++++++ error[E0382]: use of moved value: `container` --> $DIR/move-fn-self-receiver.rs:71:5 diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr index 0b1a623a013..a28f324aafa 100644 --- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr +++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr @@ -10,10 +10,10 @@ LL | touch(&x[0]); | note: `into_iter` takes ownership of the receiver `self`, which moves `x` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL -help: consider cloning the value if the performance cost is acceptable +help: you can `clone` the value and consume it, but this might not be your desired behavior | LL | consume(x.clone().into_iter().next().unwrap()); - | ++++++++ + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr index ae76889f104..ab7c2745688 100644 --- a/src/test/ui/moves/moves-based-on-type-exprs.stderr +++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr @@ -162,10 +162,10 @@ LL | touch(&x); | note: `into_iter` takes ownership of the receiver `self`, which moves `x` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL -help: consider cloning the value if the performance cost is acceptable +help: you can `clone` the value and consume it, but this might not be your desired behavior | LL | let _y = x.clone().into_iter().next().unwrap(); - | ++++++++ + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:83:11 @@ -179,10 +179,10 @@ LL | touch(&x); | note: `into_iter` takes ownership of the receiver `self`, which moves `x` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL -help: consider cloning the value if the performance cost is acceptable +help: you can `clone` the value and consume it, but this might not be your desired behavior | LL | let _y = [x.clone().into_iter().next().unwrap(); 1]; - | ++++++++ + | ++++++++ error: aborting due to 11 previous errors diff --git a/src/test/ui/moves/pin-mut-reborrow.fixed b/src/test/ui/moves/pin-mut-reborrow.fixed new file mode 100644 index 00000000000..e808186d7d4 --- /dev/null +++ b/src/test/ui/moves/pin-mut-reborrow.fixed @@ -0,0 +1,15 @@ +// run-rustfix +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn foo(self: Pin<&mut Self>) {} +} + +fn main() { + let mut foo = Foo; + let mut foo = Pin::new(&mut foo); + foo.as_mut().foo(); + foo.foo(); //~ ERROR use of moved value +} diff --git a/src/test/ui/moves/pin-mut-reborrow.rs b/src/test/ui/moves/pin-mut-reborrow.rs new file mode 100644 index 00000000000..fee6236ebb4 --- /dev/null +++ b/src/test/ui/moves/pin-mut-reborrow.rs @@ -0,0 +1,15 @@ +// run-rustfix +use std::pin::Pin; + +struct Foo; + +impl Foo { + fn foo(self: Pin<&mut Self>) {} +} + +fn main() { + let mut foo = Foo; + let mut foo = Pin::new(&mut foo); + foo.foo(); + foo.foo(); //~ ERROR use of moved value +} diff --git a/src/test/ui/moves/pin-mut-reborrow.stderr b/src/test/ui/moves/pin-mut-reborrow.stderr new file mode 100644 index 00000000000..16fa4bacc2d --- /dev/null +++ b/src/test/ui/moves/pin-mut-reborrow.stderr @@ -0,0 +1,23 @@ +error[E0382]: use of moved value: `foo` + --> $DIR/pin-mut-reborrow.rs:14:5 + | +LL | let mut foo = Pin::new(&mut foo); + | ------- move occurs because `foo` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait +LL | foo.foo(); + | ----- `foo` moved due to this method call +LL | foo.foo(); + | ^^^ value used here after move + | +note: `Foo::foo` takes ownership of the receiver `self`, which moves `foo` + --> $DIR/pin-mut-reborrow.rs:7:12 + | +LL | fn foo(self: Pin<&mut Self>) {} + | ^^^^ +help: consider reborrowing the `Pin` instead of moving it + | +LL | foo.as_mut().foo(); + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/suggest-clone.fixed b/src/test/ui/moves/suggest-clone.fixed new file mode 100644 index 00000000000..204bfdb10b0 --- /dev/null +++ b/src/test/ui/moves/suggest-clone.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +#[derive(Clone)] +struct Foo; +impl Foo { + fn foo(self) {} +} +fn main() { + let foo = &Foo; + foo.clone().foo(); //~ ERROR cannot move out +} diff --git a/src/test/ui/moves/suggest-clone.rs b/src/test/ui/moves/suggest-clone.rs new file mode 100644 index 00000000000..25dd9f006f9 --- /dev/null +++ b/src/test/ui/moves/suggest-clone.rs @@ -0,0 +1,11 @@ +// run-rustfix + +#[derive(Clone)] +struct Foo; +impl Foo { + fn foo(self) {} +} +fn main() { + let foo = &Foo; + foo.foo(); //~ ERROR cannot move out +} diff --git a/src/test/ui/moves/suggest-clone.stderr b/src/test/ui/moves/suggest-clone.stderr new file mode 100644 index 00000000000..cbb3dfea3ba --- /dev/null +++ b/src/test/ui/moves/suggest-clone.stderr @@ -0,0 +1,22 @@ +error[E0507]: cannot move out of `*foo` which is behind a shared reference + --> $DIR/suggest-clone.rs:10:5 + | +LL | foo.foo(); + | ^^^^----- + | | | + | | `*foo` moved due to this method call + | move occurs because `*foo` has type `Foo`, which does not implement the `Copy` trait + | +note: `Foo::foo` takes ownership of the receiver `self`, which moves `*foo` + --> $DIR/suggest-clone.rs:6:12 + | +LL | fn foo(self) {} + | ^^^^ +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | foo.clone().foo(); + | ++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/mut/mut-suggestion.rs b/src/test/ui/mut/mut-suggestion.rs index 3104b20aca4..8c269d1e727 100644 --- a/src/test/ui/mut/mut-suggestion.rs +++ b/src/test/ui/mut/mut-suggestion.rs @@ -8,7 +8,7 @@ impl S { fn func(arg: S) { //~^ HELP consider changing this to be mutable - //~| SUGGESTION mut arg + //~| SUGGESTION mut arg.mutate(); //~^ ERROR cannot borrow `arg` as mutable, as it is not declared as mutable } @@ -16,7 +16,7 @@ fn func(arg: S) { fn main() { let local = S; //~^ HELP consider changing this to be mutable - //~| SUGGESTION mut local + //~| SUGGESTION mut local.mutate(); //~^ ERROR cannot borrow `local` as mutable, as it is not declared as mutable } diff --git a/src/test/ui/mut/mut-suggestion.stderr b/src/test/ui/mut/mut-suggestion.stderr index cba284550b9..d89c8b41304 100644 --- a/src/test/ui/mut/mut-suggestion.stderr +++ b/src/test/ui/mut/mut-suggestion.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `arg` as mutable, as it is not declared as mutable --> $DIR/mut-suggestion.rs:12:5 | -LL | fn func(arg: S) { - | --- help: consider changing this to be mutable: `mut arg` -... LL | arg.mutate(); | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn func(mut arg: S) { + | +++ error[E0596]: cannot borrow `local` as mutable, as it is not declared as mutable --> $DIR/mut-suggestion.rs:20:5 | -LL | let local = S; - | ----- help: consider changing this to be mutable: `mut local` -... LL | local.mutate(); | ^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut local = S; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/mut/mutable-class-fields-2.stderr b/src/test/ui/mut/mutable-class-fields-2.stderr index 5a4e31947f2..c53c6ea302c 100644 --- a/src/test/ui/mut/mutable-class-fields-2.stderr +++ b/src/test/ui/mut/mutable-class-fields-2.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `self.how_hungry`, which is behind a `&` reference --> $DIR/mutable-class-fields-2.rs:9:5 | -LL | pub fn eat(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` LL | self.how_hungry -= 5; | ^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | pub fn eat(&mut self) { + | ~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/mut/mutable-class-fields.stderr b/src/test/ui/mut/mutable-class-fields.stderr index 40a0dc9b29c..1d731be8a85 100644 --- a/src/test/ui/mut/mutable-class-fields.stderr +++ b/src/test/ui/mut/mutable-class-fields.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `nyan.how_hungry`, as `nyan` is not declared as mutable --> $DIR/mutable-class-fields.rs:15:3 | -LL | let nyan : Cat = cat(52, 99); - | ---- help: consider changing this to be mutable: `mut nyan` LL | nyan.how_hungry = 0; | ^^^^^^^^^^^^^^^^^^^ cannot assign + | +help: consider changing this to be mutable + | +LL | let mut nyan : Cat = cat(52, 99); + | +++ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-47388.stderr b/src/test/ui/nll/issue-47388.stderr index a4ee7781753..c780451dfa9 100644 --- a/src/test/ui/nll/issue-47388.stderr +++ b/src/test/ui/nll/issue-47388.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `fancy_ref.num`, which is behind a `&` reference --> $DIR/issue-47388.rs:8:5 | -LL | let fancy_ref = &(&mut fancy); - | ------------- help: consider changing this to be a mutable reference: `&mut (&mut fancy)` LL | fancy_ref.num = 6; | ^^^^^^^^^^^^^^^^^ `fancy_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let fancy_ref = &mut (&mut fancy); + | ~~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-51191.stderr b/src/test/ui/nll/issue-51191.stderr index 63ca6ae5c28..27b1f8705ff 100644 --- a/src/test/ui/nll/issue-51191.stderr +++ b/src/test/ui/nll/issue-51191.stderr @@ -30,10 +30,13 @@ LL | (&mut self).bar(); error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable --> $DIR/issue-51191.rs:13:9 | -LL | fn imm(self) { - | ---- help: consider changing this to be mutable: `mut self` LL | (&mut self).bar(); | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn imm(mut self) { + | +++ error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable --> $DIR/issue-51191.rs:22:9 diff --git a/src/test/ui/nll/issue-51244.stderr b/src/test/ui/nll/issue-51244.stderr index dcb6f9fec18..03d8acc8188 100644 --- a/src/test/ui/nll/issue-51244.stderr +++ b/src/test/ui/nll/issue-51244.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `*my_ref`, which is behind a `&` reference --> $DIR/issue-51244.rs:3:5 | -LL | let ref my_ref @ _ = 0; - | ---------- help: consider changing this to be a mutable reference: `ref mut my_ref` LL | *my_ref = 0; | ^^^^^^^^^^^ `my_ref` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let ref mut my_ref @ _ = 0; + | ~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-57989.stderr b/src/test/ui/nll/issue-57989.stderr index e85e63e52ec..31f40d8252e 100644 --- a/src/test/ui/nll/issue-57989.stderr +++ b/src/test/ui/nll/issue-57989.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/issue-57989.rs:5:5 | -LL | fn f(x: &i32) { - | ---- help: consider changing this to be a mutable reference: `&mut i32` -LL | let g = &x; LL | *x = 0; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn f(x: &mut i32) { + | ~~~~~~~~ error[E0506]: cannot assign to `*x` because it is borrowed --> $DIR/issue-57989.rs:5:5 diff --git a/src/test/ui/object-safety/issue-106247.rs b/src/test/ui/object-safety/issue-106247.rs new file mode 100644 index 00000000000..64bf59e5d3a --- /dev/null +++ b/src/test/ui/object-safety/issue-106247.rs @@ -0,0 +1,9 @@ +// check-pass + +#![deny(where_clauses_object_safety)] + +pub trait Trait { + fn method(&self) where Self: Sync; +} + +fn main() {} diff --git a/src/test/ui/parser/diff-markers/enum-2.rs b/src/test/ui/parser/diff-markers/enum-2.rs new file mode 100644 index 00000000000..76ea980fc62 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum-2.rs @@ -0,0 +1,11 @@ +enum E { + Foo { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +||||||| + z: (), +======= + y: i8, +>>>>>>> branch + } +} diff --git a/src/test/ui/parser/diff-markers/enum-2.stderr b/src/test/ui/parser/diff-markers/enum-2.stderr new file mode 100644 index 00000000000..63da5c2a6e1 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum-2.stderr @@ -0,0 +1,21 @@ +error: encountered diff marker + --> $DIR/enum-2.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ||||||| + | ------- +LL | z: (), +LL | ======= + | ------- +LL | y: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/enum.rs b/src/test/ui/parser/diff-markers/enum.rs new file mode 100644 index 00000000000..45df6e3251d --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum.rs @@ -0,0 +1,7 @@ +enum E { +<<<<<<< HEAD //~ ERROR encountered diff marker + Foo(u8), +======= + Bar(i8), +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/enum.stderr b/src/test/ui/parser/diff-markers/enum.stderr new file mode 100644 index 00000000000..abbf3fb41e7 --- /dev/null +++ b/src/test/ui/parser/diff-markers/enum.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/enum.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | Foo(u8), +LL | ======= + | ------- +LL | Bar(i8), +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/fn-arg.rs b/src/test/ui/parser/diff-markers/fn-arg.rs new file mode 100644 index 00000000000..86c355628ab --- /dev/null +++ b/src/test/ui/parser/diff-markers/fn-arg.rs @@ -0,0 +1,16 @@ +trait T { + fn foo( +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch + ) {} +} + +struct S; +impl T for S {} + +fn main() { + S::foo(42); +} diff --git a/src/test/ui/parser/diff-markers/fn-arg.stderr b/src/test/ui/parser/diff-markers/fn-arg.stderr new file mode 100644 index 00000000000..933a206410e --- /dev/null +++ b/src/test/ui/parser/diff-markers/fn-arg.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/fn-arg.rs:3:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ======= + | ------- +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/item-with-attr.rs b/src/test/ui/parser/diff-markers/item-with-attr.rs new file mode 100644 index 00000000000..985907c08b2 --- /dev/null +++ b/src/test/ui/parser/diff-markers/item-with-attr.rs @@ -0,0 +1,10 @@ +#[attribute] +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/src/test/ui/parser/diff-markers/item-with-attr.stderr b/src/test/ui/parser/diff-markers/item-with-attr.stderr new file mode 100644 index 00000000000..850e2368e55 --- /dev/null +++ b/src/test/ui/parser/diff-markers/item-with-attr.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/item-with-attr.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/item.rs b/src/test/ui/parser/diff-markers/item.rs new file mode 100644 index 00000000000..4ed36b7b42b --- /dev/null +++ b/src/test/ui/parser/diff-markers/item.rs @@ -0,0 +1,9 @@ +<<<<<<< HEAD //~ ERROR encountered diff marker +fn foo() {} +======= +fn bar() {} +>>>>>>> branch + +fn main() { + foo(); +} diff --git a/src/test/ui/parser/diff-markers/item.stderr b/src/test/ui/parser/diff-markers/item.stderr new file mode 100644 index 00000000000..9ab3631a60e --- /dev/null +++ b/src/test/ui/parser/diff-markers/item.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/item.rs:1:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/statement.rs b/src/test/ui/parser/diff-markers/statement.rs new file mode 100644 index 00000000000..e55d16d3bbb --- /dev/null +++ b/src/test/ui/parser/diff-markers/statement.rs @@ -0,0 +1,15 @@ +trait T { + fn foo() {} + fn bar() {} +} + +struct S; +impl T for S {} + +fn main() { +<<<<<<< HEAD //~ ERROR encountered diff marker + S::foo(); +======= + S::bar(); +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/statement.stderr b/src/test/ui/parser/diff-markers/statement.stderr new file mode 100644 index 00000000000..7ca2495b829 --- /dev/null +++ b/src/test/ui/parser/diff-markers/statement.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/statement.rs:10:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | S::foo(); +LL | ======= + | ------- +LL | S::bar(); +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/struct-expr.rs b/src/test/ui/parser/diff-markers/struct-expr.rs new file mode 100644 index 00000000000..99d2fd662c6 --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct-expr.rs @@ -0,0 +1,12 @@ +struct S { + x: u8, +} +fn main() { + let _ = S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: 42, +======= + x: 0, +>>>>>>> branch + } +} diff --git a/src/test/ui/parser/diff-markers/struct-expr.stderr b/src/test/ui/parser/diff-markers/struct-expr.stderr new file mode 100644 index 00000000000..d70476a9833 --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct-expr.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/struct-expr.rs:6:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: 42, +LL | ======= + | ------- +LL | x: 0, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/struct.rs b/src/test/ui/parser/diff-markers/struct.rs new file mode 100644 index 00000000000..d26464d47bc --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct.rs @@ -0,0 +1,7 @@ +struct S { +<<<<<<< HEAD //~ ERROR encountered diff marker + x: u8, +======= + x: i8, +>>>>>>> branch +} diff --git a/src/test/ui/parser/diff-markers/struct.stderr b/src/test/ui/parser/diff-markers/struct.stderr new file mode 100644 index 00000000000..cc0b3da664e --- /dev/null +++ b/src/test/ui/parser/diff-markers/struct.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | x: u8, +LL | ======= + | ------- +LL | x: i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/trait-item.rs b/src/test/ui/parser/diff-markers/trait-item.rs new file mode 100644 index 00000000000..3227c8212c9 --- /dev/null +++ b/src/test/ui/parser/diff-markers/trait-item.rs @@ -0,0 +1,14 @@ +trait T { +<<<<<<< HEAD //~ ERROR encountered diff marker + fn foo() {} +======= + fn bar() {} +>>>>>>> branch +} + +struct S; +impl T for S {} + +fn main() { + S::foo(); +} diff --git a/src/test/ui/parser/diff-markers/trait-item.stderr b/src/test/ui/parser/diff-markers/trait-item.stderr new file mode 100644 index 00000000000..cdc19f8e076 --- /dev/null +++ b/src/test/ui/parser/diff-markers/trait-item.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/trait-item.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | fn foo() {} +LL | ======= + | ------- +LL | fn bar() {} +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/tuple-struct.rs b/src/test/ui/parser/diff-markers/tuple-struct.rs new file mode 100644 index 00000000000..7eec35c968d --- /dev/null +++ b/src/test/ui/parser/diff-markers/tuple-struct.rs @@ -0,0 +1,7 @@ +struct S( +<<<<<<< HEAD //~ ERROR encountered diff marker + u8, +======= + i8, +>>>>>>> branch +); diff --git a/src/test/ui/parser/diff-markers/tuple-struct.stderr b/src/test/ui/parser/diff-markers/tuple-struct.stderr new file mode 100644 index 00000000000..d673db89837 --- /dev/null +++ b/src/test/ui/parser/diff-markers/tuple-struct.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/tuple-struct.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | u8, +LL | ======= + | ------- +LL | i8, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/diff-markers/use-statement.rs b/src/test/ui/parser/diff-markers/use-statement.rs new file mode 100644 index 00000000000..6306243a514 --- /dev/null +++ b/src/test/ui/parser/diff-markers/use-statement.rs @@ -0,0 +1,9 @@ +use foo::{ +<<<<<<< HEAD //~ ERROR encountered diff marker + bar, +======= + baz, +>>>>>>> branch +}; + +fn main() {} diff --git a/src/test/ui/parser/diff-markers/use-statement.stderr b/src/test/ui/parser/diff-markers/use-statement.stderr new file mode 100644 index 00000000000..12e6f57dd50 --- /dev/null +++ b/src/test/ui/parser/diff-markers/use-statement.stderr @@ -0,0 +1,18 @@ +error: encountered diff marker + --> $DIR/use-statement.rs:2:1 + | +LL | <<<<<<< HEAD + | ^^^^^^^ after this is the code before the merge +LL | bar, +LL | ======= + | ------- +LL | baz, +LL | >>>>>>> branch + | ^^^^^^^ above this are the incoming code changes + | + = help: if you're having merge conflicts after pulling new code, the top section is the code you already had and the bottom section is the remote code + = help: if you're in the middle of a rebase, the top section is the code being rebased onto and the bottom section is the code coming from the current commit being rebased + = note: for an explanation on these markers from the `git` documentation, visit <https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_checking_out_conflicts> + +error: aborting due to previous error + diff --git a/src/test/ui/parser/intersection-patterns-1.fixed b/src/test/ui/parser/intersection-patterns-1.fixed new file mode 100644 index 00000000000..44773095b87 --- /dev/null +++ b/src/test/ui/parser/intersection-patterns-1.fixed @@ -0,0 +1,35 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +// run-rustfix + +#![allow(unused_variables)] + +fn main() { + let s: Option<u8> = None; + + match s { + y @ Some(x) => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION y @ Some(x) + _ => {} + } + + match 2 { + e @ 1..=5 => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left + //~| HELP switch the order + //~| SUGGESTION e @ 1..=5 + _ => {} + } +} diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns-1.rs index a6d27aab4f6..1036b9daf64 100644 --- a/src/test/ui/parser/intersection-patterns.rs +++ b/src/test/ui/parser/intersection-patterns-1.rs @@ -6,6 +6,10 @@ // to suggest either switching the order or note that intersection // patterns are not allowed. +// run-rustfix + +#![allow(unused_variables)] + fn main() { let s: Option<u8> = None; @@ -19,15 +23,6 @@ fn main() { _ => {} } - match s { - Some(x) @ Some(y) => {} - //~^ ERROR left-hand side of `@` must be a binding - //~| interpreted as a pattern, not a binding - //~| also a pattern - //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` - _ => {} - } - match 2 { 1 ..= 5 @ e => {} //~^ ERROR pattern on wrong side of `@` diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns-1.stderr index 9dc4c469a60..dc968656c91 100644 --- a/src/test/ui/parser/intersection-patterns.stderr +++ b/src/test/ui/parser/intersection-patterns-1.stderr @@ -1,5 +1,5 @@ error: pattern on wrong side of `@` - --> $DIR/intersection-patterns.rs:13:9 + --> $DIR/intersection-patterns-1.rs:17:9 | LL | Some(x) @ y => {} | -------^^^- @@ -8,19 +8,8 @@ LL | Some(x) @ y => {} | pattern on the left, should be on the right | help: switch the order: `y @ Some(x)` -error: left-hand side of `@` must be a binding - --> $DIR/intersection-patterns.rs:23:9 - | -LL | Some(x) @ Some(y) => {} - | -------^^^------- - | | | - | | also a pattern - | interpreted as a pattern, not a binding - | - = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` - error: pattern on wrong side of `@` - --> $DIR/intersection-patterns.rs:32:9 + --> $DIR/intersection-patterns-1.rs:27:9 | LL | 1 ..= 5 @ e => {} | -------^^^- @@ -29,5 +18,5 @@ LL | 1 ..= 5 @ e => {} | pattern on the left, should be on the right | help: switch the order: `e @ 1..=5` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/intersection-patterns-2.rs b/src/test/ui/parser/intersection-patterns-2.rs new file mode 100644 index 00000000000..408415e87ef --- /dev/null +++ b/src/test/ui/parser/intersection-patterns-2.rs @@ -0,0 +1,20 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +fn main() { + let s: Option<u8> = None; + + match s { + Some(x) @ Some(y) => {} + //~^ ERROR left-hand side of `@` must be a binding + //~| interpreted as a pattern, not a binding + //~| also a pattern + //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` + _ => {} + } +} diff --git a/src/test/ui/parser/intersection-patterns-2.stderr b/src/test/ui/parser/intersection-patterns-2.stderr new file mode 100644 index 00000000000..f7e78814ca5 --- /dev/null +++ b/src/test/ui/parser/intersection-patterns-2.stderr @@ -0,0 +1,13 @@ +error: left-hand side of `@` must be a binding + --> $DIR/intersection-patterns-2.rs:13:9 + | +LL | Some(x) @ Some(y) => {} + | -------^^^------- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: aborting due to previous error + diff --git a/src/test/ui/parser/issue-105634.rs b/src/test/ui/parser/issue-105634.rs new file mode 100644 index 00000000000..579aa6e5bfb --- /dev/null +++ b/src/test/ui/parser/issue-105634.rs @@ -0,0 +1,8 @@ +// check-pass + +fn main() { + let _a = ..; + let _b = ..=10; + let _c = &..; + let _d = &..=10; +} diff --git a/src/test/ui/parser/kw-in-trait-bounds.rs b/src/test/ui/parser/kw-in-trait-bounds.rs index fa037e5937d..e9e85339aff 100644 --- a/src/test/ui/parser/kw-in-trait-bounds.rs +++ b/src/test/ui/parser/kw-in-trait-bounds.rs @@ -4,21 +4,13 @@ fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) //~^ ERROR expected identifier, found keyword `fn` //~| ERROR expected identifier, found keyword `fn` //~| ERROR expected identifier, found keyword `fn` -//~| ERROR cannot find trait `r#fn` in this scope -//~| ERROR cannot find trait `r#fn` in this scope -//~| ERROR cannot find trait `r#fn` in this scope -//~| HELP a trait with a similar name exists -//~| HELP a trait with a similar name exists -//~| HELP a trait with a similar name exists -//~| HELP escape `fn` to use it as an identifier -//~| HELP escape `fn` to use it as an identifier -//~| HELP escape `fn` to use it as an identifier +//~| HELP use `Fn` to refer to the trait +//~| HELP use `Fn` to refer to the trait +//~| HELP use `Fn` to refer to the trait where G: fn(), //~^ ERROR expected identifier, found keyword `fn` - //~| ERROR cannot find trait `r#fn` in this scope - //~| HELP a trait with a similar name exists - //~| HELP escape `fn` to use it as an identifier + //~| HELP use `Fn` to refer to the trait {} fn _g<A: struct, B>(_: impl struct, _: &dyn struct) diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr index 79643660e8b..2d3aad4d6ba 100644 --- a/src/test/ui/parser/kw-in-trait-bounds.stderr +++ b/src/test/ui/parser/kw-in-trait-bounds.stderr @@ -2,48 +2,48 @@ error: expected identifier, found keyword `fn` --> $DIR/kw-in-trait-bounds.rs:3:10 | LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | fn _f<F: r#fn(), G>(_: impl fn(), _: &dyn fn()) - | ++ +LL | fn _f<F: Fn(), G>(_: impl fn(), _: &dyn fn()) + | ~~ error: expected identifier, found keyword `fn` --> $DIR/kw-in-trait-bounds.rs:3:27 | LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | fn _f<F: fn(), G>(_: impl r#fn(), _: &dyn fn()) - | ++ +LL | fn _f<F: fn(), G>(_: impl Fn(), _: &dyn fn()) + | ~~ error: expected identifier, found keyword `fn` --> $DIR/kw-in-trait-bounds.rs:3:41 | LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn r#fn()) - | ++ +LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn Fn()) + | ~~ error: expected identifier, found keyword `fn` - --> $DIR/kw-in-trait-bounds.rs:17:4 + --> $DIR/kw-in-trait-bounds.rs:11:4 | LL | G: fn(), - | ^^ expected identifier, found keyword + | ^^ | -help: escape `fn` to use it as an identifier +help: use `Fn` to refer to the trait | -LL | G: r#fn(), - | ++ +LL | G: Fn(), + | ~~ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:24:10 + --> $DIR/kw-in-trait-bounds.rs:16:10 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ expected identifier, found keyword @@ -54,7 +54,7 @@ LL | fn _g<A: r#struct, B>(_: impl struct, _: &dyn struct) | ++ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:24:29 + --> $DIR/kw-in-trait-bounds.rs:16:29 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ expected identifier, found keyword @@ -65,7 +65,7 @@ LL | fn _g<A: struct, B>(_: impl r#struct, _: &dyn struct) | ++ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:24:45 + --> $DIR/kw-in-trait-bounds.rs:16:45 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ expected identifier, found keyword @@ -76,7 +76,7 @@ LL | fn _g<A: struct, B>(_: impl struct, _: &dyn r#struct) | ++ error: expected identifier, found keyword `struct` - --> $DIR/kw-in-trait-bounds.rs:38:8 + --> $DIR/kw-in-trait-bounds.rs:30:8 | LL | B: struct, | ^^^^^^ expected identifier, found keyword @@ -86,44 +86,8 @@ help: escape `struct` to use it as an identifier LL | B: r#struct, | ++ -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:3:10 - | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:17:4 - | -LL | G: fn(), - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:3:27 - | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - -error[E0405]: cannot find trait `r#fn` in this scope - --> $DIR/kw-in-trait-bounds.rs:3:41 - | -LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn()) - | ^^ help: a trait with a similar name exists (notice the capitalization): `Fn` - --> $SRC_DIR/core/src/ops/function.rs:LL:COL - | - = note: similarly named trait `Fn` defined here - error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:24:10 + --> $DIR/kw-in-trait-bounds.rs:16:10 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -132,7 +96,7 @@ LL | trait Struct {} | ------------ similarly named trait `Struct` defined here error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:38:8 + --> $DIR/kw-in-trait-bounds.rs:30:8 | LL | B: struct, | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -141,7 +105,7 @@ LL | trait Struct {} | ------------ similarly named trait `Struct` defined here error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:24:29 + --> $DIR/kw-in-trait-bounds.rs:16:29 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -150,7 +114,7 @@ LL | trait Struct {} | ------------ similarly named trait `Struct` defined here error[E0405]: cannot find trait `r#struct` in this scope - --> $DIR/kw-in-trait-bounds.rs:24:45 + --> $DIR/kw-in-trait-bounds.rs:16:45 | LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) | ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct` @@ -158,6 +122,6 @@ LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct) LL | trait Struct {} | ------------ similarly named trait `Struct` defined here -error: aborting due to 16 previous errors +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs b/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs new file mode 100644 index 00000000000..b6611e6273d --- /dev/null +++ b/src/test/ui/parser/recover-fn-trait-from-fn-kw.rs @@ -0,0 +1,12 @@ +fn foo(_: impl fn() -> i32) {} +//~^ ERROR expected identifier, found keyword `fn` + +fn foo2<T: fn(i32)>(_: T) {} +//~^ ERROR expected identifier, found keyword `fn` + +fn main() { + foo(|| ()); + //~^ mismatched types + foo2(|_: ()| {}); + //~^ type mismatch in closure arguments +} diff --git a/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr b/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr new file mode 100644 index 00000000000..3681a796c53 --- /dev/null +++ b/src/test/ui/parser/recover-fn-trait-from-fn-kw.stderr @@ -0,0 +1,48 @@ +error: expected identifier, found keyword `fn` + --> $DIR/recover-fn-trait-from-fn-kw.rs:1:16 + | +LL | fn foo(_: impl fn() -> i32) {} + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn foo(_: impl Fn() -> i32) {} + | ~~ + +error: expected identifier, found keyword `fn` + --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12 + | +LL | fn foo2<T: fn(i32)>(_: T) {} + | ^^ + | +help: use `Fn` to refer to the trait + | +LL | fn foo2<T: Fn(i32)>(_: T) {} + | ~~ + +error[E0308]: mismatched types + --> $DIR/recover-fn-trait-from-fn-kw.rs:8:12 + | +LL | foo(|| ()); + | ^^ expected `i32`, found `()` + +error[E0631]: type mismatch in closure arguments + --> $DIR/recover-fn-trait-from-fn-kw.rs:10:5 + | +LL | foo2(|_: ()| {}); + | ^^^^ ------- found signature defined here + | | + | expected due to this + | + = note: expected closure signature `fn(i32) -> _` + found closure signature `fn(()) -> _` +note: required by a bound in `foo2` + --> $DIR/recover-fn-trait-from-fn-kw.rs:4:12 + | +LL | fn foo2<T: fn(i32)>(_: T) {} + | ^^^^^^^ required by this bound in `foo2` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr index 70beb5d4232..54118dc3677 100644 --- a/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr +++ b/src/test/ui/pattern/bindings-after-at/nested-binding-modes-mut.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable --> $DIR/nested-binding-modes-mut.rs:4:5 | -LL | let mut is_mut @ not_mut = 42; - | ------- help: consider changing this to be mutable: `mut not_mut` -LL | &mut is_mut; LL | &mut not_mut; | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut is_mut @ mut not_mut = 42; + | +++ error[E0596]: cannot borrow `not_mut` as mutable, as it is not declared as mutable --> $DIR/nested-binding-modes-mut.rs:9:5 | -LL | let not_mut @ mut is_mut = 42; - | ------- help: consider changing this to be mutable: `mut not_mut` -LL | &mut is_mut; LL | &mut not_mut; | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut not_mut @ mut is_mut = 42; + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr index bb7b818368b..1b93267b397 100644 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -104,20 +104,24 @@ LL | *_x0 = U; error[E0594]: cannot assign to `*_x0`, which is behind a `&` reference --> $DIR/borrowck-move-ref-pattern.rs:26:5 | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- help: consider changing this to be a mutable reference: `ref mut _x0` -... LL | *_x0 = U; | ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let (ref mut _x0, _x1, ref _x2, ..) = tup; + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*_x2`, which is behind a `&` reference --> $DIR/borrowck-move-ref-pattern.rs:27:5 | -LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | ------- help: consider changing this to be a mutable reference: `ref mut _x2` -... LL | *_x2 = U; | ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let (ref _x0, _x1, ref mut _x2, ..) = tup; + | ~~~~~~~~~~~ error[E0382]: use of moved value: `tup.1` --> $DIR/borrowck-move-ref-pattern.rs:28:10 diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.rs b/src/test/ui/repr/transparent-enum-too-many-variants.rs new file mode 100644 index 00000000000..0dd4b4e6846 --- /dev/null +++ b/src/test/ui/repr/transparent-enum-too-many-variants.rs @@ -0,0 +1,10 @@ +use std::mem::size_of; + +#[repr(transparent)] +enum Foo { //~ ERROR E0731 + A(u8), B(u8), +} + +fn main() { + println!("Foo: {}", size_of::<Foo>()); +} diff --git a/src/test/ui/repr/transparent-enum-too-many-variants.stderr b/src/test/ui/repr/transparent-enum-too-many-variants.stderr new file mode 100644 index 00000000000..fb44757efaf --- /dev/null +++ b/src/test/ui/repr/transparent-enum-too-many-variants.stderr @@ -0,0 +1,11 @@ +error[E0731]: transparent enum needs exactly one variant, but has 2 + --> $DIR/transparent-enum-too-many-variants.rs:4:1 + | +LL | enum Foo { + | ^^^^^^^^ needs exactly one variant, but has 2 +LL | A(u8), B(u8), + | - - too many variants in `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0731`. diff --git a/src/test/ui/rfc-2091-track-caller/call-chain.rs b/src/test/ui/rfc-2091-track-caller/call-chain.rs index fefb84de729..28b3f76c9d5 100644 --- a/src/test/ui/rfc-2091-track-caller/call-chain.rs +++ b/src/test/ui/rfc-2091-track-caller/call-chain.rs @@ -1,10 +1,14 @@ // run-pass +// revisions: default mir-opt +//[default] compile-flags: -Zinline-mir=no +//[mir-opt] compile-flags: -Zmir-opt-level=4 use std::panic::Location; struct Foo; impl Foo { + #[inline(always)] #[track_caller] fn check_loc(&self, line: u32, col: u32) -> &Self { let loc = Location::caller(); diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs new file mode 100644 index 00000000000..b5f19e40c03 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.rs @@ -0,0 +1,19 @@ +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); +//~^ ERROR: the trait bound + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr new file mode 100644 index 00000000000..4470e287cc3 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `(): ~const Tr` is not satisfied in `fn(()) -> i32 {<() as Tr>::a}` + --> $DIR/const-closure-trait-method-fail.rs:16:42 + | +LL | const _: () = assert!(need_const_closure(Tr::a) == 42); + | ------------------ ^^^^^ within `fn(()) -> i32 {<() as Tr>::a}`, the trait `~const Tr` is not implemented for `()` + | | + | required by a bound introduced by this call + | +note: the trait `Tr` is implemented for `()`, but that implementation is not `const` + --> $DIR/const-closure-trait-method-fail.rs:16:42 + | +LL | const _: () = assert!(need_const_closure(Tr::a) == 42); + | ^^^^^ + = note: required because it appears within the type `fn(()) -> i32 {<() as Tr>::a}` +note: required by a bound in `need_const_closure` + --> $DIR/const-closure-trait-method-fail.rs:12:32 + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `need_const_closure` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs new file mode 100644 index 00000000000..3e6d1908848 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-closure-trait-method.rs @@ -0,0 +1,19 @@ +// check-pass +#![feature(const_trait_impl)] + +#[const_trait] +trait Tr { + fn a(self) -> i32; +} + +impl const Tr for () { + fn a(self) -> i32 { 42 } +} + +const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { + x(()) +} + +const _: () = assert!(need_const_closure(Tr::a) == 42); + +fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed new file mode 100644 index 00000000000..8cdb08e81b9 --- /dev/null +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.fixed @@ -0,0 +1,137 @@ +// edition:2018 +// aux-build:edition-lint-infer-outlives-macro.rs +// run-rustfix + +#![deny(explicit_outlives_requirements)] +#![allow(dead_code)] + +#[macro_use] +extern crate edition_lint_infer_outlives_macro; + +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. +macro_rules! make_foo { + ($a:tt) => { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { + foo: &$a &'b (), + } + } +} + +gimme_a! {make_foo!} + +struct Bar<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +struct BarWhere<'a, 'b> { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b >(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where ; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, ; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs index d7a832831c1..647906c2dc2 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.rs @@ -1,18 +1,22 @@ // edition:2018 // aux-build:edition-lint-infer-outlives-macro.rs - -// Test that the lint does not fire if the where predicate -// is from the local crate, but all the bounds are from an -// external macro. +// run-rustfix #![deny(explicit_outlives_requirements)] +#![allow(dead_code)] #[macro_use] extern crate edition_lint_infer_outlives_macro; +// Test that the lint does not fire if the predicate is from the local crate, +// but all the bounds are from an external macro. macro_rules! make_foo { ($a:tt) => { - struct Foo<$a, 'b> where 'b: $a { + struct Foo<$a, 'b: $a> { + foo: &$a &'b (), + } + + struct FooWhere<$a, 'b> where 'b: $a { foo: &$a &'b (), } } @@ -25,4 +29,109 @@ struct Bar<'a, 'b: 'a> { bar: &'a &'b (), } +struct BarWhere<'a, 'b> where 'b: 'a { + //~^ ERROR: outlives requirements can be inferred + bar: &'a &'b (), +} + +// Test that the lint *does* fire if the predicate is contained in a local macro. +mod everything_inside { + macro_rules! m { + ('b: 'a) => { + struct Foo<'a, 'b: 'a>(&'a &'b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + //~^ ERROR: outlives requirements can be inferred + }; + } + m!('b: 'a); +} + +mod inner_lifetime_outside_colon_inside { + macro_rules! m { + ($b:lifetime: 'a) => { + struct Foo<'a, $b: 'a>(&'a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + +mod outer_lifetime_outside_colon_inside { + macro_rules! m { + ('b: $a:lifetime) => { + struct Foo<$a, 'b: $a>(&$a &'b ()); + struct Bar<$a, 'b>(&$a &'b ()) where 'b: $a; + struct Baz<$a, 'b>(&$a &'b ()) where (): Sized, 'b: $a; + } + } + m!('b: 'a); +} + +mod both_lifetimes_outside_colon_inside { + macro_rules! m { + ($b:lifetime: $a:lifetime) => { + struct Foo<$a, $b: $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b: $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b: $a; + } + } + m!('b: 'a); +} + +mod everything_outside { + macro_rules! m { + ($b:lifetime $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_inner { + macro_rules! m { + ($b:tt $colon:tt $a:lifetime) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +// FIXME: These should be consistent. +mod everything_outside_with_tt_outer { + macro_rules! m { + ($b:lifetime $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + } + } + m!('b: 'a); +} + +mod everything_outside_with_tt_both { + macro_rules! m { + ($b:tt $colon:tt $a:tt) => { + struct Foo<$a, $b $colon $a>(&$a &$b ()); + //~^ ERROR: outlives requirements can be inferred + struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + //~^ ERROR: outlives requirements can be inferred + } + } + m!('b: 'a); +} + fn main() {} diff --git a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr index 553b1cd976a..734ae687978 100644 --- a/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr +++ b/src/test/ui/rust-2018/edition-lint-infer-outlives-macro.stderr @@ -1,14 +1,110 @@ error: outlives requirements can be inferred - --> $DIR/edition-lint-infer-outlives-macro.rs:23:18 + --> $DIR/edition-lint-infer-outlives-macro.rs:27:18 | LL | struct Bar<'a, 'b: 'a> { | ^^^^ help: remove this bound | note: the lint level is defined here - --> $DIR/edition-lint-infer-outlives-macro.rs:8:9 + --> $DIR/edition-lint-infer-outlives-macro.rs:5:9 | LL | #![deny(explicit_outlives_requirements)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:32:24 + | +LL | struct BarWhere<'a, 'b> where 'b: 'a { + | ^^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:41:30 + | +LL | struct Foo<'a, 'b: 'a>(&'a &'b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:43:44 + | +LL | struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:45:61 + | +LL | struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:55:30 + | +LL | struct Foo<'a, $b: 'a>(&'a &$b ()); + | ^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:57:44 + | +LL | struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; + | ^^^^^^^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:59:61 + | +LL | struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; + | ^^^^^^ help: remove this bound +... +LL | m!('b: 'a); + | ---------- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:114:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:126:31 + | +LL | struct Foo<$a, $b $colon $a>(&$a &$b ()); + | ^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:128:50 + | +LL | struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: outlives requirements can be inferred + --> $DIR/edition-lint-infer-outlives-macro.rs:130:61 + | +LL | struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; + | ^^^^^^^^^^^^ help: remove this bound + +error: aborting due to 12 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr index e4ec9f87576..570328fc211 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr @@ -1,18 +1,24 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:53:24 | -LL | fn deref_mut_field1(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | let __isize = &mut x.y; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_field1(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:65:10 | -LL | fn deref_extend_mut_field1(x: &Own<Point>) -> &mut isize { - | ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>` LL | &mut x.y | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_field1(x: &mut Own<Point>) -> &mut isize { + | ~~~~~~~~~~~~~~~ error[E0499]: cannot borrow `*x` as mutable more than once at a time --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:78:19 @@ -27,18 +33,24 @@ LL | use_mut(_x); error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:88:5 | -LL | fn assign_field1<'a>(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | x.y = 3; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_field1<'a>(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:92:5 | -LL | fn assign_field2<'a>(x: &'a Own<Point>) { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>` LL | x.y = 3; | ^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_field2<'a>(x: &'a mut Own<Point>) { + | ~~~~~~~~~~~~~~~~~~ error[E0499]: cannot borrow `*x` as mutable more than once at a time --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:101:5 @@ -53,34 +65,46 @@ LL | use_mut(_p); error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:109:5 | -LL | fn deref_mut_method1(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | x.set(0, 0); | ^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut_method1(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:121:5 | -LL | fn deref_extend_mut_method1(x: &Own<Point>) -> &mut isize { - | ----------- help: consider changing this to be a mutable reference: `&mut Own<Point>` LL | x.y_mut() | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut_method1(x: &mut Own<Point>) -> &mut isize { + | ~~~~~~~~~~~~~~~ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:129:6 | -LL | fn assign_method1<'a>(x: Own<Point>) { - | - help: consider changing this to be mutable: `mut x` LL | *x.y_mut() = 3; | ^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign_method1<'a>(mut x: Own<Point>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:133:6 | -LL | fn assign_method2<'a>(x: &'a Own<Point>) { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<Point>` LL | *x.y_mut() = 3; | ^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign_method2<'a>(x: &'a mut Own<Point>) { + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 10 previous errors diff --git a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr index 3ebfba7e4de..3fed7b3f4dc 100644 --- a/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr +++ b/src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr @@ -1,34 +1,46 @@ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:29:25 | -LL | fn deref_mut1(x: Own<isize>) { - | - help: consider changing this to be mutable: `mut x` LL | let __isize = &mut *x; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn deref_mut1(mut x: Own<isize>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:41:11 | -LL | fn deref_extend_mut1<'a>(x: &'a Own<isize>) -> &'a mut isize { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>` LL | &mut **x | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn deref_extend_mut1<'a>(x: &'a mut Own<isize>) -> &'a mut isize { + | ~~~~~~~~~~~~~~~~~~ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:49:6 | -LL | fn assign1<'a>(x: Own<isize>) { - | - help: consider changing this to be mutable: `mut x` LL | *x = 3; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn assign1<'a>(mut x: Own<isize>) { + | +++ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:53:6 | -LL | fn assign2<'a>(x: &'a Own<isize>) { - | -------------- help: consider changing this to be a mutable reference: `&'a mut Own<isize>` LL | **x = 3; | ^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn assign2<'a>(x: &'a mut Own<isize>) { + | ~~~~~~~~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 6b43801b5e0..48b42bc7825 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -13,18 +13,24 @@ LL | f((Box::new(|| {}))) error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference --> $DIR/borrowck-call-is-borrow-issue-12224.rs:25:5 | -LL | fn test2<F>(f: &F) where F: FnMut() { - | -- help: consider changing this to be a mutable reference: `&mut F` LL | (*f)(); | ^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test2<F>(f: &mut F) where F: FnMut() { + | ~~~~~~ error[E0596]: cannot borrow `f.f` as mutable, as it is behind a `&` reference --> $DIR/borrowck-call-is-borrow-issue-12224.rs:34:5 | -LL | fn test4(f: &Test) { - | ----- help: consider changing this to be a mutable reference: `&mut Test<'_>` LL | f.f.call_mut(()) | ^^^^^^^^^^^^^^^^ `f` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn test4(f: &mut Test<'_>) { + | ~~~~~~~~~~~~~ error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13 diff --git a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr index 1864f5de108..2a842f5a2a9 100644 --- a/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr +++ b/src/test/ui/span/borrowck-call-method-from-mut-aliasable.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-call-method-from-mut-aliasable.rs:17:5 | -LL | fn b(x: &Foo) { - | ---- help: consider changing this to be a mutable reference: `&mut Foo` -LL | x.f(); LL | x.h(); | ^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn b(x: &mut Foo) { + | ~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-fn-in-const-b.stderr b/src/test/ui/span/borrowck-fn-in-const-b.stderr index 1f5d8bd32bb..1df19deb12f 100644 --- a/src/test/ui/span/borrowck-fn-in-const-b.stderr +++ b/src/test/ui/span/borrowck-fn-in-const-b.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-fn-in-const-b.rs:7:9 | -LL | fn broken(x: &Vec<String>) { - | ------------ help: consider changing this to be a mutable reference: `&mut Vec<String>` LL | x.push(format!("this is broken")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn broken(x: &mut Vec<String>) { + | ~~~~~~~~~~~~~~~~ error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-object-mutability.stderr b/src/test/ui/span/borrowck-object-mutability.stderr index cc43f6d0928..b6517e0b309 100644 --- a/src/test/ui/span/borrowck-object-mutability.stderr +++ b/src/test/ui/span/borrowck-object-mutability.stderr @@ -1,20 +1,24 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference --> $DIR/borrowck-object-mutability.rs:8:5 | -LL | fn borrowed_receiver(x: &dyn Foo) { - | -------- help: consider changing this to be a mutable reference: `&mut dyn Foo` -LL | x.borrowed(); LL | x.borrowed_mut(); | ^^^^^^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn borrowed_receiver(x: &mut dyn Foo) { + | ~~~~~~~~~~~~ error[E0596]: cannot borrow `*x` as mutable, as `x` is not declared as mutable --> $DIR/borrowck-object-mutability.rs:18:5 | -LL | fn owned_receiver(x: Box<dyn Foo>) { - | - help: consider changing this to be mutable: `mut x` -LL | x.borrowed(); LL | x.borrowed_mut(); | ^^^^^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn owned_receiver(mut x: Box<dyn Foo>) { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index 8a7c504f005..96ce4d5bc6c 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -1,26 +1,35 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:3:9 | -LL | fn foo(mut a: &String) { - | ------- help: consider changing this to be a mutable reference: `&mut String` LL | a.push_str("bar"); | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:8:5 | -LL | pub fn foo<'a>(mut a: &'a String) { - | ---------- help: consider changing this to be a mutable reference: `&'a mut String` LL | a.push_str("foo"); | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo<'a>(mut a: &'a mut String) { + | ~~~~~~~~~~~~~~ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference --> $DIR/mut-arg-hint.rs:15:9 | -LL | pub fn foo(mut a: &String) { - | ------- help: consider changing this to be a mutable reference: `&mut String` LL | a.push_str("foo"); | ^^^^^^^^^^^^^^^^^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | pub fn foo(mut a: &mut String) { + | ~~~~~~~~~~~ error: aborting due to 3 previous errors diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 15900bef7f6..7d9ff2dfb4d 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -41,8 +41,8 @@ ast-stats-1 - Wild 88 ( 1.2%) 1 ast-stats-1 - Ident 440 ( 5.9%) 5 ast-stats-1 PathSegment 720 ( 9.7%) 30 24 ast-stats-1 Ty 896 (12.1%) 14 64 -ast-stats-1 - Rptr 64 ( 0.9%) 1 ast-stats-1 - Ptr 64 ( 0.9%) 1 +ast-stats-1 - Ref 64 ( 0.9%) 1 ast-stats-1 - ImplicitSelf 128 ( 1.7%) 2 ast-stats-1 - Path 640 ( 8.6%) 10 ast-stats-1 Item 1_656 (22.3%) 9 184 @@ -100,8 +100,8 @@ ast-stats-2 - Lit 144 ( 1.8%) 2 ast-stats-2 - Block 216 ( 2.7%) 3 ast-stats-2 PathSegment 792 ( 9.8%) 33 24 ast-stats-2 Ty 896 (11.0%) 14 64 -ast-stats-2 - Rptr 64 ( 0.8%) 1 ast-stats-2 - Ptr 64 ( 0.8%) 1 +ast-stats-2 - Ref 64 ( 0.8%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.6%) 2 ast-stats-2 - Path 640 ( 7.9%) 10 ast-stats-2 Item 2_024 (25.0%) 11 184 @@ -154,7 +154,7 @@ hir-stats GenericParam 400 ( 4.4%) 5 80 hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 -hir-stats - Rptr 48 ( 0.5%) 1 +hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Path 624 ( 6.9%) 13 hir-stats Expr 768 ( 8.5%) 12 64 hir-stats - Path 64 ( 0.7%) 1 diff --git a/src/test/ui/suggestions/bad-hex-float-lit.rs b/src/test/ui/suggestions/bad-hex-float-lit.rs new file mode 100644 index 00000000000..cd6fdbde96c --- /dev/null +++ b/src/test/ui/suggestions/bad-hex-float-lit.rs @@ -0,0 +1,13 @@ +fn main() { + let _f: f32 = 0xAAf32; + //~^ ERROR mismatched types + //~| HELP rewrite this + + let _f: f32 = 0xAB_f32; + //~^ ERROR mismatched types + //~| HELP rewrite this + + let _f: f64 = 0xFF_f64; + //~^ ERROR mismatched types + //~| HELP rewrite this +} diff --git a/src/test/ui/suggestions/bad-hex-float-lit.stderr b/src/test/ui/suggestions/bad-hex-float-lit.stderr new file mode 100644 index 00000000000..bc09abb1a56 --- /dev/null +++ b/src/test/ui/suggestions/bad-hex-float-lit.stderr @@ -0,0 +1,48 @@ +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:2:19 + | +LL | let _f: f32 = 0xAAf32; + | --- ^^^^^^^ expected `f32`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f32 = 0xAA as f32; + | ~~~~~~~~~~~ +LL | let _f: f32 = 170_f32; + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:6:19 + | +LL | let _f: f32 = 0xAB_f32; + | --- ^^^^^^^^ expected `f32`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f32 = 0xAB as f32; + | ~~~~~~~~~~~ +LL | let _f: f32 = 171_f32; + | ~~~~~~~ + +error[E0308]: mismatched types + --> $DIR/bad-hex-float-lit.rs:10:19 + | +LL | let _f: f64 = 0xFF_f64; + | --- ^^^^^^^^ expected `f64`, found integer + | | + | expected due to this + | +help: rewrite this as a decimal floating point literal, or use `as` to turn a hex literal into a float + | +LL | let _f: f64 = 0xFF as f64; + | ~~~~~~~~~~~ +LL | let _f: f64 = 255_f64; + | ~~~~~~~ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-104287.rs b/src/test/ui/suggestions/issue-104287.rs index b7601a548b9..e3fa22a8f66 100644 --- a/src/test/ui/suggestions/issue-104287.rs +++ b/src/test/ui/suggestions/issue-104287.rs @@ -1,9 +1,13 @@ // The purpose of this test is not to validate the output of the compiler. // Instead, it ensures the suggestion is generated without performing an arithmetic overflow. +struct S; +impl S { + fn foo(&self) {} +} fn main() { - let x = not_found; //~ ERROR cannot find value `not_found` in this scope - simd_gt::<()>(x); + let x = S; + foo::<()>(x); //~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied - //~| ERROR cannot find function `simd_gt` in this scope + //~| ERROR cannot find function `foo` in this scope } diff --git a/src/test/ui/suggestions/issue-104287.stderr b/src/test/ui/suggestions/issue-104287.stderr index 79812a2985e..602a01828b2 100644 --- a/src/test/ui/suggestions/issue-104287.stderr +++ b/src/test/ui/suggestions/issue-104287.stderr @@ -1,30 +1,30 @@ -error[E0425]: cannot find value `not_found` in this scope - --> $DIR/issue-104287.rs:5:13 - | -LL | let x = not_found; - | ^^^^^^^^^ not found in this scope - error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/issue-104287.rs:6:5 + --> $DIR/issue-104287.rs:10:5 | -LL | simd_gt::<()>(x); - | ^^^^^^^------ help: remove these generics +LL | foo::<()>(x); + | ^^^------ help: remove these generics | | | expected 0 generic arguments + | +note: associated function defined here, with 0 generic parameters + --> $DIR/issue-104287.rs:6:8 + | +LL | fn foo(&self) {} + | ^^^ -error[E0425]: cannot find function `simd_gt` in this scope - --> $DIR/issue-104287.rs:6:5 +error[E0425]: cannot find function `foo` in this scope + --> $DIR/issue-104287.rs:10:5 | -LL | simd_gt::<()>(x); - | ^^^^^^^ not found in this scope +LL | foo::<()>(x); + | ^^^ not found in this scope | -help: use the `.` operator to call the method `SimdPartialOrd::simd_gt` on `[type error]` +help: use the `.` operator to call the method `foo` on `&S` | -LL - simd_gt::<()>(x); -LL + x.simd_gt(); +LL - foo::<()>(x); +LL + x.foo(); | -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0107, E0425. For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/suggestions/issue-105494.rs b/src/test/ui/suggestions/issue-105494.rs new file mode 100644 index 00000000000..8b409232c20 --- /dev/null +++ b/src/test/ui/suggestions/issue-105494.rs @@ -0,0 +1,22 @@ +fn test1() { + let _v: i32 = (1 as i32).to_string(); //~ ERROR mismatched types + + // won't suggestion + let _v: i32 = (1 as i128).to_string(); //~ ERROR mismatched types + + let _v: &str = "foo".to_string(); //~ ERROR mismatched types +} + +fn test2() { + let mut path: String = "/usr".to_string(); + let folder: String = "lib".to_string(); + + path = format!("{}/{}", path, folder).as_str(); //~ ERROR mismatched types + + println!("{}", &path); +} + +fn main() { + test1(); + test2(); +} diff --git a/src/test/ui/suggestions/issue-105494.stderr b/src/test/ui/suggestions/issue-105494.stderr new file mode 100644 index 00000000000..5aa3f2af738 --- /dev/null +++ b/src/test/ui/suggestions/issue-105494.stderr @@ -0,0 +1,54 @@ +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:2:19 + | +LL | let _v: i32 = (1 as i32).to_string(); + | --- ^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String` + | | + | expected due to this + | +help: try removing the method call + | +LL - let _v: i32 = (1 as i32).to_string(); +LL + let _v: i32 = (1 as i32); + | + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:5:19 + | +LL | let _v: i32 = (1 as i128).to_string(); + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `String` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:7:20 + | +LL | let _v: &str = "foo".to_string(); + | ---- ^^^^^^^^^^^^^^^^^ expected `&str`, found struct `String` + | | + | expected due to this + | +help: try removing the method call + | +LL - let _v: &str = "foo".to_string(); +LL + let _v: &str = "foo"; + | + +error[E0308]: mismatched types + --> $DIR/issue-105494.rs:14:12 + | +LL | let mut path: String = "/usr".to_string(); + | ------ expected due to this type +... +LL | path = format!("{}/{}", path, folder).as_str(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `String`, found `&str` + | +help: try removing the method call + | +LL - path = format!("{}/{}", path, folder).as_str(); +LL + path = format!("{}/{}", path, folder); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-68049-2.stderr b/src/test/ui/suggestions/issue-68049-2.stderr index 2f31193e4a4..de35aa5b186 100644 --- a/src/test/ui/suggestions/issue-68049-2.stderr +++ b/src/test/ui/suggestions/issue-68049-2.stderr @@ -1,20 +1,24 @@ error[E0594]: cannot assign to `*input`, which is behind a `&` reference --> $DIR/issue-68049-2.rs:9:7 | -LL | fn example(&self, input: &i32); // should suggest here - | ---- help: consider changing that to be a mutable reference: `&mut i32` -... LL | *input = self.0; | ^^^^^^^^^^^^^^^ `input` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing that to be a mutable reference + | +LL | fn example(&self, input: &mut i32); // should suggest here + | ~~~~~~~~ error[E0594]: cannot assign to `self.0`, which is behind a `&` reference --> $DIR/issue-68049-2.rs:17:5 | -LL | fn example(&self, input: &i32); // should suggest here - | ----- help: consider changing that to be a mutable reference: `&mut self` -... LL | self.0 += *input; | ^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing that to be a mutable reference + | +LL | fn example(&mut self, input: &i32); // should suggest here + | ~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-99240-2.stderr b/src/test/ui/suggestions/issue-99240-2.stderr index 260df85653b..a2b55978478 100644 --- a/src/test/ui/suggestions/issue-99240-2.stderr +++ b/src/test/ui/suggestions/issue-99240-2.stderr @@ -4,10 +4,7 @@ error[E0618]: expected function, found enum variant `Alias::Unit` LL | Unit, | ---- enum variant `Alias::Unit` defined here ... -LL | Alias:: - | ______^ - | | _____| - | || +LL | // Alias:: LL | || Unit(); | ||________^_- call expression requires function | |________| diff --git a/src/test/ui/suggestions/method-access-to-range-literal-typo.rs b/src/test/ui/suggestions/method-access-to-range-literal-typo.rs new file mode 100644 index 00000000000..ac662edafe6 --- /dev/null +++ b/src/test/ui/suggestions/method-access-to-range-literal-typo.rs @@ -0,0 +1,30 @@ +fn as_ref() -> Option<Vec<u8>> { + None +} +struct Type { + option: Option<Vec<u8>> +} +trait Trait { + fn foo(&self) -> Vec<u8>; +} +impl Trait for Option<Vec<u8>> { + fn foo(&self) -> Vec<u8> { + vec![1, 2, 3] + } +} + +impl Type { + fn method(&self) -> Option<Vec<u8>> { + self.option..as_ref().map(|x| x) + //~^ ERROR E0308 + } + fn method2(&self) -> &u8 { + self.option..foo().get(0) + //~^ ERROR E0425 + //~| ERROR E0308 + } +} + +fn main() { + let _ = Type { option: None }.method(); +} diff --git a/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr b/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr new file mode 100644 index 00000000000..c84f9467891 --- /dev/null +++ b/src/test/ui/suggestions/method-access-to-range-literal-typo.stderr @@ -0,0 +1,48 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/method-access-to-range-literal-typo.rs:22:22 + | +LL | self.option..foo().get(0) + | ^^^ not found in this scope + | +help: you might have meant to write `.` instead of `..` + | +LL - self.option..foo().get(0) +LL + self.option.foo().get(0) + | + +error[E0308]: mismatched types + --> $DIR/method-access-to-range-literal-typo.rs:18:9 + | +LL | fn method(&self) -> Option<Vec<u8>> { + | --------------- expected `Option<Vec<u8>>` because of return type +LL | self.option..as_ref().map(|x| x) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Option`, found struct `Range` + | + = note: expected enum `Option<_>` + found struct `std::ops::Range<Option<_>>` +help: you likely meant to write a method call instead of a range + | +LL - self.option..as_ref().map(|x| x) +LL + self.option.as_ref().map(|x| x) + | + +error[E0308]: mismatched types + --> $DIR/method-access-to-range-literal-typo.rs:22:9 + | +LL | fn method2(&self) -> &u8 { + | --- expected `&u8` because of return type +LL | self.option..foo().get(0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&u8`, found struct `Range` + | + = note: expected reference `&u8` + found struct `std::ops::Range<Option<Vec<u8>>>` +help: you likely meant to write a method call instead of a range + | +LL - self.option..foo().get(0) +LL + self.option.foo().get(0) + | + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/option-content-move.stderr b/src/test/ui/suggestions/option-content-move.stderr index 3e0271d0257..474a72093c6 100644 --- a/src/test/ui/suggestions/option-content-move.stderr +++ b/src/test/ui/suggestions/option-content-move.stderr @@ -9,6 +9,10 @@ LL | if selection.1.unwrap().contains(selection.0) { | note: `Option::<T>::unwrap` takes ownership of the receiver `self`, which moves `selection.1` --> $SRC_DIR/core/src/option.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | if selection.1.clone().unwrap().contains(selection.0) { + | ++++++++ error[E0507]: cannot move out of `selection.1` which is behind a shared reference --> $DIR/option-content-move.rs:27:20 @@ -21,6 +25,10 @@ LL | if selection.1.unwrap().contains(selection.0) { | note: `Result::<T, E>::unwrap` takes ownership of the receiver `self`, which moves `selection.1` --> $SRC_DIR/core/src/result.rs:LL:COL +help: you can `clone` the value and consume it, but this might not be your desired behavior + | +LL | if selection.1.clone().unwrap().contains(selection.0) { + | ++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/shadowed-lplace-method-2.rs b/src/test/ui/suggestions/shadowed-lplace-method-2.rs new file mode 100644 index 00000000000..dab99fbacd9 --- /dev/null +++ b/src/test/ui/suggestions/shadowed-lplace-method-2.rs @@ -0,0 +1,23 @@ +#![allow(unused)] + +struct X { + x: (), +} +pub trait A { + fn foo(&mut self, _: usize) -> &mut (); +} +impl A for X { + fn foo(&mut self, _: usize) -> &mut () { + &mut self.x + } +} +impl X { + fn foo(&mut self, _: usize) -> &mut Self { + self + } +} + +fn main() { + let mut x = X { x: () }; + *x.foo(0) = (); //~ ERROR E0308 +} diff --git a/src/test/ui/suggestions/shadowed-lplace-method-2.stderr b/src/test/ui/suggestions/shadowed-lplace-method-2.stderr new file mode 100644 index 00000000000..94eef15f330 --- /dev/null +++ b/src/test/ui/suggestions/shadowed-lplace-method-2.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/shadowed-lplace-method-2.rs:22:17 + | +LL | *x.foo(0) = (); + | --------- ^^ expected struct `X`, found `()` + | | + | expected due to the type of this binding + | +note: the `foo` call is resolved to the method in `X`, shadowing the method of the same name on trait `A` + --> $DIR/shadowed-lplace-method-2.rs:22:8 + | +LL | *x.foo(0) = (); + | ^^^ refers to `X::foo` +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL | *<_ as A>::foo(&mut x, 0) = (); + | ++++++++++++++++++ ~ +help: try wrapping the expression in `X` + | +LL | *x.foo(0) = X { x: () }; + | ++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/shadowed-lplace-method.fixed b/src/test/ui/suggestions/shadowed-lplace-method.fixed new file mode 100644 index 00000000000..740ac77ee0c --- /dev/null +++ b/src/test/ui/suggestions/shadowed-lplace-method.fixed @@ -0,0 +1,10 @@ +// run-rustfix +#![allow(unused_imports)] +use std::borrow::BorrowMut; +use std::cell::RefCell; +use std::rc::Rc; + +fn main() { + let rc = Rc::new(RefCell::new(true)); + *std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308 +} diff --git a/src/test/ui/suggestions/shadowed-lplace-method.rs b/src/test/ui/suggestions/shadowed-lplace-method.rs new file mode 100644 index 00000000000..6bf12879e6f --- /dev/null +++ b/src/test/ui/suggestions/shadowed-lplace-method.rs @@ -0,0 +1,10 @@ +// run-rustfix +#![allow(unused_imports)] +use std::borrow::BorrowMut; +use std::cell::RefCell; +use std::rc::Rc; + +fn main() { + let rc = Rc::new(RefCell::new(true)); + *rc.borrow_mut() = false; //~ ERROR E0308 +} diff --git a/src/test/ui/suggestions/shadowed-lplace-method.stderr b/src/test/ui/suggestions/shadowed-lplace-method.stderr new file mode 100644 index 00000000000..91d0d1200d4 --- /dev/null +++ b/src/test/ui/suggestions/shadowed-lplace-method.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/shadowed-lplace-method.rs:9:24 + | +LL | *rc.borrow_mut() = false; + | ---------------- ^^^^^ expected struct `Rc`, found `bool` + | | + | expected due to the type of this binding + | + = note: expected struct `Rc<RefCell<bool>>` + found type `bool` +note: the `borrow_mut` call is resolved to the method in `std::borrow::BorrowMut`, shadowing the method of the same name on the inherent impl for `std::cell::RefCell<T>` + --> $DIR/shadowed-lplace-method.rs:9:9 + | +LL | use std::borrow::BorrowMut; + | ---------------------- `std::borrow::BorrowMut` imported here +... +LL | *rc.borrow_mut() = false; + | ^^^^^^^^^^ refers to `std::borrow::BorrowMut::borrow_mut` +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL | *std::cell::RefCell::<_>::borrow_mut(&rc) = false; + | +++++++++++++++++++++++++++++++++++++ ~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggestions/suggest-ref-mut.stderr index 9fd2658ec70..7973759bf5e 100644 --- a/src/test/ui/suggestions/suggest-ref-mut.stderr +++ b/src/test/ui/suggestions/suggest-ref-mut.stderr @@ -1,37 +1,46 @@ error[E0594]: cannot assign to `self.0`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:7:9 | -LL | fn zap(&self) { - | ----- help: consider changing this to be a mutable reference: `&mut self` -... LL | self.0 = 32; | ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | fn zap(&mut self) { + | ~~~~~~~~~ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:16:5 | -LL | let ref foo = 16; - | ------- help: consider changing this to be a mutable reference: `ref mut foo` -... LL | *foo = 32; | ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | let ref mut foo = 16; + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*bar`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:21:9 | -LL | if let Some(ref bar) = Some(16) { - | ------- help: consider changing this to be a mutable reference: `ref mut bar` -... LL | *bar = 32; | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | if let Some(ref mut bar) = Some(16) { + | ~~~~~~~~~~~ error[E0594]: cannot assign to `*quo`, which is behind a `&` reference --> $DIR/suggest-ref-mut.rs:25:22 | LL | ref quo => { *quo = 32; }, - | ------- ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written - | | - | help: consider changing this to be a mutable reference: `ref mut quo` + | ^^^^^^^^^ `quo` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | ref mut quo => { *quo = 32; }, + | ~~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/src/test/ui/suggestions/unnamable-types.stderr b/src/test/ui/suggestions/unnamable-types.stderr index ede3ebfa739..24bedb5297b 100644 --- a/src/test/ui/suggestions/unnamable-types.stderr +++ b/src/test/ui/suggestions/unnamable-types.stderr @@ -19,7 +19,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | const C: _ = || 42; | ^ not allowed in type signatures | -note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:16]` cannot be named +note: however, the inferred type `[closure@unnamable-types.rs:17:14]` cannot be named --> $DIR/unnamable-types.rs:17:14 | LL | const C: _ = || 42; @@ -31,7 +31,7 @@ error: missing type for `const` item LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; | ^ | -note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named +note: however, the inferred type `S<[closure@unnamable-types.rs:23:31]>` cannot be named --> $DIR/unnamable-types.rs:23:11 | LL | const D = S { t: { let i = 0; move || -> i32 { i } } }; diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout index 7fb90581f8a..4b6915f7715 100644 --- a/src/test/ui/thir-tree.stdout +++ b/src/test/ui/thir-tree.stdout @@ -32,12 +32,7 @@ Thir { kind: Scope { region_scope: Node(2), lint_level: Explicit( - HirId { - owner: OwnerId { - def_id: DefId(0:3 ~ thir_tree[8f1d]::main), - }, - local_id: 2, - }, + HirId(DefId(0:3 ~ thir_tree[8f1d]::main).2), ), value: e0, }, diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr index 41fc3600fcd..30cc76b2e1a 100644 --- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -50,7 +50,7 @@ LL | is_send((8, TestType)); | required by a bound introduced by this call | = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType` - = note: required because it appears within the type `({integer}, dummy1c::TestType)` + = note: required because it appears within the type `({integer}, TestType)` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 | @@ -67,7 +67,7 @@ LL | is_send(Box::new(TestType)); | = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied = note: required for `Unique<dummy2::TestType>` to implement `Send` - = note: required because it appears within the type `Box<dummy2::TestType>` + = note: required because it appears within the type `Box<TestType>` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 | @@ -87,13 +87,13 @@ LL | is_send(Box::new(Outer2(TestType))); | required by a bound introduced by this call | = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType` -note: required because it appears within the type `Outer2<dummy3::TestType>` +note: required because it appears within the type `Outer2<TestType>` --> $DIR/negated-auto-traits-error.rs:12:8 | LL | struct Outer2<T>(T); | ^^^^^^ = note: required for `Unique<Outer2<dummy3::TestType>>` to implement `Send` - = note: required because it appears within the type `Box<Outer2<dummy3::TestType>>` + = note: required because it appears within the type `Box<Outer2<TestType>>` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 | diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr index aac119afda5..39b60c31197 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-copy-reborrow.stderr @@ -1,18 +1,24 @@ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:6:5 | -LL | fn reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { - | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` LL | *t | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn reborrow_mut<'a>(t: &'a mut &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | ~~~~~~~~~~~~~~~~~~~ error[E0596]: cannot borrow `**t` as mutable, as it is behind a `&` reference --> $DIR/trivial-bounds-inconsistent-copy-reborrow.rs:10:6 | -LL | fn copy_reborrow_mut<'a>(t: &'a &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { - | --------------- help: consider changing this to be a mutable reference: `&'a mut &'a mut i32` LL | {*t} | ^^ `t` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this to be a mutable reference + | +LL | fn copy_reborrow_mut<'a>(t: &'a mut &'a mut i32) -> &'a mut i32 where &'a mut i32: Copy { + | ~~~~~~~~~~~~~~~~~~~ error: aborting due to 2 previous errors diff --git a/src/test/ui/type/issue-102598.rs b/src/test/ui/type/issue-102598.rs new file mode 100644 index 00000000000..93808f18b99 --- /dev/null +++ b/src/test/ui/type/issue-102598.rs @@ -0,0 +1,8 @@ +fn foo<'a>(_: impl 'a Sized) {} +//~^ ERROR: expected `+` between lifetime and Sized +//~| ERROR: expected one of `:`, `@`, or `|`, found `)` +//~| ERROR: expected one of `)`, `+`, or `,`, found `Sized` +//~| ERROR: at least one trait must be specified + +fn main(){ +} diff --git a/src/test/ui/type/issue-102598.stderr b/src/test/ui/type/issue-102598.stderr new file mode 100644 index 00000000000..a232395cedb --- /dev/null +++ b/src/test/ui/type/issue-102598.stderr @@ -0,0 +1,43 @@ +error: expected `+` between lifetime and Sized + --> $DIR/issue-102598.rs:1:20 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^^ + | +help: add `+` + | +LL | fn foo<'a>(_: impl 'a + Sized) {} + | + + +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/issue-102598.rs:1:28 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^ expected one of `:`, `@`, or `|` + | + = note: anonymous parameters are removed in the 2018 edition (see RFC 1685) +help: if this is a parameter name, give it a type + | +LL | fn foo<'a>(_: impl 'a Sized: TypeName) {} + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn foo<'a>(_: impl 'a _: Sized) {} + | ++ + +error: expected one of `)`, `+`, or `,`, found `Sized` + --> $DIR/issue-102598.rs:1:23 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | -^^^^^ expected one of `)`, `+`, or `,` + | | + | help: missing `,` + +error: at least one trait must be specified + --> $DIR/issue-102598.rs:1:15 + | +LL | fn foo<'a>(_: impl 'a Sized) {} + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/typeck/nonexistent-field-not-ambiguous.rs b/src/test/ui/typeck/nonexistent-field-not-ambiguous.rs new file mode 100644 index 00000000000..1cd192b783c --- /dev/null +++ b/src/test/ui/typeck/nonexistent-field-not-ambiguous.rs @@ -0,0 +1,8 @@ +struct Foo { + val: MissingType, + //~^ ERROR cannot find type `MissingType` in this scope +} + +fn main() { + Foo { val: Default::default() }; +} diff --git a/src/test/ui/typeck/nonexistent-field-not-ambiguous.stderr b/src/test/ui/typeck/nonexistent-field-not-ambiguous.stderr new file mode 100644 index 00000000000..76a2a5f99f2 --- /dev/null +++ b/src/test/ui/typeck/nonexistent-field-not-ambiguous.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `MissingType` in this scope + --> $DIR/nonexistent-field-not-ambiguous.rs:2:10 + | +LL | val: MissingType, + | ^^^^^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/typeck/quiet-type-err-let-binding.rs b/src/test/ui/typeck/quiet-type-err-let-binding.rs new file mode 100644 index 00000000000..a6eab536a6b --- /dev/null +++ b/src/test/ui/typeck/quiet-type-err-let-binding.rs @@ -0,0 +1,17 @@ +// fn foo() -> String { +// String::new() +// } + +fn test(s: &str) { + println!("{}", s); +} + +fn test2(s: String) { + println!("{}", s); +} + +fn main() { + let x = foo(); //~ERROR cannot find function `foo` in this scope + test(&x); + test2(x); // Does not complain about `x` being a `&str`. +} diff --git a/src/test/ui/typeck/quiet-type-err-let-binding.stderr b/src/test/ui/typeck/quiet-type-err-let-binding.stderr new file mode 100644 index 00000000000..ad7f85e01ec --- /dev/null +++ b/src/test/ui/typeck/quiet-type-err-let-binding.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `foo` in this scope + --> $DIR/quiet-type-err-let-binding.rs:14:13 + | +LL | let x = foo(); + | ^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 22fedb22d66..b96c5271339 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -220,3 +220,11 @@ fn value() -> Option<&'static _> { const _: Option<_> = map(value); //~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants + +fn evens_squared(n: usize) -> _ { +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types + (1..n).filter(|x| x % 2 == 0).map(|x| x * x) +} + +const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index c57f71b8057..bc02547c65e 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -428,6 +428,27 @@ LL | const _: Option<_> = map(value); | not allowed in type signatures | help: replace with the correct type: `Option<u8>` +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/typeck_type_placeholder_item.rs:224:31 + | +LL | fn evens_squared(n: usize) -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Iterator<Item = usize>` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/typeck_type_placeholder_item.rs:229:10 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^ not allowed in type signatures + | +note: however, the inferred type `Map<Filter<Range<i32>, [closure@typeck_type_placeholder_item.rs:229:29]>, [closure@typeck_type_placeholder_item.rs:229:49]>` cannot be named + --> $DIR/typeck_type_placeholder_item.rs:229:14 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:140:31 | @@ -636,7 +657,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error: aborting due to 69 previous errors +error: aborting due to 71 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr index a0ed56d4bcf..5c93ed6d7f7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.stderr @@ -12,13 +12,16 @@ LL | tick1(); error[E0596]: cannot borrow `tick2` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-calling-fnmut-no-mut.rs:19:5 | -LL | let tick2 = || { - | ----- help: consider changing this to be mutable: `mut tick2` LL | tick1(); | ----- calling `tick2` requires mutable binding due to mutable borrow of `tick1` ... LL | tick2(); | ^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick2 = || { + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr index 27d23e3fa04..3f539c42d9b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-missing-mut.stderr @@ -2,11 +2,14 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-missing-mut.rs:7:5 | LL | let tick = || counter += 1; - | ---- ------- calling `tick` requires mutable binding due to mutable borrow of `counter` - | | - | help: consider changing this to be mutable: `mut tick` + | ------- calling `tick` requires mutable binding due to mutable borrow of `counter` LL | tick(); | ^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick = || counter += 1; + | +++ error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr index c00f986c397..e3b19297b9c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnmut-move-missing-mut.stderr @@ -2,11 +2,14 @@ error[E0596]: cannot borrow `tick` as mutable, as it is not declared as mutable --> $DIR/unboxed-closures-infer-fnmut-move-missing-mut.rs:7:5 | LL | let tick = move || counter += 1; - | ---- ------- calling `tick` requires mutable binding due to possible mutation of `counter` - | | - | help: consider changing this to be mutable: `mut tick` + | ------- calling `tick` requires mutable binding due to possible mutation of `counter` LL | tick(); | ^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut tick = move || counter += 1; + | +++ error: aborting due to previous error diff --git a/src/test/ui/unsized-locals/suggest-borrow.rs b/src/test/ui/unsized-locals/suggest-borrow.rs new file mode 100644 index 00000000000..08694857993 --- /dev/null +++ b/src/test/ui/unsized-locals/suggest-borrow.rs @@ -0,0 +1,7 @@ +fn main() { + let x: [u8] = vec!(1, 2, 3)[..]; //~ ERROR E0277 + let x: &[u8] = vec!(1, 2, 3)[..]; //~ ERROR E0308 + let x: [u8] = &vec!(1, 2, 3)[..]; //~ ERROR E0308 + //~^ ERROR E0277 + let x: &[u8] = &vec!(1, 2, 3)[..]; +} diff --git a/src/test/ui/unsized-locals/suggest-borrow.stderr b/src/test/ui/unsized-locals/suggest-borrow.stderr new file mode 100644 index 00000000000..08745eab28d --- /dev/null +++ b/src/test/ui/unsized-locals/suggest-borrow.stderr @@ -0,0 +1,60 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:2:9 + | +LL | let x: [u8] = vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | + + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:3:20 + | +LL | let x: &[u8] = vec!(1, 2, 3)[..]; + | ----- ^^^^^^^^^^^^^^^^^ + | | | + | | expected `&[u8]`, found slice `[{integer}]` + | | help: consider borrowing here: `&vec!(1, 2, 3)[..]` + | expected due to this + +error[E0308]: mismatched types + --> $DIR/suggest-borrow.rs:4:19 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ---- ^^^^^^^^^^^^^^^^^^ expected slice `[u8]`, found `&[{integer}]` + | | + | expected due to this + | +help: consider removing the borrow + | +LL - let x: [u8] = &vec!(1, 2, 3)[..]; +LL + let x: [u8] = vec!(1, 2, 3)[..]; + | +help: alternatively, consider changing the type annotation + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow.rs:4:9 + | +LL | let x: [u8] = &vec!(1, 2, 3)[..]; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let x: &[u8] = &vec!(1, 2, 3)[..]; + | + + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr index da77026673d..ace5a87187b 100644 --- a/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr +++ b/src/test/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr @@ -27,6 +27,10 @@ LL | let _foo: [u8] = *foo; = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider borrowing here + | +LL | let _foo: &[u8] = *foo; + | + error: aborting due to 3 previous errors diff --git a/src/test/ui/unsized/unsized6.stderr b/src/test/ui/unsized/unsized6.stderr index 011f2b426c7..18ac1ea1875 100644 --- a/src/test/ui/unsized/unsized6.stderr +++ b/src/test/ui/unsized/unsized6.stderr @@ -14,6 +14,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) { LL + fn f1<W: ?Sized, X: ?Sized, Y, Z: ?Sized>(x: &X) { | +help: consider borrowing here + | +LL | let y: &Y; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:7:12 @@ -62,6 +66,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f2<X: ?Sized, Y: ?Sized>(x: &X) { LL + fn f2<X, Y: ?Sized>(x: &X) { | +help: consider borrowing here + | +LL | let y: &X; + | + error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:17:12 @@ -94,6 +102,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { LL + fn f3<X>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:24:9 @@ -144,6 +156,10 @@ help: consider removing the `?Sized` bound to make the type parameter `Sized` LL - fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { LL + fn f4<X: T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) { | +help: consider borrowing here + | +LL | let y: &X = *x1; + | + error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:32:9 diff --git a/src/test/ui/writing-to-immutable-vec.stderr b/src/test/ui/writing-to-immutable-vec.stderr index a65765c86c8..286267c3834 100644 --- a/src/test/ui/writing-to-immutable-vec.stderr +++ b/src/test/ui/writing-to-immutable-vec.stderr @@ -1,10 +1,13 @@ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/writing-to-immutable-vec.rs:3:5 | -LL | let v: Vec<isize> = vec![1, 2, 3]; - | - help: consider changing this to be mutable: `mut v` LL | v[1] = 4; | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut v: Vec<isize> = vec![1, 2, 3]; + | +++ error: aborting due to previous error diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 903ee938d9d..02f3188f8be 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -4203,6 +4203,7 @@ Released 2018-09-13 [`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const [`float_equality_without_abs`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_equality_without_abs [`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons +[`fn_null_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_null_check [`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`fn_to_numeric_cast_any`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_any @@ -4460,6 +4461,7 @@ Released 2018-09-13 [`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none [`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite [`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch +[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false [`positional_named_format_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#positional_named_format_parameters [`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma [`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence @@ -4545,6 +4547,7 @@ Released 2018-09-13 [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else [`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count +[`size_of_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_ref [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive @@ -4590,6 +4593,7 @@ Released 2018-09-13 [`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool [`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char [`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float +[`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn [`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes [`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr [`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index e862f13e69f..c8e54d7b8e0 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -54,7 +54,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv diag.span_suggestion( expr.span, - &format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), + format!("replace with `ptr::slice_from_raw_parts{mutbl_fn_str}`"), sugg, rustc_errors::Applicability::HasPlaceholders, ); diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 3cd7d1d7e72..2982460c9cf 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -161,6 +161,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::float_literal::LOSSY_FLOAT_LITERAL_INFO, crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO, crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO, + crate::fn_null_check::FN_NULL_CHECK_INFO, crate::format::USELESS_FORMAT_INFO, crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO, crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO, @@ -494,6 +495,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE_INFO, crate::pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF_INFO, crate::pattern_type_mismatch::PATTERN_TYPE_MISMATCH_INFO, + crate::permissions_set_readonly_false::PERMISSIONS_SET_READONLY_FALSE_INFO, crate::precedence::PRECEDENCE_INFO, crate::ptr::CMP_NULL_INFO, crate::ptr::INVALID_NULL_PTR_USAGE_INFO, @@ -535,6 +537,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO, crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO, crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO, + crate::size_of_ref::SIZE_OF_REF_INFO, crate::slow_vector_initialization::SLOW_VECTOR_INITIALIZATION_INFO, crate::std_instead_of_core::ALLOC_INSTEAD_OF_CORE_INFO, crate::std_instead_of_core::STD_INSTEAD_OF_ALLOC_INFO, @@ -568,6 +571,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO, crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO, crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO, + crate::transmute::TRANSMUTE_NULL_TO_FN_INFO, crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO, crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO, crate::transmute::TRANSMUTE_PTR_TO_REF_INFO, diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 7b43d8ccc67..f327c9a71b3 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -969,14 +969,14 @@ fn binding_ty_auto_deref_stability<'tcx>( precedence: i8, binder_args: &'tcx List<BoundVariableKind>, ) -> Position { - let TyKind::Rptr(_, ty) = &ty.kind else { + let TyKind::Ref(_, ty) = &ty.kind else { return Position::Other(precedence); }; let mut ty = ty; loop { break match ty.ty.kind { - TyKind::Rptr(_, ref ref_ty) => { + TyKind::Ref(_, ref ref_ty) => { ty = ref_ty; continue; }, @@ -1282,10 +1282,10 @@ fn referent_used_exactly_once<'tcx>( possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir))); } let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1; - // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is - // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of - // itself. See the comment in that method for an explanation as to why. - possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location) + // If `place.local` were not included here, the `copyable_iterator::warn` test would fail. The + // reason is that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible + // borrower of itself. See the comment in that method for an explanation as to why. + possible_borrower.at_most_borrowers(cx, &[local, place.local], place.local, location) && used_exactly_once(mir, place.local).unwrap_or(false) } else { false diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs index 0ed30196475..f95b628e6c3 100644 --- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs @@ -324,7 +324,7 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: let maybe_neg_sugg = |expr, hir_id| { let sugg = Sugg::hir(cx, expr, ".."); if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id { - format!("-{sugg}") + format!("-{}", sugg.maybe_par()) } else { sugg.to_string() } diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs new file mode 100644 index 00000000000..91c8c340ce2 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/fn_null_check.rs @@ -0,0 +1,106 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; +use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Checks for comparing a function pointer to null. + /// + /// ### Why is this bad? + /// Function pointers are assumed to not be null. + /// + /// ### Example + /// ```rust,ignore + /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */ + /// + /// if (fn_ptr as *const ()).is_null() { ... } + /// ``` + /// Use instead: + /// ```rust,ignore + /// let fn_ptr: Option<fn()> = /* somehow obtained nullable function pointer */ + /// + /// if fn_ptr.is_none() { ... } + /// ``` + #[clippy::version = "1.67.0"] + pub FN_NULL_CHECK, + correctness, + "`fn()` type assumed to be nullable" +} +declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]); + +fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { + span_lint_and_help( + cx, + FN_NULL_CHECK, + expr.span, + "function pointer assumed to be nullable, even though it isn't", + None, + "try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value", + ); +} + +fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind + && let TyKind::Ptr(_) = cast_ty.kind + { + cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn() + } else { + false + } +} + +impl<'tcx> LateLintPass<'tcx> for FnNullCheck { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + match expr.kind { + // Catching: + // (fn_ptr as *<const/mut> <ty>).is_null() + ExprKind::MethodCall(method_name, receiver, _, _) + if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) => + { + lint_expr(cx, expr); + }, + + ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => { + let to_check: &Expr<'_>; + if is_fn_ptr_cast(cx, left) { + to_check = right; + } else if is_fn_ptr_cast(cx, right) { + to_check = left; + } else { + return; + } + + match to_check.kind { + // Catching: + // (fn_ptr as *<const/mut> <ty>) == (0 as <ty>) + ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => { + lint_expr(cx, expr); + }, + + // Catching: + // (fn_ptr as *<const/mut> <ty>) == std::ptr::null() + ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => { + lint_expr(cx, expr); + }, + + // Catching: + // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr> + _ if matches!( + constant(cx, cx.typeck_results(), to_check), + Some((Constant::RawPtr(0), _)) + ) => + { + lint_expr(cx, expr); + }, + + _ => {}, + } + }, + _ => {}, + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 69f7c152fc4..043112bbc95 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -382,7 +382,7 @@ fn check_format_in_format_args( call_site, &format!("`format!` in `{name}!` args"), |diag| { - diag.help(&format!( + diag.help(format!( "combine the `format!(..)` arguments with the outer `{name}!(..)` call" )); diag.help("or consider changing `format!` to `format_args!`"); diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs index 91e6ffe6447..9dbce3f889b 100644 --- a/src/tools/clippy/clippy_lints/src/functions/mod.rs +++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs @@ -63,23 +63,40 @@ declare_clippy_lint! { /// arguments but are not marked `unsafe`. /// /// ### Why is this bad? - /// The function should probably be marked `unsafe`, since - /// for an arbitrary raw pointer, there is no way of telling for sure if it is - /// valid. + /// The function should almost definitely be marked `unsafe`, since for an + /// arbitrary raw pointer, there is no way of telling for sure if it is valid. + /// + /// In general, this lint should **never be disabled** unless it is definitely a + /// false positive (please submit an issue if so) since it breaks Rust's + /// soundness guarantees, directly exposing API users to potentially dangerous + /// program behavior. This is also true for internal APIs, as it is easy to leak + /// unsoundness. + /// + /// ### Context + /// In Rust, an `unsafe {...}` block is used to indicate that the code in that + /// section has been verified in some way that the compiler can not. For a + /// function that accepts a raw pointer then accesses the pointer's data, this is + /// generally impossible as the incoming pointer could point anywhere, valid or + /// not. So, the signature should be marked `unsafe fn`: this indicates that the + /// function's caller must provide some verification that the arguments it sends + /// are valid (and then call the function within an `unsafe` block). /// /// ### Known problems /// * It does not check functions recursively so if the pointer is passed to a /// private non-`unsafe` function which does the dereferencing, the lint won't - /// trigger. + /// trigger (false negative). /// * It only checks for arguments whose type are raw pointers, not raw pointers /// got from an argument in some other way (`fn foo(bar: &[*const u8])` or - /// `some_argument.get_raw_ptr()`). + /// `some_argument.get_raw_ptr()`) (false negative). /// /// ### Example /// ```rust,ignore /// pub fn foo(x: *const u8) { /// println!("{}", unsafe { *x }); /// } + /// + /// // this call "looks" safe but will segfault or worse! + /// // foo(invalid_ptr); /// ``` /// /// Use instead: @@ -87,6 +104,12 @@ declare_clippy_lint! { /// pub unsafe fn foo(x: *const u8) { /// println!("{}", unsafe { *x }); /// } + /// + /// // this would cause a compiler error for calling without `unsafe` + /// // foo(invalid_ptr); + /// + /// // sound call if the caller knows the pointer is valid + /// unsafe { foo(valid_ptr); } /// ``` #[clippy::version = "pre 1.29.0"] pub NOT_UNSAFE_PTR_ARG_DEREF, diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 76c83ab47d0..db637dfc068 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -34,12 +34,12 @@ declare_clippy_lint! { } pub struct LargeConstArrays { - maximum_allowed_size: u64, + maximum_allowed_size: u128, } impl LargeConstArrays { #[must_use] - pub fn new(maximum_allowed_size: u64) -> Self { + pub fn new(maximum_allowed_size: u128) -> Self { Self { maximum_allowed_size } } } @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind(); if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx); if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()); - if self.maximum_allowed_size < element_count * element_size; + if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size); then { let hi_pos = item.ident.span.lo() - BytePos::from_usize(1); diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index b18456ee523..b8d4abdbb78 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { ); diag.span_label( def.variants[variants_size[1].ind].span, - &if variants_size[1].fields_size.is_empty() { + if variants_size[1].fields_size.is_empty() { "the second-largest variant carries no data at all".to_owned() } else { format!( diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 5857d81ab1f..89ae83d48f5 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -24,12 +24,12 @@ declare_clippy_lint! { } pub struct LargeStackArrays { - maximum_allowed_size: u64, + maximum_allowed_size: u128, } impl LargeStackArrays { #[must_use] - pub fn new(maximum_allowed_size: u64) -> Self { + pub fn new(maximum_allowed_size: u128) -> Self { Self { maximum_allowed_size } } } @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && !cx.tcx.hir().parent_iter(expr.hir_id) .any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. }))) - && self.maximum_allowed_size < element_count * element_size { + && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size) { span_lint_and_help( cx, LARGE_STACK_ARRAYS, diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index e88d1764a24..9eba4675629 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -361,7 +361,7 @@ fn check_for_is_empty<'tcx>( db.span_note(span, "`is_empty` defined here"); } if let Some(self_kind) = self_kind { - db.note(&output.expected_sig(self_kind)); + db.note(output.expected_sig(self_kind)); } }); } diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 39850d59803..dcd8ca81ae8 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -125,6 +125,7 @@ mod explicit_write; mod fallible_impl_from; mod float_literal; mod floating_point_arithmetic; +mod fn_null_check; mod format; mod format_args; mod format_impl; @@ -234,6 +235,7 @@ mod partialeq_ne_impl; mod partialeq_to_none; mod pass_by_ref_or_value; mod pattern_type_mismatch; +mod permissions_set_readonly_false; mod precedence; mod ptr; mod ptr_offset_with_cast; @@ -263,6 +265,7 @@ mod shadow; mod single_char_lifetime_names; mod single_component_path_imports; mod size_of_in_element_count; +mod size_of_ref; mod slow_vector_initialization; mod std_instead_of_core; mod strings; @@ -334,7 +337,7 @@ pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf { Ok(Some(path)) => path, Ok(None) => return Conf::default(), Err(error) => { - sess.struct_err(&format!("error finding Clippy's configuration file: {error}")) + sess.struct_err(format!("error finding Clippy's configuration file: {error}")) .emit(); return Conf::default(); }, @@ -902,6 +905,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow)); store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv()))); store.register_late_pass(|_| Box::new(semicolon_block::SemicolonBlock)); + store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck)); + store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse)); + store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs index 14f22348132..1953ee8a717 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs @@ -77,7 +77,7 @@ pub(super) fn check<'tcx>( applicability, ); - diag.note(&format!( + diag.note(format!( "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`" )); }, diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 075ecbe7ede..63212beaa63 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { let help = format!("make the function `async` and {ret_sugg}"); diag.span_suggestion( header_span, - &help, + help, format!("async {}{ret_snip}", &header_snip[..ret_pos]), Applicability::MachineApplicable ); @@ -152,7 +152,7 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName]) let input_lifetimes: Vec<LifetimeName> = inputs .iter() .filter_map(|ty| { - if let TyKind::Rptr(lt, _) = ty.kind { + if let TyKind::Ref(lt, _) = ty.kind { Some(lt.res) } else { None diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs index bb6d628af3b..f239736d38a 100644 --- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs +++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs @@ -35,6 +35,9 @@ declare_clippy_lint! { /// Some may consider panicking in these situations to be desirable, but it also may /// introduce panicking where there wasn't any before. /// + /// See also [the discussion in the + /// PR](https://github.com/rust-lang/rust-clippy/pull/9484#issuecomment-1278922613). + /// /// ### Examples /// ```rust /// # let (input, min, max) = (0, -2, 1); @@ -78,7 +81,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.66.0"] pub MANUAL_CLAMP, - complexity, + nursery, "using a clamp pattern instead of the clamp function" } impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]); diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index de166b9765f..c795c1d9a16 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -109,7 +109,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip { let test_span = expr.span.until(then.span); span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| { - diag.span_note(test_span, &format!("the {kind_word} was tested here")); + diag.span_note(test_span, format!("the {kind_word} was tested here")); multispan_sugg( diag, &format!("try using the `strip_{kind_word}` method"), diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs index d521a529e0d..f6bf0e7aa1a 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs @@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::contains_unsafe_block; use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id}; -use rustc_hir::LangItem::OptionSome; +use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind}; use rustc_lint::LateContext; use rustc_span::{sym, SyntaxContext}; @@ -25,15 +25,13 @@ fn get_cond_expr<'tcx>( if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr); if let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind; if let PatKind::Binding(_,target, ..) = pat.kind; - if let (then_visitor, else_visitor) - = (is_some_expr(cx, target, ctxt, then_expr), - is_some_expr(cx, target, ctxt, else_expr)); - if then_visitor != else_visitor; // check that one expr resolves to `Some(x)`, the other to `None` + if is_some_expr(cx, target, ctxt, then_expr) && is_none_expr(cx, else_expr) + || is_none_expr(cx, then_expr) && is_some_expr(cx, target, ctxt, else_expr); // check that one expr resolves to `Some(x)`, the other to `None` then { return Some(SomeExpr { expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()), needs_unsafe_block: contains_unsafe_block(cx, expr), - needs_negated: !then_visitor // if the `then_expr` resolves to `None`, need to negate the cond + needs_negated: is_none_expr(cx, then_expr) // if the `then_expr` resolves to `None`, need to negate the cond }) } }; @@ -74,6 +72,13 @@ fn is_some_expr(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: false } +fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) { + return is_res_lang_ctor(cx, path_res(cx, inner_expr), OptionNone); + }; + false +} + // given the closure: `|<pattern>| <expr>` // returns `|&<pattern>| <expr>` fn add_ampersand_if_copy(body_str: String, has_copy_trait: bool) -> String { diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs index 1bf8d4e96ad..c94a1f76330 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs @@ -31,19 +31,11 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e }; // Do we need to add ';' to suggestion ? - match match_body.kind { - ExprKind::Block(block, _) => { - // macro + expr_ty(body) == () - if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() { - snippet_body.push(';'); - } - }, - _ => { - // expr_ty(body) == () - if cx.typeck_results().expr_ty(match_body).is_unit() { - snippet_body.push(';'); - } - }, + if let ExprKind::Block(block, _) = match_body.kind { + // macro + expr_ty(body) == () + if block.span.from_expansion() && cx.typeck_results().expr_ty(match_body).is_unit() { + snippet_body.push(';'); + } } let mut applicability = Applicability::MaybeIncorrect; diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs index 7f8d124838c..59de8c0384b 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs @@ -30,7 +30,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { let mut has_non_wild = false; for arm in arms { match peel_hir_pat_refs(arm.pat).0.kind { - PatKind::Wild => wildcard_span = Some(arm.pat.span), + PatKind::Wild if arm.guard.is_none() => wildcard_span = Some(arm.pat.span), PatKind::Binding(_, _, ident, None) => { wildcard_span = Some(arm.pat.span); wildcard_ident = Some(ident); diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs index d8c821bc9ee..424482859ee 100644 --- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs +++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs @@ -36,7 +36,7 @@ pub fn check( expr.span, &format!("calling `to_string` on `{arg_ty}`"), |diag| { - diag.help(&format!( + diag.help(format!( "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`" )); let mut applicability = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs index beb772100af..279175e20c3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_skip_next.rs @@ -29,7 +29,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr application = Applicability::Unspecified; diag.span_help( pat.span, - &format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")), + format!("for this change `{}` has to be mutable", snippet(cx, pat.span, "..")), ); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 561e4336593..77be61b4793 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -3986,7 +3986,7 @@ impl OutType { (Self::Unit, &hir::FnRetTy::Return(ty)) if is_unit(ty) => true, (Self::Bool, &hir::FnRetTy::Return(ty)) if is_bool(ty) => true, (Self::Any, &hir::FnRetTy::Return(ty)) if !is_unit(ty) => true, - (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Rptr(_, _)), + (Self::Ref, &hir::FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(_, _)), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 910ee14855e..4c6328481e4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -84,7 +84,7 @@ pub(super) fn check<'tcx>( suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, "))); } - diag.multipart_suggestion(&format!("use `{suggest}` instead"), suggestion, applicability); + diag.multipart_suggestion(format!("use `{suggest}` instead"), suggestion, applicability); }); } } diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 3c01ce1fecd..d00708e828e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -167,7 +167,7 @@ fn check_manual_split_once_indirect( }; diag.span_suggestion_verbose( local.span, - &format!("try `{r}split_once`"), + format!("try `{r}split_once`"), format!("let ({lhs}, {rhs}) = {self_snip}.{r}split_once({pat_snip}){unwrap};"), app, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index 0e73459ad65..47e2e744112 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -62,7 +62,7 @@ pub(super) fn check<'tcx>( span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| { diag.span_suggestion( span, - &format!("use `{simplify_using}(..)` instead"), + format!("use `{simplify_using}(..)` instead"), format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index bc90e131b7f..64d8333a093 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { return; } - if let hir::TyKind::Rptr( + if let hir::TyKind::Ref( _, hir::MutTy { ty: pty, @@ -94,7 +94,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> { }, ) = ty.kind { - if let hir::TyKind::Rptr( + if let hir::TyKind::Ref( _, hir::MutTy { mutbl: hir::Mutability::Mut, diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs index f2ffac85bf4..5457eeec4ea 100644 --- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs @@ -124,7 +124,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl); } }, - TyKind::Rptr(lifetime, mut_ty) => { + TyKind::Ref(lifetime, mut_ty) => { if_chain! { if let TyKind::Path(None, path) = &mut_ty.ty.kind; if let PatKind::Ident(BindingAnnotation::NONE, _, _) = p.pat.kind; diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 67debe7e08a..5a9387b34cc 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -284,7 +284,7 @@ fn check<'tcx>( diag.span_suggestion( assign.lhs_span, - &format!("declare `{binding_name}` here"), + format!("declare `{binding_name}` here"), let_snippet, Applicability::MachineApplicable, ); @@ -304,7 +304,7 @@ fn check<'tcx>( diag.span_suggestion_verbose( usage.stmt.span.shrink_to_lo(), - &format!("declare `{binding_name}` here"), + format!("declare `{binding_name}` here"), format!("{let_snippet} = "), applicability, ); @@ -335,7 +335,7 @@ fn check<'tcx>( diag.span_suggestion_verbose( usage.stmt.span.shrink_to_lo(), - &format!("declare `{binding_name}` here"), + format!("declare `{binding_name}` here"), format!("{let_snippet} = "), applicability, ); diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs index ae0a41db918..7376ab0c846 100644 --- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs +++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs @@ -125,7 +125,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { if is_string { "string" } else { "byte string" } ), |diag| { - diag.help(&format!( + diag.help(format!( "octal escapes are not supported, `\\0` is always a null {}", if is_string { "character" } else { "byte" } )); @@ -139,7 +139,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { // suggestion 2: unambiguous null byte diag.span_suggestion( span, - &format!( + format!( "if the null {} is intended, disambiguate using", if is_string { "character" } else { "byte" } ), diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs index ae805147f07..015f6c14e76 100644 --- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs +++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs @@ -50,7 +50,7 @@ fn lint_misrefactored_assign_op( let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r)); diag.span_suggestion( expr.span, - &format!( + format!( "did you mean `{snip_a} = {snip_a} {} {snip_r}` or `{long}`? Consider replacing it with", op.as_str() ), diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index f9fd3645668..75add4ee4aa 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -184,7 +184,7 @@ impl<'tcx> PassByRefOrValue { if is_copy(cx, ty) && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) && size <= self.ref_min_size - && let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind + && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind { if let Some(typeck) = cx.maybe_typeck_results() { // Don't lint if an unsafe pointer is created. diff --git a/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs new file mode 100644 index 00000000000..e7095ec191f --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/permissions_set_readonly_false.rs @@ -0,0 +1,52 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::paths; +use clippy_utils::ty::match_type; +use rustc_ast::ast::LitKind; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// ### What it does + /// Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`. + /// + /// ### Why is this bad? + /// On Unix platforms this results in the file being world writable, + /// equivalent to `chmod a+w <file>`. + /// ### Example + /// ```rust + /// use std::fs::File; + /// let f = File::create("foo.txt").unwrap(); + /// let metadata = f.metadata().unwrap(); + /// let mut permissions = metadata.permissions(); + /// permissions.set_readonly(false); + /// ``` + #[clippy::version = "1.66.0"] + pub PERMISSIONS_SET_READONLY_FALSE, + suspicious, + "Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`" +} +declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALSE]); + +impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind + && match_type(cx, cx.typeck_results().expr_ty(receiver), &paths::PERMISSIONS) + && path.ident.name == sym!(set_readonly) + && let ExprKind::Lit(lit) = &arg.kind + && LitKind::Bool(false) == lit.node + { + span_lint_and_then( + cx, + PERMISSIONS_SET_READONLY_FALSE, + expr.span, + "call to `set_readonly` with argument `false`", + |diag| { + diag.note("on Unix platforms this results in the file being world writable"); + diag.help("you can set the desired permissions using `PermissionsExt`. For more information, see\n\ + https://doc.rust-lang.org/std/os/unix/fs/trait.PermissionsExt.html"); + } + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index e395ff54cb1..26295304258 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -421,7 +421,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>( if let ty::Ref(_, ty, mutability) = *ty.kind(); if let ty::Adt(adt, substs) = *ty.kind(); - if let TyKind::Rptr(lt, ref ty) = hir_ty.kind; + if let TyKind::Ref(lt, ref ty) = hir_ty.kind; if let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind; // Check that the name as typed matches the actual name of the type. @@ -503,14 +503,14 @@ fn check_fn_args<'cx, 'tcx: 'cx>( fn check_mut_from_ref<'tcx>(cx: &LateContext<'tcx>, sig: &FnSig<'_>, body: Option<&'tcx Body<'_>>) { if let FnRetTy::Return(ty) = sig.decl.output - && let Some((out, Mutability::Mut, _)) = get_rptr_lm(ty) + && let Some((out, Mutability::Mut, _)) = get_ref_lm(ty) { let out_region = cx.tcx.named_region(out.hir_id); let args: Option<Vec<_>> = sig .decl .inputs .iter() - .filter_map(get_rptr_lm) + .filter_map(get_ref_lm) .filter(|&(lt, _, _)| cx.tcx.named_region(lt.hir_id) == out_region) .map(|(_, mutability, span)| (mutability == Mutability::Not).then_some(span)) .collect(); @@ -704,8 +704,8 @@ fn matches_preds<'tcx>( }) } -fn get_rptr_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> { - if let TyKind::Rptr(lt, ref m) = ty.kind { +fn get_ref_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> { + if let TyKind::Ref(lt, ref m) = ty.kind { Some((lt, m.mutbl, ty.span)) } else { None diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs index c1677fb3da1..0e7c5cca724 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { // `res = clone(arg)` can be turned into `res = move arg;` // if `arg` is the only borrow of `cloned` at this point. - if cannot_move_out || !possible_borrower.only_borrowers(&[arg], cloned, loc) { + if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg], cloned, loc) { continue; } @@ -178,7 +178,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone { // StorageDead(pred_arg); // res = to_path_buf(cloned); // ``` - if cannot_move_out || !possible_borrower.only_borrowers(&[arg, cloned], local, loc) { + if cannot_move_out || !possible_borrower.at_most_borrowers(cx, &[arg, cloned], local, loc) { continue; } diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index 41f991a967b..44bf824aa0e 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -59,7 +59,7 @@ impl RedundantStaticLifetimes { } }, // This is what we are looking for ! - TyKind::Rptr(ref optional_lifetime, ref borrow_type) => { + TyKind::Ref(ref optional_lifetime, ref borrow_type) => { // Match the 'static lifetime if let Some(lifetime) = *optional_lifetime { match borrow_type.ty.kind { diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index f21b3ea6c3b..448a32b77c0 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -39,7 +39,7 @@ declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]); impl<'tcx> LateLintPass<'tcx> for RefOptionRef { fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { if_chain! { - if let TyKind::Rptr(_, ref mut_ty) = ty.kind; + if let TyKind::Ref(_, ref mut_ty) = ty.kind; if mut_ty.mutbl == Mutability::Not; if let TyKind::Path(ref qpath) = &mut_ty.ty.kind; let last = last_path_segment(qpath); @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { GenericArg::Type(inner_ty) => Some(inner_ty), _ => None, }); - if let TyKind::Rptr(_, ref inner_mut_ty) = inner_ty.kind; + if let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind; if inner_mut_ty.mutbl == Mutability::Not; then { diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 81143d7799e..d4d50660520 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -6,7 +6,7 @@ use core::ops::ControlFlow; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, PatKind, StmtKind}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, LangItem, MatchSource, PatKind, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; @@ -207,6 +207,12 @@ fn check_final_expr<'tcx>( match &peeled_drop_expr.kind { // simple return is always "bad" ExprKind::Ret(ref inner) => { + // if desugar of `do yeet`, don't lint + if let Some(inner_expr) = inner + && let ExprKind::Call(path_expr, _) = inner_expr.kind + && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind { + return; + } if cx.tcx.hir().attrs(expr.hir_id).is_empty() { let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner)); if !borrows { diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index caab5851baf..17763128cd1 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { |diag| { diag.span_note( trait_method_span, - &format!("existing `{method_name}` defined here"), + format!("existing `{method_name}` defined here"), ); }, ); @@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { // iterate on trait_spans? diag.span_note( trait_spans[0], - &format!("existing `{method_name}` defined here"), + format!("existing `{method_name}` defined here"), ); }, ); diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs new file mode 100644 index 00000000000..3fcdb4288ce --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs @@ -0,0 +1,73 @@ +use clippy_utils::{diagnostics::span_lint_and_help, path_def_id, ty::peel_mid_ty_refs}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for calls to `std::mem::size_of_val()` where the argument is + /// a reference to a reference. + /// + /// ### Why is this bad? + /// + /// Calling `size_of_val()` with a reference to a reference as the argument + /// yields the size of the reference-type, not the size of the value behind + /// the reference. + /// + /// ### Example + /// ```rust + /// struct Foo { + /// buffer: [u8], + /// } + /// + /// impl Foo { + /// fn size(&self) -> usize { + /// // Note that `&self` as an argument is a `&&Foo`: Because `self` + /// // is already a reference, `&self` is a double-reference. + /// // The return value of `size_of_val()` therefor is the + /// // size of the reference-type, not the size of `self`. + /// std::mem::size_of_val(&self) + /// } + /// } + /// ``` + /// Use instead: + /// ```rust + /// struct Foo { + /// buffer: [u8], + /// } + /// + /// impl Foo { + /// fn size(&self) -> usize { + /// // Correct + /// std::mem::size_of_val(self) + /// } + /// } + /// ``` + #[clippy::version = "1.67.0"] + pub SIZE_OF_REF, + suspicious, + "Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended" +} +declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]); + +impl LateLintPass<'_> for SizeOfRef { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { + if let ExprKind::Call(path, [arg]) = expr.kind + && let Some(def_id) = path_def_id(cx, path) + && cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id) + && let arg_ty = cx.typeck_results().expr_ty(arg) + && peel_mid_ty_refs(arg_ty).1 > 1 + { + span_lint_and_help( + cx, + SIZE_OF_REF, + expr.span, + "argument to `std::mem::size_of_val()` is a reference to a reference", + None, + "dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type", + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index c374529d1ea..17e9cc5f6b7 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -132,7 +132,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa applicability, ); if !is_xor_based { - diag.note(&format!("or maybe you should use `{sugg}::mem::replace`?")); + diag.note(format!("or maybe you should use `{sugg}::mem::replace`?")); } }, ); @@ -214,7 +214,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) { Applicability::MaybeIncorrect, ); diag.note( - &format!("or maybe you should use `{sugg}::mem::replace`?") + format!("or maybe you should use `{sugg}::mem::replace`?") ); } }); diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 83e651aba8e..691d759d773 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -3,6 +3,7 @@ mod transmute_float_to_int; mod transmute_int_to_bool; mod transmute_int_to_char; mod transmute_int_to_float; +mod transmute_null_to_fn; mod transmute_num_to_bytes; mod transmute_ptr_to_ptr; mod transmute_ptr_to_ref; @@ -409,6 +410,34 @@ declare_clippy_lint! { "transmutes from a null pointer to a reference, which is undefined behavior" } +declare_clippy_lint! { + /// ### What it does + /// Checks for null function pointer creation through transmute. + /// + /// ### Why is this bad? + /// Creating a null function pointer is undefined behavior. + /// + /// More info: https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimization + /// + /// ### Known problems + /// Not all cases can be detected at the moment of this writing. + /// For example, variables which hold a null pointer and are then fed to a `transmute` + /// call, aren't detectable yet. + /// + /// ### Example + /// ```rust + /// let null_fn: fn() = unsafe { std::mem::transmute( std::ptr::null::<()>() ) }; + /// ``` + /// Use instead: + /// ```rust + /// let null_fn: Option<fn()> = None; + /// ``` + #[clippy::version = "1.67.0"] + pub TRANSMUTE_NULL_TO_FN, + correctness, + "transmute results in a null function pointer, which is undefined behavior" +} + pub struct Transmute { msrv: Msrv, } @@ -428,6 +457,7 @@ impl_lint_pass!(Transmute => [ TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, TRANSMUTE_UNDEFINED_REPR, TRANSMUTING_NULL, + TRANSMUTE_NULL_TO_FN, ]); impl Transmute { #[must_use] @@ -461,6 +491,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let linted = wrong_transmute::check(cx, e, from_ty, to_ty) | crosspointer_transmute::check(cx, e, from_ty, to_ty) | transmuting_null::check(cx, e, arg, to_ty) + | transmute_null_to_fn::check(cx, e, arg, to_ty) | transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv) | transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context) | transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context) diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs new file mode 100644 index 00000000000..e75d7f6bf1d --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs @@ -0,0 +1,64 @@ +use clippy_utils::consts::{constant, Constant}; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::{is_integer_literal, is_path_diagnostic_item}; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::Ty; +use rustc_span::symbol::sym; + +use super::TRANSMUTE_NULL_TO_FN; + +fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { + span_lint_and_then( + cx, + TRANSMUTE_NULL_TO_FN, + expr.span, + "transmuting a known null pointer into a function pointer", + |diag| { + diag.span_label(expr.span, "this transmute results in undefined behavior"); + diag.help( + "try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value" + ); + }, + ); +} + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>, to_ty: Ty<'tcx>) -> bool { + if !to_ty.is_fn() { + return false; + } + + match arg.kind { + // Catching: + // transmute over constants that resolve to `null`. + ExprKind::Path(ref _qpath) + if matches!(constant(cx, cx.typeck_results(), arg), Some((Constant::RawPtr(0), _))) => + { + lint_expr(cx, expr); + true + }, + + // Catching: + // `std::mem::transmute(0 as *const i32)` + ExprKind::Cast(inner_expr, _cast_ty) if is_integer_literal(inner_expr, 0) => { + lint_expr(cx, expr); + true + }, + + // Catching: + // `std::mem::transmute(std::ptr::null::<i32>())` + ExprKind::Call(func1, []) if is_path_diagnostic_item(cx, func1, sym::ptr_null) => { + lint_expr(cx, expr); + true + }, + + _ => { + // FIXME: + // Also catch transmutations of variables which are known nulls. + // To do this, MIR const propagation seems to be the better tool. + // Whenever MIR const prop routines are more developed, this will + // become available. As of this writing (25/03/19) it is not yet. + false + }, + } +} diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 3dde4eee671..54ac04df1c1 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -71,7 +71,7 @@ pub(super) fn check<'tcx>( /// Gets the type `Bar` in `…::transmute<Foo, &Bar>`. fn get_explicit_type<'tcx>(path: &'tcx Path<'tcx>) -> Option<&'tcx hir::Ty<'tcx>> { if let GenericArg::Type(ty) = path.segments.last()?.args?.args.get(1)? - && let TyKind::Rptr(_, ty) = &ty.kind + && let TyKind::Ref(_, ty) = &ty.kind { Some(ty.ty) } else { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 34642f4b122..af0242348ac 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -77,7 +77,7 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty.peel_refs() { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(format!("the contained type `{from_ty}` has an undefined layout")); } }, ); @@ -91,7 +91,7 @@ pub(super) fn check<'tcx>( &format!("transmute to `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty.peel_refs() { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(format!("the contained type `{to_ty}` has an undefined layout")); } }, ); @@ -119,16 +119,16 @@ pub(super) fn check<'tcx>( ), |diag| { if let Some(same_adt_did) = same_adt_did { - diag.note(&format!( + diag.note(format!( "two instances of the same generic type (`{}`) may have different layouts", cx.tcx.item_name(same_adt_did) )); } else { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(format!("the contained type `{from_ty}` has an undefined layout")); } if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(format!("the contained type `{to_ty}` has an undefined layout")); } } }, @@ -146,7 +146,7 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty_orig}` which has an undefined layout"), |diag| { if from_ty_orig.peel_refs() != from_ty { - diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); + diag.note(format!("the contained type `{from_ty}` has an undefined layout")); } }, ); @@ -163,7 +163,7 @@ pub(super) fn check<'tcx>( &format!("transmute into `{to_ty_orig}` which has an undefined layout"), |diag| { if to_ty_orig.peel_refs() != to_ty { - diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); + diag.note(format!("the contained type `{to_ty}` has an undefined layout")); } }, ); diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 6b444922a7c..b79d4e915a2 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>( &format!("transmute from `{from_ty}` to `{to_ty}` which could be expressed as a pointer cast instead"), |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - let sugg = arg.as_ty(&to_ty.to_string()).to_string(); + let sugg = arg.as_ty(to_ty.to_string()).to_string(); diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); } }, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs index 19ce5ae72c2..1e407fc4138 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs @@ -18,8 +18,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t // Catching transmute over constants that resolve to `null`. let mut const_eval_context = constant_context(cx, cx.typeck_results()); if let ExprKind::Path(ref _qpath) = arg.kind && - let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg) && - x == 0 + let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg) { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG); return true; diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs index f919bbd5afc..871c3fadbba 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs @@ -61,7 +61,7 @@ pub(super) fn check<'tcx>( "transmute from an integer to a pointer", |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - diag.span_suggestion(e.span, "try", arg.as_ty(&to_ty.to_string()), Applicability::Unspecified); + diag.span_suggestion(e.span, "try", arg.as_ty(to_ty.to_string()), Applicability::Unspecified); } }, ); diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 20978e81dc5..c14f056a1f2 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -539,7 +539,7 @@ impl Types { QPath::LangItem(..) => {}, } }, - TyKind::Rptr(lt, ref mut_ty) => { + TyKind::Ref(lt, ref mut_ty) => { context.is_nested_call = true; if !borrowed_box::check(cx, hir_ty, lt, mut_ty) { self.check_ty(cx, mut_ty.ty, context); diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index fae5385ffc8..f9b9a66b5fa 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ &format!("usage of `{outer_sym}<{generic_snippet}>`"), |diag| { diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability); - diag.note(&format!( + diag.note(format!( "`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap" )); }, @@ -78,7 +78,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ format!("{outer_sym}<{generic_snippet}>"), applicability, ); - diag.note(&format!( + diag.note(format!( "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation" )); }, @@ -91,10 +91,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_ hir_ty.span, &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"), |diag| { - diag.note(&format!( + diag.note(format!( "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation" )); - diag.help(&format!( + diag.help(format!( "consider using just `{outer_sym}<{generic_snippet}>` or `{inner_sym}<{generic_snippet}>`" )); }, diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs index 5ca4023aa5c..0aa50c99c16 100644 --- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -44,7 +44,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { let (add_score, sub_nest) = match ty.kind { // _, &x and *x have only small overhead; don't mess with nesting level - TyKind::Infer | TyKind::Ptr(..) | TyKind::Rptr(..) => (1, 0), + TyKind::Infer | TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0), // the "normal" components of a type: named types, arrays/tuples TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), diff --git a/src/tools/clippy/clippy_lints/src/types/utils.rs b/src/tools/clippy/clippy_lints/src/types/utils.rs index 0fa75f8f0a9..7f43b7841ff 100644 --- a/src/tools/clippy/clippy_lints/src/types/utils.rs +++ b/src/tools/clippy/clippy_lints/src/types/utils.rs @@ -13,7 +13,7 @@ pub(super) fn match_borrows_parameter(_cx: &LateContext<'_>, qpath: &QPath<'_>) GenericArg::Type(ty) => Some(ty), _ => None, }); - if let TyKind::Rptr(..) = ty.kind; + if let TyKind::Ref(..) = ty.kind; then { return Some(ty.span); } diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index f6d3fb00f4e..ef9f740f704 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -129,7 +129,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp if arg_snippets_without_empty_blocks.is_empty() { db.multipart_suggestion( - &format!("use {singular}unit literal{plural} instead"), + format!("use {singular}unit literal{plural} instead"), args_to_recover .iter() .map(|arg| (arg.span, "()".to_string())) @@ -142,7 +142,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp let it_or_them = if plural { "them" } else { "it" }; db.span_suggestion( expr.span, - &format!( + format!( "{or}move the expression{empty_or_s} in front of the call and replace {it_or_them} with the unit literal `()`" ), sugg, diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 3743d5d97a7..a95e7b61374 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -1,11 +1,11 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::source::{snippet, snippet_with_macro_callsite}; use clippy_utils::sugg::Sugg; -use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts}; -use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths}; +use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; +use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, path_to_local, paths}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind, HirId, MatchSource}; +use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -81,16 +81,24 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } } if is_trait_method(cx, e, sym::IntoIterator) && name.ident.name == sym::into_iter { - if let Some(parent_expr) = get_parent_expr(cx, e) { - if let ExprKind::MethodCall(parent_name, ..) = parent_expr.kind { - if parent_name.ident.name != sym::into_iter { - return; - } - } + if get_parent_expr(cx, e).is_some() && + let Some(id) = path_to_local(recv) && + let Node::Pat(pat) = cx.tcx.hir().get(id) && + let PatKind::Binding(ann, ..) = pat.kind && + ann != BindingAnnotation::MUT + { + // Do not remove .into_iter() applied to a non-mutable local variable used in + // a larger expression context as it would differ in mutability. + return; } + let a = cx.typeck_results().expr_ty(e); let b = cx.typeck_results().expr_ty(recv); - if same_type_and_consts(a, b) { + + // If the types are identical then .into_iter() can be removed, unless the type + // implements Copy, in which case .into_iter() returns a copy of the receiver and + // cannot be safely omitted. + if same_type_and_consts(a, b) && !is_copy(cx, b) { let sugg = snippet(cx, recv.span, "<expr>").into_owned(); span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs index 3e7d0028c0f..c1589c771c4 100644 --- a/src/tools/clippy/clippy_lints/src/utils/conf.rs +++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs @@ -333,7 +333,7 @@ define_Conf! { /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS. /// /// The maximum allowed size for arrays on the stack - (array_size_threshold: u64 = 512_000), + (array_size_threshold: u128 = 512_000), /// Lint: VEC_BOX. /// /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 786d9608c85..4c3b1b131fd 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -257,7 +257,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { } pub(super) fn is_lint_ref_type(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool { - if let TyKind::Rptr( + if let TyKind::Ref( _, MutTy { ty: inner, diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 857abe77e21..929544cd69d 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -558,8 +558,8 @@ impl fmt::Display for ClippyConfiguration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result { writeln!( f, - "* `{}`: `{}`: {} (defaults to `{}`)", - self.name, self.config_type, self.doc, self.default + "* `{}`: `{}`(defaults to `{}`): {}", + self.name, self.config_type, self.default, self.doc ) } } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 6b321765bc0..df335038881 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -377,7 +377,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c // print!("\n"), write!(f, "\n") diag.multipart_suggestion( - &format!("use `{name}ln!` instead"), + format!("use `{name}ln!` instead"), vec![(name_span, format!("{name}ln")), (format_string_span, String::new())], Applicability::MachineApplicable, ); @@ -388,7 +388,7 @@ fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_c let newline_span = format_string_span.with_lo(hi - BytePos(3)).with_hi(hi - BytePos(1)); diag.multipart_suggestion( - &format!("use `{name}ln!` instead"), + format!("use `{name}ln!` instead"), vec![(name_span, format!("{name}ln")), (newline_span, String::new())], Applicability::MachineApplicable, ); diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 49e5f283db0..9d0263e93be 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -625,7 +625,7 @@ pub fn eq_ty(l: &Ty, r: &Ty) -> bool { (Slice(l), Slice(r)) => eq_ty(l, r), (Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value), (Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty), - (Rptr(ll, l), Rptr(rl, r)) => { + (Ref(ll, l), Ref(rl, r)) => { both(ll, rl, |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) }, (BareFn(l), BareFn(r)) => { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 7a637d32bab..a67bd8d4600 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -620,12 +620,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( int.try_into().expect("invalid f64 bit representation"), ))), - ty::RawPtr(type_and_mut) => { - if let ty::Uint(_) = type_and_mut.ty.kind() { - return Some(Constant::RawPtr(int.assert_bits(int.size()))); - } - None - }, + ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))), // FIXME: implement other conversions. _ => None, } diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 16b160b6fd2..812f6fe71a0 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -17,7 +17,7 @@ use std::env; fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() { if let Some(lint) = lint.name_lower().strip_prefix("clippy::") { - diag.help(&format!( + diag.help(format!( "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}", &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| { // extract just major + minor version and ignore patch versions diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 07fb6af91ba..2bbe1a19b62 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -430,7 +430,7 @@ impl HirEqInterExpr<'_, '_, '_> { (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl), (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty), - (TyKind::Rptr(_, l_rmut), TyKind::Rptr(_, r_rmut)) => { + (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => { l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) }, (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), @@ -950,7 +950,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - TyKind::Rptr(lifetime, ref mut_ty) => { + TyKind::Ref(lifetime, ref mut_ty) => { self.hash_lifetime(lifetime); self.hash_ty(mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 43e2d1ec826..d863609b6a7 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2264,7 +2264,7 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) let mut count = 0; loop { match &ty.kind { - TyKind::Rptr(_, ref_ty) => { + TyKind::Ref(_, ref_ty) => { ty = ref_ty.ty; count += 1; }, diff --git a/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs b/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs deleted file mode 100644 index d262b335d99..00000000000 --- a/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs +++ /dev/null @@ -1,52 +0,0 @@ -use rustc_index::bit_set::BitSet; -use rustc_middle::mir; -use rustc_mir_dataflow::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis}; - -/// Determines liveness of each local purely based on `StorageLive`/`Dead`. -#[derive(Copy, Clone)] -pub(super) struct MaybeStorageLive; - -impl<'tcx> AnalysisDomain<'tcx> for MaybeStorageLive { - type Domain = BitSet<mir::Local>; - const NAME: &'static str = "maybe_storage_live"; - - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { - // bottom = dead - BitSet::new_empty(body.local_decls.len()) - } - - fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) { - for arg in body.args_iter() { - state.insert(arg); - } - } -} - -impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive { - type Idx = mir::Local; - - fn statement_effect(&self, trans: &mut impl GenKill<Self::Idx>, stmt: &mir::Statement<'tcx>, _: mir::Location) { - match stmt.kind { - mir::StatementKind::StorageLive(l) => trans.gen(l), - mir::StatementKind::StorageDead(l) => trans.kill(l), - _ => (), - } - } - - fn terminator_effect( - &self, - _trans: &mut impl GenKill<Self::Idx>, - _terminator: &mir::Terminator<'tcx>, - _loc: mir::Location, - ) { - } - - fn call_return_effect( - &self, - _trans: &mut impl GenKill<Self::Idx>, - _block: mir::BasicBlock, - _return_places: CallReturnPlaces<'_, 'tcx>, - ) { - // Nothing to do when a call returns successfully - } -} diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index 818e603f665..26c0015e87e 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -5,8 +5,6 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::TyCtxt; -mod maybe_storage_live; - mod possible_borrower; pub use possible_borrower::PossibleBorrowerMap; diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 25717bf3d2f..395d46e7a2f 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -1,92 +1,137 @@ -use super::{ - maybe_storage_live::MaybeStorageLive, possible_origin::PossibleOriginVisitor, - transitive_relation::TransitiveRelation, -}; +use super::possible_origin::PossibleOriginVisitor; use crate::ty::is_copy; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_lint::LateContext; -use rustc_middle::mir::{self, visit::Visitor as _, Mutability}; -use rustc_middle::ty::{self, visit::TypeVisitor}; -use rustc_mir_dataflow::{Analysis, ResultsCursor}; +use rustc_middle::mir::{ + self, visit::Visitor as _, BasicBlock, Local, Location, Mutability, Statement, StatementKind, Terminator, +}; +use rustc_middle::ty::{self, visit::TypeVisitor, TyCtxt}; +use rustc_mir_dataflow::{ + fmt::DebugWithContext, impls::MaybeStorageLive, lattice::JoinSemiLattice, Analysis, AnalysisDomain, + CallReturnPlaces, ResultsCursor, +}; +use std::borrow::Cow; use std::ops::ControlFlow; /// Collects the possible borrowers of each local. /// For example, `b = &a; c = &a;` will make `b` and (transitively) `c` /// possible borrowers of `a`. #[allow(clippy::module_name_repetitions)] -struct PossibleBorrowerVisitor<'a, 'b, 'tcx> { - possible_borrower: TransitiveRelation, +struct PossibleBorrowerAnalysis<'b, 'tcx> { + tcx: TyCtxt<'tcx>, body: &'b mir::Body<'tcx>, - cx: &'a LateContext<'tcx>, possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, } -impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> { - fn new( - cx: &'a LateContext<'tcx>, - body: &'b mir::Body<'tcx>, - possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, - ) -> Self { +#[derive(Clone, Debug, Eq, PartialEq)] +struct PossibleBorrowerState { + map: FxIndexMap<Local, BitSet<Local>>, + domain_size: usize, +} + +impl PossibleBorrowerState { + fn new(domain_size: usize) -> Self { Self { - possible_borrower: TransitiveRelation::default(), - cx, - body, - possible_origin, + map: FxIndexMap::default(), + domain_size, } } - fn into_map( - self, - cx: &'a LateContext<'tcx>, - maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>, - ) -> PossibleBorrowerMap<'b, 'tcx> { - let mut map = FxHashMap::default(); - for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { - if is_copy(cx, self.body.local_decls[row].ty) { - continue; - } + #[allow(clippy::similar_names)] + fn add(&mut self, borrowed: Local, borrower: Local) { + self.map + .entry(borrowed) + .or_insert(BitSet::new_empty(self.domain_size)) + .insert(borrower); + } +} - let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len()); - borrowers.remove(mir::Local::from_usize(0)); +impl<C> DebugWithContext<C> for PossibleBorrowerState { + fn fmt_with(&self, _ctxt: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + <_ as std::fmt::Debug>::fmt(self, f) + } + fn fmt_diff_with(&self, _old: &Self, _ctxt: &C, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + unimplemented!() + } +} + +impl JoinSemiLattice for PossibleBorrowerState { + fn join(&mut self, other: &Self) -> bool { + let mut changed = false; + for (&borrowed, borrowers) in other.map.iter() { if !borrowers.is_empty() { - map.insert(row, borrowers); + changed |= self + .map + .entry(borrowed) + .or_insert(BitSet::new_empty(self.domain_size)) + .union(borrowers); } } + changed + } +} - let bs = BitSet::new_empty(self.body.local_decls.len()); - PossibleBorrowerMap { - map, - maybe_live, - bitset: (bs.clone(), bs), +impl<'b, 'tcx> AnalysisDomain<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> { + type Domain = PossibleBorrowerState; + + const NAME: &'static str = "possible_borrower"; + + fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { + PossibleBorrowerState::new(body.local_decls.len()) + } + + fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _entry_set: &mut Self::Domain) {} +} + +impl<'b, 'tcx> PossibleBorrowerAnalysis<'b, 'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + body: &'b mir::Body<'tcx>, + possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, + ) -> Self { + Self { + tcx, + body, + possible_origin, } } } -impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, 'tcx> { - fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) { - let lhs = place.local; - match rvalue { - mir::Rvalue::Ref(_, _, borrowed) => { - self.possible_borrower.add(borrowed.local, lhs); - }, - other => { - if ContainsRegion - .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty) - .is_continue() - { - return; - } - rvalue_locals(other, |rhs| { - if lhs != rhs { - self.possible_borrower.add(rhs, lhs); +impl<'b, 'tcx> Analysis<'tcx> for PossibleBorrowerAnalysis<'b, 'tcx> { + fn apply_call_return_effect( + &self, + _state: &mut Self::Domain, + _block: BasicBlock, + _return_places: CallReturnPlaces<'_, 'tcx>, + ) { + } + + fn apply_statement_effect(&self, state: &mut Self::Domain, statement: &Statement<'tcx>, _location: Location) { + if let StatementKind::Assign(box (place, rvalue)) = &statement.kind { + let lhs = place.local; + match rvalue { + mir::Rvalue::Ref(_, _, borrowed) => { + state.add(borrowed.local, lhs); + }, + other => { + if ContainsRegion + .visit_ty(place.ty(&self.body.local_decls, self.tcx).ty) + .is_continue() + { + return; } - }); - }, + rvalue_locals(other, |rhs| { + if lhs != rhs { + state.add(rhs, lhs); + } + }); + }, + } } } - fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) { + fn apply_terminator_effect(&self, state: &mut Self::Domain, terminator: &Terminator<'tcx>, _location: Location) { if let mir::TerminatorKind::Call { args, destination: mir::Place { local: dest, .. }, @@ -126,10 +171,10 @@ impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, for y in mutable_variables { for x in &immutable_borrowers { - self.possible_borrower.add(*x, y); + state.add(*x, y); } for x in &mutable_borrowers { - self.possible_borrower.add(*x, y); + state.add(*x, y); } } } @@ -165,73 +210,98 @@ fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { } } -/// Result of `PossibleBorrowerVisitor`. +/// Result of `PossibleBorrowerAnalysis`. #[allow(clippy::module_name_repetitions)] pub struct PossibleBorrowerMap<'b, 'tcx> { - /// Mapping `Local -> its possible borrowers` - pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>, - maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>, - // Caches to avoid allocation of `BitSet` on every query - pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>), + body: &'b mir::Body<'tcx>, + possible_borrower: ResultsCursor<'b, 'tcx, PossibleBorrowerAnalysis<'b, 'tcx>>, + maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'b>>, + pushed: BitSet<Local>, + stack: Vec<Local>, } -impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { - pub fn new(cx: &'a LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self { +impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { + pub fn new(cx: &LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self { let possible_origin = { let mut vis = PossibleOriginVisitor::new(mir); vis.visit_body(mir); vis.into_map(cx) }; - let maybe_storage_live_result = MaybeStorageLive + let possible_borrower = PossibleBorrowerAnalysis::new(cx.tcx, mir, possible_origin) .into_engine(cx.tcx, mir) - .pass_name("redundant_clone") + .pass_name("possible_borrower") .iterate_to_fixpoint() .into_results_cursor(mir); - let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin); - vis.visit_body(mir); - vis.into_map(cx, maybe_storage_live_result) - } - - /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`. - pub fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool { - self.bounded_borrowers(borrowers, borrowers, borrowed, at) + let maybe_live = MaybeStorageLive::new(Cow::Owned(BitSet::new_empty(mir.local_decls.len()))) + .into_engine(cx.tcx, mir) + .pass_name("possible_borrower") + .iterate_to_fixpoint() + .into_results_cursor(mir); + PossibleBorrowerMap { + body: mir, + possible_borrower, + maybe_live, + pushed: BitSet::new_empty(mir.local_decls.len()), + stack: Vec::with_capacity(mir.local_decls.len()), + } } - /// Returns true if the set of borrowers of `borrowed` living at `at` includes at least `below` - /// but no more than `above`. - pub fn bounded_borrowers( + /// Returns true if the set of borrowers of `borrowed` living at `at` includes no more than + /// `borrowers`. + /// Notes: + /// 1. It would be nice if `PossibleBorrowerMap` could store `cx` so that `at_most_borrowers` + /// would not require it to be passed in. But a `PossibleBorrowerMap` is stored in `LintPass` + /// `Dereferencing`, which outlives any `LateContext`. + /// 2. In all current uses of `at_most_borrowers`, `borrowers` is a slice of at most two + /// elements. Thus, `borrowers.contains(...)` is effectively a constant-time operation. If + /// `at_most_borrowers`'s uses were to expand beyond this, its implementation might have to be + /// adjusted. + pub fn at_most_borrowers( &mut self, - below: &[mir::Local], - above: &[mir::Local], + cx: &LateContext<'tcx>, + borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location, ) -> bool { - self.maybe_live.seek_after_primary_effect(at); + if is_copy(cx, self.body.local_decls[borrowed].ty) { + return true; + } - self.bitset.0.clear(); - let maybe_live = &mut self.maybe_live; - if let Some(bitset) = self.map.get(&borrowed) { - for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) { - self.bitset.0.insert(b); + self.possible_borrower.seek_before_primary_effect(at); + self.maybe_live.seek_before_primary_effect(at); + + let possible_borrower = &self.possible_borrower.get().map; + let maybe_live = &self.maybe_live; + + self.pushed.clear(); + self.stack.clear(); + + if let Some(borrowers) = possible_borrower.get(&borrowed) { + for b in borrowers.iter() { + if self.pushed.insert(b) { + self.stack.push(b); + } } } else { - return false; + // Nothing borrows `borrowed` at `at`. + return true; } - self.bitset.1.clear(); - for b in below { - self.bitset.1.insert(*b); - } - - if !self.bitset.0.superset(&self.bitset.1) { - return false; - } + while let Some(borrower) = self.stack.pop() { + if maybe_live.contains(borrower) && !borrowers.contains(&borrower) { + return false; + } - for b in above { - self.bitset.0.remove(*b); + if let Some(borrowers) = possible_borrower.get(&borrower) { + for b in borrowers.iter() { + if self.pushed.insert(b) { + self.stack.push(b); + } + } + } } - self.bitset.0.is_empty() + true } pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool { diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index b66604f33db..e7879bb196e 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -185,7 +185,6 @@ impl<'a> Sugg<'a> { ) -> Self { use rustc_ast::ast::RangeLimits; - #[expect(clippy::match_wildcard_for_single_variants)] match expr.kind { _ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0), ast::ExprKind::AddrOf(..) @@ -813,9 +812,9 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti let closure_body = cx.tcx.hir().body(body); // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`) // a type annotation is present if param `kind` is different from `TyKind::Infer` - let closure_arg_is_type_annotated_double_ref = if let TyKind::Rptr(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind + let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind { - matches!(ty.kind, TyKind::Rptr(_, MutTy { .. })) + matches!(ty.kind, TyKind::Ref(_, MutTy { .. })) } else { false }; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2773da70d78..c8d56a3be5c 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -496,7 +496,7 @@ pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bo /// Returns the base type for HIR references and pointers. pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { match ty.kind { - TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty), + TyKind::Ptr(ref mut_ty) | TyKind::Ref(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty), _ => ty, } } diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index 8e21cef32ab..9399d422036 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-12-17" +channel = "nightly-2022-12-29" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index 92ba3592967..22ce1c6f647 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -3,8 +3,7 @@ error: an async construct yields a type which is itself awaitable | LL | let _h = async { | _____________________- -LL | | async { - | | _________^ +LL | |/ async { LL | || 3 LL | || } | ||_________^ awaitable value not awaited @@ -37,8 +36,7 @@ error: an async construct yields a type which is itself awaitable | LL | let _j = async || { | ________________________- -LL | | async { - | | _________^ +LL | |/ async { LL | || 3 LL | || } | ||_________^ awaitable value not awaited diff --git a/src/tools/clippy/tests/ui/crashes/ice-10044.rs b/src/tools/clippy/tests/ui/crashes/ice-10044.rs new file mode 100644 index 00000000000..65f38fe7118 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-10044.rs @@ -0,0 +1,3 @@ +fn main() { + [0; usize::MAX]; +} diff --git a/src/tools/clippy/tests/ui/crashes/ice-10044.stderr b/src/tools/clippy/tests/ui/crashes/ice-10044.stderr new file mode 100644 index 00000000000..731f8265ad6 --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-10044.stderr @@ -0,0 +1,10 @@ +error: statement with no effect + --> $DIR/ice-10044.rs:2:5 + | +LL | [0; usize::MAX]; + | ^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::no-effect` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/floating_point_powi.fixed b/src/tools/clippy/tests/ui/floating_point_powi.fixed index 884d05fed71..8ffd4cc5137 100644 --- a/src/tools/clippy/tests/ui/floating_point_powi.fixed +++ b/src/tools/clippy/tests/ui/floating_point_powi.fixed @@ -14,6 +14,15 @@ fn main() { let _ = (y as f32).mul_add(y as f32, x); let _ = x.mul_add(x, y).sqrt(); let _ = y.mul_add(y, x).sqrt(); + + let _ = (x - 1.0).mul_add(x - 1.0, -y); + let _ = (x - 1.0).mul_add(x - 1.0, -y) + 3.0; + let _ = (x - 1.0).mul_add(x - 1.0, -(y + 3.0)); + let _ = (y + 1.0).mul_add(-(y + 1.0), x); + let _ = (3.0 * y).mul_add(-(3.0 * y), x); + let _ = (y + 1.0 + x).mul_add(-(y + 1.0 + x), x); + let _ = (y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x); + // Cases where the lint shouldn't be applied let _ = x.powi(2); let _ = x.powi(1 + 1); diff --git a/src/tools/clippy/tests/ui/floating_point_powi.rs b/src/tools/clippy/tests/ui/floating_point_powi.rs index e6a1c895371..9ae3455a134 100644 --- a/src/tools/clippy/tests/ui/floating_point_powi.rs +++ b/src/tools/clippy/tests/ui/floating_point_powi.rs @@ -14,6 +14,15 @@ fn main() { let _ = x + (y as f32).powi(2); let _ = (x.powi(2) + y).sqrt(); let _ = (x + y.powi(2)).sqrt(); + + let _ = (x - 1.0).powi(2) - y; + let _ = (x - 1.0).powi(2) - y + 3.0; + let _ = (x - 1.0).powi(2) - (y + 3.0); + let _ = x - (y + 1.0).powi(2); + let _ = x - (3.0 * y).powi(2); + let _ = x - (y + 1.0 + x).powi(2); + let _ = x - (y + 1.0 + 2.0).powi(2); + // Cases where the lint shouldn't be applied let _ = x.powi(2); let _ = x.powi(1 + 1); diff --git a/src/tools/clippy/tests/ui/floating_point_powi.stderr b/src/tools/clippy/tests/ui/floating_point_powi.stderr index 5df0de1fef2..fdf6d088052 100644 --- a/src/tools/clippy/tests/ui/floating_point_powi.stderr +++ b/src/tools/clippy/tests/ui/floating_point_powi.stderr @@ -42,5 +42,47 @@ error: multiply and add expressions can be calculated more efficiently and accur LL | let _ = (x + y.powi(2)).sqrt(); | ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)` -error: aborting due to 7 previous errors +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:18:13 + | +LL | let _ = (x - 1.0).powi(2) - y; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:19:13 + | +LL | let _ = (x - 1.0).powi(2) - y + 3.0; + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -y)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:20:13 + | +LL | let _ = (x - 1.0).powi(2) - (y + 3.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x - 1.0).mul_add(x - 1.0, -(y + 3.0))` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:21:13 + | +LL | let _ = x - (y + 1.0).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0).mul_add(-(y + 1.0), x)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:22:13 + | +LL | let _ = x - (3.0 * y).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(3.0 * y).mul_add(-(3.0 * y), x)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:23:13 + | +LL | let _ = x - (y + 1.0 + x).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + x).mul_add(-(y + 1.0 + x), x)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> $DIR/floating_point_powi.rs:24:13 + | +LL | let _ = x - (y + 1.0 + 2.0).powi(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y + 1.0 + 2.0).mul_add(-(y + 1.0 + 2.0), x)` + +error: aborting due to 14 previous errors diff --git a/src/tools/clippy/tests/ui/fn_null_check.rs b/src/tools/clippy/tests/ui/fn_null_check.rs new file mode 100644 index 00000000000..df5bc8420d5 --- /dev/null +++ b/src/tools/clippy/tests/ui/fn_null_check.rs @@ -0,0 +1,21 @@ +#![allow(unused)] +#![warn(clippy::fn_null_check)] +#![allow(clippy::cmp_null)] +#![allow(clippy::ptr_eq)] +#![allow(clippy::zero_ptr)] + +pub const ZPTR: *const () = 0 as *const _; +pub const NOT_ZPTR: *const () = 1 as *const _; + +fn main() { + let fn_ptr = main; + + if (fn_ptr as *mut ()).is_null() {} + if (fn_ptr as *const u8).is_null() {} + if (fn_ptr as *const ()) == std::ptr::null() {} + if (fn_ptr as *const ()) == (0 as *const ()) {} + if (fn_ptr as *const ()) == ZPTR {} + + // no lint + if (fn_ptr as *const ()) == NOT_ZPTR {} +} diff --git a/src/tools/clippy/tests/ui/fn_null_check.stderr b/src/tools/clippy/tests/ui/fn_null_check.stderr new file mode 100644 index 00000000000..660dd323979 --- /dev/null +++ b/src/tools/clippy/tests/ui/fn_null_check.stderr @@ -0,0 +1,43 @@ +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:13:8 + | +LL | if (fn_ptr as *mut ()).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + = note: `-D clippy::fn-null-check` implied by `-D warnings` + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:14:8 + | +LL | if (fn_ptr as *const u8).is_null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:15:8 + | +LL | if (fn_ptr as *const ()) == std::ptr::null() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:16:8 + | +LL | if (fn_ptr as *const ()) == (0 as *const ()) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: function pointer assumed to be nullable, even though it isn't + --> $DIR/fn_null_check.rs:17:8 + | +LL | if (fn_ptr as *const ()) == ZPTR {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_filter.fixed b/src/tools/clippy/tests/ui/manual_filter.fixed index 3553291b87d..ef6780dc96d 100644 --- a/src/tools/clippy/tests/ui/manual_filter.fixed +++ b/src/tools/clippy/tests/ui/manual_filter.fixed @@ -116,4 +116,45 @@ fn main() { }, None => None, }; + + match Some(20) { + // Don't Lint, because `Some(3*x)` is not `None` + None => None, + Some(x) => { + if x > 0 { + Some(3 * x) + } else { + Some(x) + } + }, + }; + + // Don't lint: https://github.com/rust-lang/rust-clippy/issues/10088 + let result = if let Some(a) = maybe_some() { + if let Some(b) = maybe_some() { + Some(a + b) + } else { + Some(a) + } + } else { + None + }; + + let allowed_integers = vec![3, 4, 5, 6]; + // Don't lint, since there's a side effect in the else branch + match Some(21) { + Some(x) => { + if allowed_integers.contains(&x) { + Some(x) + } else { + println!("Invalid integer: {x:?}"); + None + } + }, + None => None, + }; +} + +fn maybe_some() -> Option<u32> { + Some(0) } diff --git a/src/tools/clippy/tests/ui/manual_filter.rs b/src/tools/clippy/tests/ui/manual_filter.rs index aa9f90f752b..ea0ce83172b 100644 --- a/src/tools/clippy/tests/ui/manual_filter.rs +++ b/src/tools/clippy/tests/ui/manual_filter.rs @@ -240,4 +240,45 @@ fn main() { }, None => None, }; + + match Some(20) { + // Don't Lint, because `Some(3*x)` is not `None` + None => None, + Some(x) => { + if x > 0 { + Some(3 * x) + } else { + Some(x) + } + }, + }; + + // Don't lint: https://github.com/rust-lang/rust-clippy/issues/10088 + let result = if let Some(a) = maybe_some() { + if let Some(b) = maybe_some() { + Some(a + b) + } else { + Some(a) + } + } else { + None + }; + + let allowed_integers = vec![3, 4, 5, 6]; + // Don't lint, since there's a side effect in the else branch + match Some(21) { + Some(x) => { + if allowed_integers.contains(&x) { + Some(x) + } else { + println!("Invalid integer: {x:?}"); + None + } + }, + None => None, + }; +} + +fn maybe_some() -> Option<u32> { + Some(0) } diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed index e5ae3cf3e50..8f25fea678f 100644 --- a/src/tools/clippy/tests/ui/manual_retain.fixed +++ b/src/tools/clippy/tests/ui/manual_retain.fixed @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::manual_retain)] -#![allow(unused)] +#![allow(unused, clippy::redundant_clone)] use std::collections::BTreeMap; use std::collections::BTreeSet; use std::collections::BinaryHeap; diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs index 1021f15edd1..e6b3995a689 100644 --- a/src/tools/clippy/tests/ui/manual_retain.rs +++ b/src/tools/clippy/tests/ui/manual_retain.rs @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::manual_retain)] -#![allow(unused)] +#![allow(unused, clippy::redundant_clone)] use std::collections::BTreeMap; use std::collections::BTreeSet; use std::collections::BinaryHeap; diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed index a6e315e4773..6cfb6661a03 100644 --- a/src/tools/clippy/tests/ui/match_single_binding.fixed +++ b/src/tools/clippy/tests/ui/match_single_binding.fixed @@ -133,3 +133,16 @@ fn issue_9575() { println!("Needs curlies"); }; } + +#[allow(dead_code)] +fn issue_9725(r: Option<u32>) { + let x = r; + match x { + Some(_) => { + println!("Some"); + }, + None => { + println!("None"); + }, + }; +} diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs index cecbd703e56..f188aeb5f2f 100644 --- a/src/tools/clippy/tests/ui/match_single_binding.rs +++ b/src/tools/clippy/tests/ui/match_single_binding.rs @@ -148,3 +148,17 @@ fn issue_9575() { _ => println!("Needs curlies"), }; } + +#[allow(dead_code)] +fn issue_9725(r: Option<u32>) { + match r { + x => match x { + Some(_) => { + println!("Some"); + }, + None => { + println!("None"); + }, + }, + }; +} diff --git a/src/tools/clippy/tests/ui/match_single_binding.stderr b/src/tools/clippy/tests/ui/match_single_binding.stderr index 2b9ec7ee702..e960d64ad2b 100644 --- a/src/tools/clippy/tests/ui/match_single_binding.stderr +++ b/src/tools/clippy/tests/ui/match_single_binding.stderr @@ -213,5 +213,30 @@ LL + println!("Needs curlies"); LL ~ }; | -error: aborting due to 14 previous errors +error: this match could be written as a `let` statement + --> $DIR/match_single_binding.rs:154:5 + | +LL | / match r { +LL | | x => match x { +LL | | Some(_) => { +LL | | println!("Some"); +... | +LL | | }, +LL | | }; + | |_____^ + | +help: consider using a `let` statement + | +LL ~ let x = r; +LL + match x { +LL + Some(_) => { +LL + println!("Some"); +LL + }, +LL + None => { +LL + println!("None"); +LL + }, +LL ~ }; + | + +error: aborting due to 15 previous errors diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed index e675c183ea7..fc252cdd352 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.fixed @@ -132,3 +132,25 @@ fn main() { } } } + +mod issue9993 { + enum Foo { + A(bool), + B, + } + + fn test() { + let _ = match Foo::A(true) { + _ if false => 0, + Foo::A(true) => 1, + Foo::A(false) => 2, + Foo::B => 3, + }; + + let _ = match Foo::B { + _ if false => 0, + Foo::A(_) => 1, + Foo::B => 2, + }; + } +} diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs index 38c3ffc00c7..9a5c849e6ec 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.rs @@ -132,3 +132,25 @@ fn main() { } } } + +mod issue9993 { + enum Foo { + A(bool), + B, + } + + fn test() { + let _ = match Foo::A(true) { + _ if false => 0, + Foo::A(true) => 1, + Foo::A(false) => 2, + Foo::B => 3, + }; + + let _ = match Foo::B { + _ if false => 0, + Foo::A(_) => 1, + _ => 2, + }; + } +} diff --git a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr index 34538dea8e5..6fa313dc911 100644 --- a/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr +++ b/src/tools/clippy/tests/ui/match_wildcard_for_single_variants.stderr @@ -48,5 +48,11 @@ error: wildcard matches only a single variant and will also match any future add LL | _ => (), | ^ help: try this: `Color::Blue` -error: aborting due to 8 previous errors +error: wildcard matches only a single variant and will also match any future added variants + --> $DIR/match_wildcard_for_single_variants.rs:153:13 + | +LL | _ => 2, + | ^ help: try this: `Foo::B` + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index 4cb7f6b687f..31e1cb6c3d7 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![feature(lint_reasons)] +#![feature(custom_inner_attributes, lint_reasons, rustc_private)] #![allow( unused, clippy::uninlined_format_args, @@ -491,3 +491,14 @@ mod issue_9782_method_variant { S.foo::<&[u8; 100]>(&a); } } + +extern crate rustc_lint; +extern crate rustc_span; + +#[allow(dead_code)] +mod span_lint { + use rustc_lint::{LateContext, Lint, LintContext}; + fn foo(cx: &LateContext<'_>, lint: &'static Lint) { + cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(String::new())); + } +} diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 9a01190ed8d..55c2738fcf2 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -1,5 +1,5 @@ // run-rustfix -#![feature(lint_reasons)] +#![feature(custom_inner_attributes, lint_reasons, rustc_private)] #![allow( unused, clippy::uninlined_format_args, @@ -491,3 +491,14 @@ mod issue_9782_method_variant { S.foo::<&[u8; 100]>(&a); } } + +extern crate rustc_lint; +extern crate rustc_span; + +#[allow(dead_code)] +mod span_lint { + use rustc_lint::{LateContext, Lint, LintContext}; + fn foo(cx: &LateContext<'_>, lint: &'static Lint) { + cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new())); + } +} diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index d26c317124b..98a48d68317 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -216,5 +216,11 @@ error: the borrowed expression implements the required traits LL | foo(&a); | ^^ help: change this to: `a` -error: aborting due to 36 previous errors +error: the borrowed expression implements the required traits + --> $DIR/needless_borrow.rs:502:85 + | +LL | cx.struct_span_lint(lint, rustc_span::Span::default(), "", |diag| diag.note(&String::new())); + | ^^^^^^^^^^^^^^ help: change this to: `String::new()` + +error: aborting due to 37 previous errors diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index 4386aaec49e..d451be1f389 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -1,6 +1,7 @@ // run-rustfix #![feature(lint_reasons)] +#![feature(yeet_expr)] #![allow(unused)] #![allow( clippy::if_same_then_else, @@ -272,4 +273,8 @@ mod issue9416 { } } +fn issue9947() -> Result<(), String> { + do yeet "hello"; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index 666dc54b76b..e1a1bea2c0b 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -1,6 +1,7 @@ // run-rustfix #![feature(lint_reasons)] +#![feature(yeet_expr)] #![allow(unused)] #![allow( clippy::if_same_then_else, @@ -282,4 +283,8 @@ mod issue9416 { } } +fn issue9947() -> Result<(), String> { + do yeet "hello"; +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index a8b5d86cd55..ca2253e6586 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> $DIR/needless_return.rs:26:5 + --> $DIR/needless_return.rs:27:5 | LL | return true; | ^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:30:5 + --> $DIR/needless_return.rs:31:5 | LL | return true; | ^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:35:9 + --> $DIR/needless_return.rs:36:9 | LL | return true; | ^^^^^^^^^^^ @@ -24,7 +24,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:37:9 + --> $DIR/needless_return.rs:38:9 | LL | return false; | ^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | return false; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:43:17 + --> $DIR/needless_return.rs:44:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | true => return false, = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:45:13 + --> $DIR/needless_return.rs:46:13 | LL | return true; | ^^^^^^^^^^^ @@ -48,7 +48,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:52:9 + --> $DIR/needless_return.rs:53:9 | LL | return true; | ^^^^^^^^^^^ @@ -56,7 +56,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:54:16 + --> $DIR/needless_return.rs:55:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL | let _ = || return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:58:5 + --> $DIR/needless_return.rs:59:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | return the_answer!(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:61:21 + --> $DIR/needless_return.rs:62:21 | LL | fn test_void_fun() { | _____________________^ @@ -82,7 +82,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:66:11 + --> $DIR/needless_return.rs:67:11 | LL | if b { | ___________^ @@ -92,7 +92,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:68:13 + --> $DIR/needless_return.rs:69:13 | LL | } else { | _____________^ @@ -102,7 +102,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:76:14 + --> $DIR/needless_return.rs:77:14 | LL | _ => return, | ^^^^^^ @@ -110,7 +110,7 @@ LL | _ => return, = help: replace `return` with a unit value error: unneeded `return` statement - --> $DIR/needless_return.rs:84:24 + --> $DIR/needless_return.rs:85:24 | LL | let _ = 42; | ________________________^ @@ -120,7 +120,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:87:14 + --> $DIR/needless_return.rs:88:14 | LL | _ => return, | ^^^^^^ @@ -128,7 +128,7 @@ LL | _ => return, = help: replace `return` with a unit value error: unneeded `return` statement - --> $DIR/needless_return.rs:100:9 + --> $DIR/needless_return.rs:101:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -136,7 +136,7 @@ LL | return String::from("test"); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:102:9 + --> $DIR/needless_return.rs:103:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -144,7 +144,7 @@ LL | return String::new(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:124:32 + --> $DIR/needless_return.rs:125:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -152,7 +152,7 @@ LL | bar.unwrap_or_else(|_| return) = help: replace `return` with an empty block error: unneeded `return` statement - --> $DIR/needless_return.rs:128:21 + --> $DIR/needless_return.rs:129:21 | LL | let _ = || { | _____________________^ @@ -162,7 +162,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:131:20 + --> $DIR/needless_return.rs:132:20 | LL | let _ = || return; | ^^^^^^ @@ -170,7 +170,7 @@ LL | let _ = || return; = help: replace `return` with an empty block error: unneeded `return` statement - --> $DIR/needless_return.rs:137:32 + --> $DIR/needless_return.rs:138:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -178,7 +178,7 @@ LL | res.unwrap_or_else(|_| return Foo) = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:146:5 + --> $DIR/needless_return.rs:147:5 | LL | return true; | ^^^^^^^^^^^ @@ -186,7 +186,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:150:5 + --> $DIR/needless_return.rs:151:5 | LL | return true; | ^^^^^^^^^^^ @@ -194,7 +194,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:155:9 + --> $DIR/needless_return.rs:156:9 | LL | return true; | ^^^^^^^^^^^ @@ -202,7 +202,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:157:9 + --> $DIR/needless_return.rs:158:9 | LL | return false; | ^^^^^^^^^^^^ @@ -210,7 +210,7 @@ LL | return false; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:163:17 + --> $DIR/needless_return.rs:164:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -218,7 +218,7 @@ LL | true => return false, = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:165:13 + --> $DIR/needless_return.rs:166:13 | LL | return true; | ^^^^^^^^^^^ @@ -226,7 +226,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:172:9 + --> $DIR/needless_return.rs:173:9 | LL | return true; | ^^^^^^^^^^^ @@ -234,7 +234,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:174:16 + --> $DIR/needless_return.rs:175:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -242,7 +242,7 @@ LL | let _ = || return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:178:5 + --> $DIR/needless_return.rs:179:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -250,7 +250,7 @@ LL | return the_answer!(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:181:33 + --> $DIR/needless_return.rs:182:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -260,7 +260,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:186:11 + --> $DIR/needless_return.rs:187:11 | LL | if b { | ___________^ @@ -270,7 +270,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:188:13 + --> $DIR/needless_return.rs:189:13 | LL | } else { | _____________^ @@ -280,7 +280,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:196:14 + --> $DIR/needless_return.rs:197:14 | LL | _ => return, | ^^^^^^ @@ -288,7 +288,7 @@ LL | _ => return, = help: replace `return` with a unit value error: unneeded `return` statement - --> $DIR/needless_return.rs:209:9 + --> $DIR/needless_return.rs:210:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -296,7 +296,7 @@ LL | return String::from("test"); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:211:9 + --> $DIR/needless_return.rs:212:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -304,7 +304,7 @@ LL | return String::new(); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:227:5 + --> $DIR/needless_return.rs:228:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -312,7 +312,7 @@ LL | return format!("Hello {}", "world!"); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:238:9 + --> $DIR/needless_return.rs:239:9 | LL | return true; | ^^^^^^^^^^^ @@ -320,7 +320,7 @@ LL | return true; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:240:9 + --> $DIR/needless_return.rs:241:9 | LL | return false; | ^^^^^^^^^^^^ @@ -328,7 +328,7 @@ LL | return false; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:247:13 + --> $DIR/needless_return.rs:248:13 | LL | return 10; | ^^^^^^^^^ @@ -336,7 +336,7 @@ LL | return 10; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:250:13 + --> $DIR/needless_return.rs:251:13 | LL | return 100; | ^^^^^^^^^^ @@ -344,7 +344,7 @@ LL | return 100; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:258:9 + --> $DIR/needless_return.rs:259:9 | LL | return 0; | ^^^^^^^^ @@ -352,7 +352,7 @@ LL | return 0; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:265:13 + --> $DIR/needless_return.rs:266:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -360,7 +360,7 @@ LL | return *(x as *const isize); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:267:13 + --> $DIR/needless_return.rs:268:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -368,7 +368,7 @@ LL | return !*(x as *const isize); = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:274:20 + --> $DIR/needless_return.rs:275:20 | LL | let _ = 42; | ____________________^ @@ -379,7 +379,7 @@ LL | | return; = help: remove `return` error: unneeded `return` statement - --> $DIR/needless_return.rs:281:20 + --> $DIR/needless_return.rs:282:20 | LL | let _ = 42; return; | ^^^^^^^ diff --git a/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs b/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs new file mode 100644 index 00000000000..28c00d10094 --- /dev/null +++ b/src/tools/clippy/tests/ui/permissions_set_readonly_false.rs @@ -0,0 +1,29 @@ +#![allow(unused)] +#![warn(clippy::permissions_set_readonly_false)] + +use std::fs::File; + +struct A; + +impl A { + pub fn set_readonly(&mut self, b: bool) {} +} + +fn set_readonly(b: bool) {} + +fn main() { + let f = File::create("foo.txt").unwrap(); + let metadata = f.metadata().unwrap(); + let mut permissions = metadata.permissions(); + // lint here + permissions.set_readonly(false); + // no lint + permissions.set_readonly(true); + + let mut a = A; + // no lint here - a is not of type std::fs::Permissions + a.set_readonly(false); + + // no lint here - plain function + set_readonly(false); +} diff --git a/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr new file mode 100644 index 00000000000..e7a8ee6cb19 --- /dev/null +++ b/src/tools/clippy/tests/ui/permissions_set_readonly_false.stderr @@ -0,0 +1,13 @@ +error: call to `set_readonly` with argument `false` + --> $DIR/permissions_set_readonly_false.rs:19:5 + | +LL | permissions.set_readonly(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: on Unix platforms this results in the file being world writable + = help: you can set the desired permissions using `PermissionsExt`. For more information, see + https://doc.rust-lang.org/std/os/unix/fs/trait.PermissionsExt.html + = note: `-D clippy::permissions-set-readonly-false` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed index 00b42745093..a157b6a6f9a 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.fixed +++ b/src/tools/clippy/tests/ui/redundant_clone.fixed @@ -239,3 +239,9 @@ fn false_negative_5707() { let _z = x.clone(); // pr 7346 can't lint on `x` drop(y); } + +#[allow(unused, clippy::manual_retain)] +fn possible_borrower_improvements() { + let mut s = String::from("foobar"); + s = s.chars().filter(|&c| c != 'o').collect(); +} diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs index f899127db8d..430672e8b8d 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.rs +++ b/src/tools/clippy/tests/ui/redundant_clone.rs @@ -239,3 +239,9 @@ fn false_negative_5707() { let _z = x.clone(); // pr 7346 can't lint on `x` drop(y); } + +#[allow(unused, clippy::manual_retain)] +fn possible_borrower_improvements() { + let mut s = String::from("foobar"); + s = s.chars().filter(|&c| c != 'o').to_owned().collect(); +} diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr index 782590034d0..1bacc2c76af 100644 --- a/src/tools/clippy/tests/ui/redundant_clone.stderr +++ b/src/tools/clippy/tests/ui/redundant_clone.stderr @@ -179,5 +179,17 @@ note: this value is dropped without further use LL | foo(&x.clone(), move || { | ^ -error: aborting due to 15 previous errors +error: redundant clone + --> $DIR/redundant_clone.rs:246:40 + | +LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); + | ^^^^^^^^^^^ help: remove this + | +note: this value is dropped without further use + --> $DIR/redundant_clone.rs:246:9 + | +LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr index 2e1eb8eb180..d0e534f6356 100644 --- a/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/src/tools/clippy/tests/ui/result_map_unit_fn_unfixable.stderr @@ -19,10 +19,7 @@ LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type `()` --> $DIR/result_map_unit_fn_unfixable.rs:29:5 | -LL | x.field.map(|value| { - | ______^ - | | _____| - | || +LL | // x.field.map(|value| { LL | || do_nothing(value); LL | || do_nothing(value) LL | || }); diff --git a/src/tools/clippy/tests/ui/size_of_ref.rs b/src/tools/clippy/tests/ui/size_of_ref.rs new file mode 100644 index 00000000000..1e83ab82907 --- /dev/null +++ b/src/tools/clippy/tests/ui/size_of_ref.rs @@ -0,0 +1,27 @@ +#![allow(unused)] +#![warn(clippy::size_of_ref)] + +use std::mem::size_of_val; + +fn main() { + let x = 5; + let y = &x; + + size_of_val(&x); // no lint + size_of_val(y); // no lint + + size_of_val(&&x); + size_of_val(&y); +} + +struct S { + field: u32, + data: Vec<u8>, +} + +impl S { + /// Get size of object including `self`, in bytes. + pub fn size(&self) -> usize { + std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity()) + } +} diff --git a/src/tools/clippy/tests/ui/size_of_ref.stderr b/src/tools/clippy/tests/ui/size_of_ref.stderr new file mode 100644 index 00000000000..d4c13ac3290 --- /dev/null +++ b/src/tools/clippy/tests/ui/size_of_ref.stderr @@ -0,0 +1,27 @@ +error: argument to `std::mem::size_of_val()` is a reference to a reference + --> $DIR/size_of_ref.rs:13:5 + | +LL | size_of_val(&&x); + | ^^^^^^^^^^^^^^^^ + | + = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = note: `-D clippy::size-of-ref` implied by `-D warnings` + +error: argument to `std::mem::size_of_val()` is a reference to a reference + --> $DIR/size_of_ref.rs:14:5 + | +LL | size_of_val(&y); + | ^^^^^^^^^^^^^^^ + | + = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + +error: argument to `std::mem::size_of_val()` is a reference to a reference + --> $DIR/size_of_ref.rs:25:9 + | +LL | std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.rs b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs new file mode 100644 index 00000000000..b3ea3d9039e --- /dev/null +++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.rs @@ -0,0 +1,28 @@ +#![allow(dead_code)] +#![warn(clippy::transmute_null_to_fn)] +#![allow(clippy::zero_ptr)] + +// Easy to lint because these only span one line. +fn one_liners() { + unsafe { + let _: fn() = std::mem::transmute(0 as *const ()); + let _: fn() = std::mem::transmute(std::ptr::null::<()>()); + } +} + +pub const ZPTR: *const usize = 0 as *const _; +pub const NOT_ZPTR: *const usize = 1 as *const _; + +fn transmute_const() { + unsafe { + // Should raise a lint. + let _: fn() = std::mem::transmute(ZPTR); + // Should NOT raise a lint. + let _: fn() = std::mem::transmute(NOT_ZPTR); + } +} + +fn main() { + one_liners(); + transmute_const(); +} diff --git a/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr new file mode 100644 index 00000000000..f0c65497d75 --- /dev/null +++ b/src/tools/clippy/tests/ui/transmute_null_to_fn.stderr @@ -0,0 +1,27 @@ +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:8:23 + | +LL | let _: fn() = std::mem::transmute(0 as *const ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value + = note: `-D clippy::transmute-null-to-fn` implied by `-D warnings` + +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:9:23 + | +LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value + +error: transmuting a known null pointer into a function pointer + --> $DIR/transmute_null_to_fn.rs:19:23 + | +LL | let _: fn() = std::mem::transmute(ZPTR); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ this transmute results in undefined behavior + | + = help: try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed index 70ff08f3655..94b206d8e58 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.fixed +++ b/src/tools/clippy/tests/ui/useless_conversion.fixed @@ -33,12 +33,71 @@ fn test_issue_3913() -> Result<(), std::io::Error> { Ok(()) } -fn test_issue_5833() -> Result<(), ()> { +fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() { let text = "foo\r\nbar\n\nbaz\n"; let lines = text.lines(); if Some("ok") == lines.into_iter().next() {} +} - Ok(()) +fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines(); + if Some("ok") == lines.next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines(); + if Some("ok") == lines.next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator_2() { + let text = "foo\r\nbar\n\nbaz\n"; + if Some("ok") == text.lines().next() {} +} + +#[allow(const_item_mutation)] +fn lint_into_iter_on_const_implementing_iterator() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let _ = NUMBERS.next(); +} + +fn lint_into_iter_on_const_implementing_iterator_2() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let mut n = NUMBERS; + n.next(); +} + +#[derive(Clone, Copy)] +struct CopiableCounter { + counter: u32, +} + +impl Iterator for CopiableCounter { + type Item = u32; + + fn next(&mut self) -> Option<Self::Item> { + self.counter = self.counter.wrapping_add(1); + Some(self.counter) + } +} + +fn dont_lint_into_iter_on_copy_iter() { + let mut c = CopiableCounter { counter: 0 }; + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.next(), Some(1)); + assert_eq!(c.next(), Some(2)); +} + +fn dont_lint_into_iter_on_static_copy_iter() { + static mut C: CopiableCounter = CopiableCounter { counter: 0 }; + unsafe { + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.next(), Some(1)); + assert_eq!(C.next(), Some(2)); + } } fn main() { @@ -46,7 +105,15 @@ fn main() { test_generic2::<i32, i32>(10i32); test_questionmark().unwrap(); test_issue_3913().unwrap(); - test_issue_5833().unwrap(); + + dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_mutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_expr_implementing_iterator(); + lint_into_iter_on_expr_implementing_iterator_2(); + lint_into_iter_on_const_implementing_iterator(); + lint_into_iter_on_const_implementing_iterator_2(); + dont_lint_into_iter_on_copy_iter(); + dont_lint_into_iter_on_static_copy_iter(); let _: String = "foo".into(); let _: String = From::from("foo"); diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs index f2444a8f436..c7ae927941b 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.rs +++ b/src/tools/clippy/tests/ui/useless_conversion.rs @@ -33,12 +33,71 @@ fn test_issue_3913() -> Result<(), std::io::Error> { Ok(()) } -fn test_issue_5833() -> Result<(), ()> { +fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() { let text = "foo\r\nbar\n\nbaz\n"; let lines = text.lines(); if Some("ok") == lines.into_iter().next() {} +} - Ok(()) +fn lint_into_iter_on_mutable_local_implementing_iterator_in_expr() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines(); + if Some("ok") == lines.into_iter().next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator() { + let text = "foo\r\nbar\n\nbaz\n"; + let mut lines = text.lines().into_iter(); + if Some("ok") == lines.next() {} +} + +fn lint_into_iter_on_expr_implementing_iterator_2() { + let text = "foo\r\nbar\n\nbaz\n"; + if Some("ok") == text.lines().into_iter().next() {} +} + +#[allow(const_item_mutation)] +fn lint_into_iter_on_const_implementing_iterator() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let _ = NUMBERS.into_iter().next(); +} + +fn lint_into_iter_on_const_implementing_iterator_2() { + const NUMBERS: std::ops::Range<i32> = 0..10; + let mut n = NUMBERS.into_iter(); + n.next(); +} + +#[derive(Clone, Copy)] +struct CopiableCounter { + counter: u32, +} + +impl Iterator for CopiableCounter { + type Item = u32; + + fn next(&mut self) -> Option<Self::Item> { + self.counter = self.counter.wrapping_add(1); + Some(self.counter) + } +} + +fn dont_lint_into_iter_on_copy_iter() { + let mut c = CopiableCounter { counter: 0 }; + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.into_iter().next(), Some(1)); + assert_eq!(c.next(), Some(1)); + assert_eq!(c.next(), Some(2)); +} + +fn dont_lint_into_iter_on_static_copy_iter() { + static mut C: CopiableCounter = CopiableCounter { counter: 0 }; + unsafe { + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.into_iter().next(), Some(1)); + assert_eq!(C.next(), Some(1)); + assert_eq!(C.next(), Some(2)); + } } fn main() { @@ -46,7 +105,15 @@ fn main() { test_generic2::<i32, i32>(10i32); test_questionmark().unwrap(); test_issue_3913().unwrap(); - test_issue_5833().unwrap(); + + dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_mutable_local_implementing_iterator_in_expr(); + lint_into_iter_on_expr_implementing_iterator(); + lint_into_iter_on_expr_implementing_iterator_2(); + lint_into_iter_on_const_implementing_iterator(); + lint_into_iter_on_const_implementing_iterator_2(); + dont_lint_into_iter_on_copy_iter(); + dont_lint_into_iter_on_static_copy_iter(); let _: String = "foo".into(); let _: String = From::from("foo"); diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr index 65ee3807fa9..be067c6843a 100644 --- a/src/tools/clippy/tests/ui/useless_conversion.stderr +++ b/src/tools/clippy/tests/ui/useless_conversion.stderr @@ -22,71 +22,101 @@ error: useless conversion to the same type: `i32` LL | let _: i32 = 0i32.into(); | ^^^^^^^^^^^ help: consider removing `.into()`: `0i32` +error: useless conversion to the same type: `std::str::Lines<'_>` + --> $DIR/useless_conversion.rs:45:22 + | +LL | if Some("ok") == lines.into_iter().next() {} + | ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines` + +error: useless conversion to the same type: `std::str::Lines<'_>` + --> $DIR/useless_conversion.rs:50:21 + | +LL | let mut lines = text.lines().into_iter(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` + +error: useless conversion to the same type: `std::str::Lines<'_>` + --> $DIR/useless_conversion.rs:56:22 + | +LL | if Some("ok") == text.lines().into_iter().next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()` + +error: useless conversion to the same type: `std::ops::Range<i32>` + --> $DIR/useless_conversion.rs:62:13 + | +LL | let _ = NUMBERS.into_iter().next(); + | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` + +error: useless conversion to the same type: `std::ops::Range<i32>` + --> $DIR/useless_conversion.rs:67:17 + | +LL | let mut n = NUMBERS.into_iter(); + | ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS` + error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:61:21 + --> $DIR/useless_conversion.rs:128:21 | LL | let _: String = "foo".to_string().into(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:62:21 + --> $DIR/useless_conversion.rs:129:21 | LL | let _: String = From::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:63:13 + --> $DIR/useless_conversion.rs:130:13 | LL | let _ = String::from("foo".to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:64:13 + --> $DIR/useless_conversion.rs:131:13 | LL | let _ = String::from(format!("A: {:04}", 123)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)` error: useless conversion to the same type: `std::str::Lines<'_>` - --> $DIR/useless_conversion.rs:65:13 + --> $DIR/useless_conversion.rs:132:13 | LL | let _ = "".lines().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()` error: useless conversion to the same type: `std::vec::IntoIter<i32>` - --> $DIR/useless_conversion.rs:66:13 + --> $DIR/useless_conversion.rs:133:13 | LL | let _ = vec![1, 2, 3].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()` error: useless conversion to the same type: `std::string::String` - --> $DIR/useless_conversion.rs:67:21 + --> $DIR/useless_conversion.rs:134:21 | LL | let _: String = format!("Hello {}", "world").into(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")` error: useless conversion to the same type: `i32` - --> $DIR/useless_conversion.rs:72:13 + --> $DIR/useless_conversion.rs:139:13 | LL | let _ = i32::from(a + b) * 3; | ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)` error: useless conversion to the same type: `Foo<'a'>` - --> $DIR/useless_conversion.rs:78:23 + --> $DIR/useless_conversion.rs:145:23 | LL | let _: Foo<'a'> = s2.into(); | ^^^^^^^^^ help: consider removing `.into()`: `s2` error: useless conversion to the same type: `Foo<'a'>` - --> $DIR/useless_conversion.rs:80:13 + --> $DIR/useless_conversion.rs:147:13 | LL | let _ = Foo::<'a'>::from(s3); | ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3` error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>` - --> $DIR/useless_conversion.rs:82:13 + --> $DIR/useless_conversion.rs:149:13 | LL | let _ = vec![s4, s4, s4].into_iter().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()` -error: aborting due to 14 previous errors +error: aborting due to 19 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed index ef55f1c31a8..0baec6f0b64 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed @@ -5,7 +5,6 @@ // the 2015 edition here is needed because edition 2018 changed the module system // (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint // no longer detects some of the cases starting with Rust 2018. -// FIXME: We should likely add another edition 2021 test case for this lint #![warn(clippy::wildcard_imports)] #![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs index b8128514206..db591d56ab4 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.rs +++ b/src/tools/clippy/tests/ui/wildcard_imports.rs @@ -5,7 +5,6 @@ // the 2015 edition here is needed because edition 2018 changed the module system // (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint // no longer detects some of the cases starting with Rust 2018. -// FIXME: We should likely add another edition 2021 test case for this lint #![warn(clippy::wildcard_imports)] #![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr index 626c1754fc8..6b469cdfc44 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr @@ -1,5 +1,5 @@ error: usage of wildcard import - --> $DIR/wildcard_imports.rs:16:5 + --> $DIR/wildcard_imports.rs:15:5 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` @@ -7,85 +7,85 @@ LL | use crate::fn_mod::*; = note: `-D clippy::wildcard-imports` implied by `-D warnings` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:17:5 + --> $DIR/wildcard_imports.rs:16:5 | LL | use crate::mod_mod::*; | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:18:5 + --> $DIR/wildcard_imports.rs:17:5 | LL | use crate::multi_fn_mod::*; | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:20:5 + --> $DIR/wildcard_imports.rs:19:5 | LL | use crate::struct_mod::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:24:5 + --> $DIR/wildcard_imports.rs:23:5 | LL | use wildcard_imports_helper::inner::inner_for_self_import::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:25:5 + --> $DIR/wildcard_imports.rs:24:5 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:96:13 + --> $DIR/wildcard_imports.rs:95:13 | LL | use crate::fn_mod::*; | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:102:75 + --> $DIR/wildcard_imports.rs:101:75 | LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; | ^ help: try: `inner_extern_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:103:13 + --> $DIR/wildcard_imports.rs:102:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:114:20 + --> $DIR/wildcard_imports.rs:113:20 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^ help: try: `inner::inner_foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:114:30 + --> $DIR/wildcard_imports.rs:113:30 | LL | use self::{inner::*, inner2::*}; | ^^^^^^^^^ help: try: `inner2::inner_bar` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:121:13 + --> $DIR/wildcard_imports.rs:120:13 | LL | use wildcard_imports_helper::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:150:9 + --> $DIR/wildcard_imports.rs:149:9 | LL | use crate::in_fn_test::*; | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:159:9 + --> $DIR/wildcard_imports.rs:158:9 | LL | use crate:: in_fn_test:: * ; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:160:9 + --> $DIR/wildcard_imports.rs:159:9 | LL | use crate:: fn_mod:: | _________^ @@ -93,37 +93,37 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:171:13 + --> $DIR/wildcard_imports.rs:170:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:206:17 + --> $DIR/wildcard_imports.rs:205:17 | LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:214:13 + --> $DIR/wildcard_imports.rs:213:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:223:17 + --> $DIR/wildcard_imports.rs:222:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:232:13 + --> $DIR/wildcard_imports.rs:231:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:240:13 + --> $DIR/wildcard_imports.rs:239:13 | LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed new file mode 100644 index 00000000000..6d534a10edc --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -0,0 +1,240 @@ +// revisions: edition2018 edition2021 +//[edition2018] edition:2018 +//[edition2021] edition:2021 +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::foo; +use crate::mod_mod::inner_mod; +use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +use crate::struct_mod::{A, inner_struct_mod}; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +use wildcard_imports_helper::prelude::v1::*; +use wildcard_imports_helper::{ExternA, extern_foo}; + +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { + Ok(0) + } +} + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + let _ = PreludeModAnywhere; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::foo; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + use wildcard_imports_helper::{ExternA, extern_foo}; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::inner_foo, inner2::inner_bar}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test::exported; + use crate:: fn_mod::foo; + + exported(); + foo(); +} + +mod super_imports { + fn foofoo() {} + + mod should_be_replaced { + use super::foofoo; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass_inside_function { + fn with_super_inside_function() { + use super::*; + let _ = foofoo(); + } + } + + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_further_inside { + fn insidefoo() {} + mod inner { + use super::insidefoo; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { + use crate::super_imports::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super_should_be_replaced { + mod inner { + use super::super::foofoo; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit_should_be_replaced { + use super::super::super_imports::foofoo; + + fn with_super_explicit() { + let _ = foofoo(); + } + } + + mod attestation_should_be_replaced { + use super::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } +} diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr new file mode 100644 index 00000000000..acca9f651b4 --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -0,0 +1,132 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:13:5 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:14:5 + | +LL | use crate::mod_mod::*; + | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:15:5 + | +LL | use crate::multi_fn_mod::*; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:16:5 + | +LL | use crate::struct_mod::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:19:5 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:21:5 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:91:13 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:97:75 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + | ^ help: try: `inner_extern_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:98:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:20 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^ help: try: `inner::inner_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:30 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^^ help: try: `inner2::inner_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:116:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:145:9 + | +LL | use crate::in_fn_test::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:154:9 + | +LL | use crate:: in_fn_test:: * ; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:155:9 + | +LL | use crate:: fn_mod:: + | _________^ +LL | | *; + | |_________^ help: try: `crate:: fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:166:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:201:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:209:13 + | +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:218:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:227:13 + | +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:235:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: aborting due to 21 previous errors + diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed new file mode 100644 index 00000000000..6d534a10edc --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -0,0 +1,240 @@ +// revisions: edition2018 edition2021 +//[edition2018] edition:2018 +//[edition2021] edition:2021 +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::foo; +use crate::mod_mod::inner_mod; +use crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}; +use crate::struct_mod::{A, inner_struct_mod}; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar; +use wildcard_imports_helper::prelude::v1::*; +use wildcard_imports_helper::{ExternA, extern_foo}; + +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { + Ok(0) + } +} + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + let _ = PreludeModAnywhere; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::foo; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, inner_extern_foo}; + use wildcard_imports_helper::{ExternA, extern_foo}; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::inner_foo, inner2::inner_bar}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test::exported; + use crate:: fn_mod::foo; + + exported(); + foo(); +} + +mod super_imports { + fn foofoo() {} + + mod should_be_replaced { + use super::foofoo; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass_inside_function { + fn with_super_inside_function() { + use super::*; + let _ = foofoo(); + } + } + + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_further_inside { + fn insidefoo() {} + mod inner { + use super::insidefoo; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { + use crate::super_imports::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super_should_be_replaced { + mod inner { + use super::super::foofoo; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit_should_be_replaced { + use super::super::super_imports::foofoo; + + fn with_super_explicit() { + let _ = foofoo(); + } + } + + mod attestation_should_be_replaced { + use super::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } +} diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr new file mode 100644 index 00000000000..acca9f651b4 --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -0,0 +1,132 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:13:5 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:14:5 + | +LL | use crate::mod_mod::*; + | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:15:5 + | +LL | use crate::multi_fn_mod::*; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:16:5 + | +LL | use crate::struct_mod::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:19:5 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:21:5 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:91:13 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:97:75 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + | ^ help: try: `inner_extern_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:98:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:20 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^ help: try: `inner::inner_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:109:30 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^^ help: try: `inner2::inner_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:116:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:145:9 + | +LL | use crate::in_fn_test::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:154:9 + | +LL | use crate:: in_fn_test:: * ; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:155:9 + | +LL | use crate:: fn_mod:: + | _________^ +LL | | *; + | |_________^ help: try: `crate:: fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:166:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:201:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:209:13 + | +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:218:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:227:13 + | +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:235:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: aborting due to 21 previous errors + diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.rs b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs new file mode 100644 index 00000000000..b5ed58e6813 --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.rs @@ -0,0 +1,241 @@ +// revisions: edition2018 edition2021 +//[edition2018] edition:2018 +//[edition2021] edition:2021 +// run-rustfix +// aux-build:wildcard_imports_helper.rs + +#![warn(clippy::wildcard_imports)] +#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)] +#![warn(unused_imports)] + +extern crate wildcard_imports_helper; + +use crate::fn_mod::*; +use crate::mod_mod::*; +use crate::multi_fn_mod::*; +use crate::struct_mod::*; + +#[allow(unused_imports)] +use wildcard_imports_helper::inner::inner_for_self_import::*; +use wildcard_imports_helper::prelude::v1::*; +use wildcard_imports_helper::*; + +use std::io::prelude::*; + +struct ReadFoo; + +impl Read for ReadFoo { + fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { + Ok(0) + } +} + +mod fn_mod { + pub fn foo() {} +} + +mod mod_mod { + pub mod inner_mod { + pub fn foo() {} + } +} + +mod multi_fn_mod { + pub fn multi_foo() {} + pub fn multi_bar() {} + pub fn multi_baz() {} + pub mod multi_inner_mod { + pub fn foo() {} + } +} + +mod struct_mod { + pub struct A; + pub struct B; + pub mod inner_struct_mod { + pub struct C; + } + + #[macro_export] + macro_rules! double_struct_import_test { + () => { + let _ = A; + }; + } +} + +fn main() { + foo(); + multi_foo(); + multi_bar(); + multi_inner_mod::foo(); + inner_mod::foo(); + extern_foo(); + inner_extern_bar(); + + let _ = A; + let _ = inner_struct_mod::C; + let _ = ExternA; + let _ = PreludeModAnywhere; + + double_struct_import_test!(); + double_struct_import_test!(); +} + +mod in_fn_test { + pub use self::inner_exported::*; + #[allow(unused_imports)] + pub(crate) use self::inner_exported2::*; + + fn test_intern() { + use crate::fn_mod::*; + + foo(); + } + + fn test_extern() { + use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + use wildcard_imports_helper::*; + + inner_for_self_import::inner_extern_foo(); + inner_extern_foo(); + + extern_foo(); + + let _ = ExternA; + } + + fn test_inner_nested() { + use self::{inner::*, inner2::*}; + + inner_foo(); + inner_bar(); + } + + fn test_extern_reexported() { + use wildcard_imports_helper::*; + + extern_exported(); + let _ = ExternExportedStruct; + let _ = ExternExportedEnum::A; + } + + mod inner_exported { + pub fn exported() {} + pub struct ExportedStruct; + pub enum ExportedEnum { + A, + } + } + + mod inner_exported2 { + pub(crate) fn exported2() {} + } + + mod inner { + pub fn inner_foo() {} + } + + mod inner2 { + pub fn inner_bar() {} + } +} + +fn test_reexported() { + use crate::in_fn_test::*; + + exported(); + let _ = ExportedStruct; + let _ = ExportedEnum::A; +} + +#[rustfmt::skip] +fn test_weird_formatting() { + use crate:: in_fn_test:: * ; + use crate:: fn_mod:: + *; + + exported(); + foo(); +} + +mod super_imports { + fn foofoo() {} + + mod should_be_replaced { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod test_should_pass_inside_function { + fn with_super_inside_function() { + use super::*; + let _ = foofoo(); + } + } + + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { + use crate::super_imports::*; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super_should_be_replaced { + mod inner { + use super::super::*; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit_should_be_replaced { + use super::super::super_imports::*; + + fn with_super_explicit() { + let _ = foofoo(); + } + } + + mod attestation_should_be_replaced { + use super::*; + + fn with_explicit() { + let _ = foofoo(); + } + } +} diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr new file mode 100644 index 00000000000..92f6d31530f --- /dev/null +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.stderr @@ -0,0 +1,132 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:9:5 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:10:5 + | +LL | use crate::mod_mod::*; + | ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:11:5 + | +LL | use crate::multi_fn_mod::*; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:12:5 + | +LL | use crate::struct_mod::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:15:5 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:17:5 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:87:13 + | +LL | use crate::fn_mod::*; + | ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:93:75 + | +LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *}; + | ^ help: try: `inner_extern_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:94:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:105:20 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^ help: try: `inner::inner_foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:105:30 + | +LL | use self::{inner::*, inner2::*}; + | ^^^^^^^^^ help: try: `inner2::inner_bar` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:112:13 + | +LL | use wildcard_imports_helper::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:141:9 + | +LL | use crate::in_fn_test::*; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:150:9 + | +LL | use crate:: in_fn_test:: * ; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:151:9 + | +LL | use crate:: fn_mod:: + | _________^ +LL | | *; + | |_________^ help: try: `crate:: fn_mod::foo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:162:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:197:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:205:13 + | +LL | use crate::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:214:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:223:13 + | +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports_2021.rs:231:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: aborting due to 21 previous errors + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 95f6e047bf9..7a3c0d28fc3 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2303,6 +2303,8 @@ impl<'test> TestCx<'test> { } else { filecheck.args(&["--check-prefixes", &prefixes]); } + // Provide more context on failures. + filecheck.args(&["--dump-input-context", "100"]); self.compose_and_run(filecheck, "", None, None) } diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index e15f5fe3ccc..291d02d67bd 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -5,7 +5,7 @@ use rustdoc_json_types::{ Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Module, OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding, - TypeBindingKind, Typedef, Union, Variant, WherePredicate, + TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate, }; use crate::{item_kind::Kind, Error, ErrorKind}; @@ -140,24 +140,24 @@ impl<'a> Validator<'a> { } fn check_variant(&mut self, x: &'a Variant, id: &'a Id) { - match x { - Variant::Plain(discr) => { - if let Some(discr) = discr { - if let (Err(_), Err(_)) = - (discr.value.parse::<i128>(), discr.value.parse::<u128>()) - { - self.fail( - id, - ErrorKind::Custom(format!( - "Failed to parse discriminant value `{}`", - discr.value - )), - ); - } - } + let Variant { kind, discriminant } = x; + + if let Some(discr) = discriminant { + if let (Err(_), Err(_)) = (discr.value.parse::<i128>(), discr.value.parse::<u128>()) { + self.fail( + id, + ErrorKind::Custom(format!( + "Failed to parse discriminant value `{}`", + discr.value + )), + ); } - Variant::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)), - Variant::Struct { fields, fields_stripped: _ } => { + } + + match kind { + VariantKind::Plain => {} + VariantKind::Tuple(tys) => tys.iter().flatten().for_each(|t| self.add_field_id(t)), + VariantKind::Struct { fields, fields_stripped: _ } => { fields.iter().for_each(|f| self.add_field_id(f)) } } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 97750cb78cd..7024927b205 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -54,6 +54,11 @@ extern crate rustc_session; extern crate rustc_span; extern crate rustc_target; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + mod borrow_tracker; mod clock; mod concurrency; diff --git a/src/tools/rust-installer b/src/tools/rust-installer -Subproject 300b5ec61ef38855a07e6bb4955a37aa1c414c0 +Subproject 5b2eee7eed72b4894909c5eecbf014ea0b5ad99 diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index 1d1ef525f23..0c27bcacfb8 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -24,6 +24,11 @@ extern crate rustc_parse; extern crate rustc_session; extern crate rustc_span; +// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta +// files. +#[allow(unused_extern_crates)] +extern crate rustc_driver; + use std::cell::RefCell; use std::collections::HashMap; use std::fmt; diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index d5177a2057b..c1991e8d2c8 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -688,7 +688,7 @@ impl Rewrite for ast::Ty { rewrite_unary_prefix(context, prefix, &*mt.ty, shape) } - ast::TyKind::Rptr(ref lifetime, ref mt) => { + ast::TyKind::Ref(ref lifetime, ref mt) => { let mut_str = format_mutability(mt.mutbl); let mut_len = mut_str.len(); let mut result = String::with_capacity(128); @@ -1059,7 +1059,7 @@ pub(crate) fn can_be_overflowed_type( ) -> bool { match ty.kind { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Rptr(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { + ast::TyKind::Ref(_, ref mutty) | ast::TyKind::Ptr(ref mutty) => { can_be_overflowed_type(context, &*mutty.ty, len) } _ => false, diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 97d038da702..fff83a1d097 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -11,6 +11,7 @@ miropt-test-tools = { path = "../miropt-test-tools" } lazy_static = "1" walkdir = "2" ignore = "0.4.18" +termcolor = "1.1.3" [[bin]] name = "rust-tidy" diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs index 49fc2ceb3a2..3f060e437ac 100644 --- a/src/tools/tidy/src/error_codes_check.rs +++ b/src/tools/tidy/src/error_codes_check.rs @@ -11,8 +11,8 @@ use regex::Regex; // A few of those error codes can't be tested but all the others can and *should* be tested! const EXEMPTED_FROM_TEST: &[&str] = &[ - "E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0519", "E0523", "E0554", "E0640", - "E0717", "E0729", "E0789", + "E0313", "E0461", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", + "E0789", ]; // Some error codes don't have any tests apparently... @@ -80,15 +80,6 @@ fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool { ignore_found } -macro_rules! some_or_continue { - ($e:expr) => { - match $e { - Some(e) => e, - None => continue, - } - }; -} - fn extract_error_codes( f: &str, error_codes: &mut HashMap<String, ErrorCodeStatus>, @@ -122,10 +113,16 @@ fn extract_error_codes( Some((file_name, _)) => file_name, }, }; - let path = some_or_continue!(path.parent()) + + let Some(parent) = path.parent() else { + continue; + }; + + let path = parent .join(md_file_name) .canonicalize() .expect("failed to canonicalize error explanation file path"); + match read_to_string(&path) { Ok(content) => { let has_test = check_if_error_code_is_test_in_explanation(&content, &err_code); @@ -215,8 +212,6 @@ pub fn check(paths: &[&Path], bad: &mut bool) { // * #[error = "E0111"] let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap(); - println!("Checking which error codes lack tests..."); - for path in paths { walk(path, &mut filter_dirs, &mut |entry, contents| { let file_name = entry.file_name(); @@ -245,20 +240,15 @@ pub fn check(paths: &[&Path], bad: &mut bool) { }); } if found_explanations == 0 { - eprintln!("No error code explanation was tested!"); - *bad = true; + tidy_error!(bad, "No error code explanation was tested!"); } if found_tests == 0 { - eprintln!("No error code was found in compilation errors!"); - *bad = true; + tidy_error!(bad, "No error code was found in compilation errors!"); } if explanations.is_empty() { - eprintln!("No error code explanation was found!"); - *bad = true; + tidy_error!(bad, "No error code explanation was found!"); } if errors.is_empty() { - println!("Found {} error codes", error_codes.len()); - for (err_code, error_status) in &error_codes { if !error_status.has_test && !EXEMPTED_FROM_TEST.contains(&err_code.as_str()) { errors.push(format!("Error code {err_code} needs to have at least one UI test!")); @@ -310,11 +300,6 @@ pub fn check(paths: &[&Path], bad: &mut bool) { } errors.sort(); for err in &errors { - eprintln!("{err}"); - } - println!("Found {} error(s) in error codes", errors.len()); - if !errors.is_empty() { - *bad = true; + tidy_error!(bad, "{err}"); } - println!("Done!"); } diff --git a/src/tools/tidy/src/features/version/tests.rs b/src/tools/tidy/src/features/version/tests.rs index 31224fdf1ea..7701dce2df1 100644 --- a/src/tools/tidy/src/features/version/tests.rs +++ b/src/tools/tidy/src/features/version/tests.rs @@ -12,8 +12,8 @@ fn test_try_from_invalid_version() { #[test] fn test_try_from_single() { - assert_eq!("1.32.0".parse(), Ok(Version { parts: [1, 32, 0] })); - assert_eq!("1.0.0".parse(), Ok(Version { parts: [1, 0, 0] })); + assert_eq!("1.32.0".parse(), Ok(Version::Explicit { parts: [1, 32, 0] })); + assert_eq!("1.0.0".parse(), Ok(Version::Explicit { parts: [1, 0, 0] })); } #[test] diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 698e4850bea..ce7e7ac5cd4 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -3,6 +3,10 @@ //! This library contains the tidy lints and exposes it //! to be used by tools. +use std::fmt::Display; + +use termcolor::WriteColor; + /// A helper macro to `unwrap` a result except also print out details like: /// /// * The expression that failed @@ -26,18 +30,27 @@ macro_rules! t { } macro_rules! tidy_error { - ($bad:expr, $fmt:expr) => ({ - *$bad = true; - eprint!("tidy error: "); - eprintln!($fmt); - }); - ($bad:expr, $fmt:expr, $($arg:tt)*) => ({ - *$bad = true; - eprint!("tidy error: "); - eprintln!($fmt, $($arg)*); + ($bad:expr, $($fmt:tt)*) => ({ + $crate::tidy_error($bad, format_args!($($fmt)*)).expect("failed to output error"); }); } +fn tidy_error(bad: &mut bool, args: impl Display) -> std::io::Result<()> { + use std::io::Write; + use termcolor::{Color, ColorChoice, ColorSpec, StandardStream}; + + *bad = true; + + let mut stderr = StandardStream::stdout(ColorChoice::Auto); + stderr.set_color(ColorSpec::new().set_fg(Some(Color::Red)))?; + + write!(&mut stderr, "tidy error")?; + stderr.set_color(&ColorSpec::new())?; + + writeln!(&mut stderr, ": {args}")?; + Ok(()) +} + pub mod alphabetical; pub mod bins; pub mod debug_artifacts; diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index f746bdeffd7..070e72437be 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,7 +10,7 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. const ROOT_ENTRY_LIMIT: usize = 939; -const ISSUES_ENTRY_LIMIT: usize = 2020; +const ISSUES_ENTRY_LIMIT: usize = 2050; fn check_entries(path: &Path, bad: &mut bool) { for dir in Walk::new(&path.join("test/ui")) { diff --git a/triagebot.toml b/triagebot.toml index 22f09396efc..0da9fcddad8 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -496,7 +496,6 @@ infra-ci = [ rustdoc = [ "@jsha", "@GuillaumeGomez", - "@CraftSpider", "@notriddle", ] docs = [ diff --git a/x.ps1 b/x.ps1 index 81b98919f43..f324a4676c8 100755 --- a/x.ps1 +++ b/x.ps1 @@ -14,6 +14,12 @@ function Get-Application($app) { return Get-Command $app -ErrorAction SilentlyContinue -CommandType Application } +function Invoke-Application($application, $arguments) { + $process = Start-Process -NoNewWindow -PassThru $application $arguments + $process.WaitForExit() + Exit $process.ExitCode +} + foreach ($python in "py", "python3", "python", "python2") { # NOTE: this only tests that the command exists in PATH, not that it's actually # executable. The latter is not possible in a portable way, see @@ -23,16 +29,14 @@ foreach ($python in "py", "python3", "python", "python2") { # Use python3, not python2 $xpy_args = @("-3") + $xpy_args } - $process = Start-Process -NoNewWindow -Wait -PassThru $python $xpy_args - Exit $process.ExitCode + Invoke-Application $python $xpy_args } } $found = (Get-Application "python*" | Where-Object {$_.name -match '^python[2-3]\.[0-9]+(\.exe)?$'}) if (($null -ne $found) -and ($found.Length -ge 1)) { $python = $found[0] - $process = Start-Process -NoNewWindow -Wait -PassThru $python $xpy_args - Exit $process.ExitCode + Invoke-Application $python $xpy_args } Write-Error "${PSCommandPath}: error: did not find python installed" |
