diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 853f43e15e307..26e589c092eda 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -294,7 +294,7 @@ jobs: - name: x86_64-gnu-integration env: CI_ONLY_WHEN_CHANNEL: nightly - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-debug os: ubuntu-20.04-8core-32gb env: {} @@ -319,7 +319,7 @@ jobs: - name: dist-x86_64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" - RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin" + RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app @@ -332,7 +332,7 @@ jobs: - name: dist-apple-various env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" - RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 SELECT_XCODE: /Applications/Xcode_13.4.1.app @@ -343,7 +343,7 @@ jobs: - name: x86_64-apple-1 env: SCRIPT: "./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 @@ -354,7 +354,7 @@ jobs: - name: x86_64-apple-2 env: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false" + RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 MACOSX_DEPLOYMENT_TARGET: 10.12 MACOSX_STD_DEPLOYMENT_TARGET: 10.12 @@ -364,8 +364,8 @@ jobs: os: macos-13 - name: dist-aarch64-apple env: - SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" - RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --host=aarch64-apple-darwin --target=aarch64-apple-darwin --enable-full-tools --enable-sanitizers --enable-profiler --disable-docs --set rust.jemalloc --set llvm.ninja=false" + SCRIPT: "./x.py dist bootstrap --include-default-paths --host=aarch64-apple-darwin --target=aarch64-apple-darwin" + RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false --set rust.lto=thin" RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 SELECT_XCODE: /Applications/Xcode_13.4.1.app USE_XCODE_CLANG: 1 @@ -375,8 +375,20 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - JEMALLOC_SYS_WITH_LG_PAGE: 14 - os: macos-13 + os: macos-14 + - name: aarch64-apple + env: + SCRIPT: "./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin" + RUST_CONFIGURE_ARGS: "--enable-sanitizers --enable-profiler --set rust.jemalloc" + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + SELECT_XCODE: /Applications/Xcode_13.4.1.app + USE_XCODE_CLANG: 1 + MACOSX_DEPLOYMENT_TARGET: 11.0 + MACOSX_STD_DEPLOYMENT_TARGET: 11.0 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + NO_OVERFLOW_CHECKS: 1 + os: macos-14 - name: x86_64-msvc env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/Cargo.lock b/Cargo.lock index 25f4959bf141f..fff30b0f27bcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,9 +37,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", @@ -556,7 +556,7 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "clippy" -version = "0.1.77" +version = "0.1.78" dependencies = [ "anstream", "clippy_config", @@ -584,7 +584,7 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.77" +version = "0.1.78" dependencies = [ "rustc-semver", "serde", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.77" +version = "0.1.78" dependencies = [ "arrayvec", "cargo_metadata 0.18.0", @@ -632,7 +632,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.77" +version = "0.1.78" dependencies = [ "arrayvec", "clippy_config", @@ -1003,7 +1003,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.77" +version = "0.1.78" dependencies = [ "itertools", "quote", @@ -2090,9 +2090,9 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] @@ -2169,9 +2169,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" dependencies = [ "rustc-std-workspace-core", ] @@ -4374,6 +4374,7 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", + "rustc_ty_utils", "tracing", ] @@ -5321,6 +5322,7 @@ version = "0.0.0" dependencies = [ "core", "getopts", + "libc", "panic_abort", "panic_unwind", "std", @@ -6406,18 +6408,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.28" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.28" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", diff --git a/RELEASES.md b/RELEASES.md index 3fb74b52292c1..20e317a4d236a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,96 @@ +Version 1.76.0 (2024-02-08) +========================== + + + +Language +-------- +- [Document Rust ABI compatibility between various types](https://github.com/rust-lang/rust/pull/115476/) +- [Also: guarantee that char and u32 are ABI-compatible](https://github.com/rust-lang/rust/pull/118032/) +- [Add lint `ambiguous_wide_pointer_comparisons` that supersedes `clippy::vtable_address_comparisons`](https://github.com/rust-lang/rust/pull/117758) + + + +Compiler +-------- +- [Lint pinned `#[must_use]` pointers (in particular, `Box` where `T` is `#[must_use]`) in `unused_must_use`.](https://github.com/rust-lang/rust/pull/118054/) +- [Soundness fix: fix computing the offset of an unsized field in a packed struct](https://github.com/rust-lang/rust/pull/118540/) +- [Soundness fix: fix dynamic size/align computation logic for packed types with dyn Trait tail](https://github.com/rust-lang/rust/pull/118538/) +- [Add `$message_type` field to distinguish json diagnostic outputs](https://github.com/rust-lang/rust/pull/115691/) +- [Enable Rust to use the EHCont security feature of Windows](https://github.com/rust-lang/rust/pull/118013/) +- [Add tier 3 {x86_64,i686}-win7-windows-msvc targets](https://github.com/rust-lang/rust/pull/118150/) +- [Add tier 3 aarch64-apple-watchos target](https://github.com/rust-lang/rust/pull/119074/) +- [Add tier 3 arm64e-apple-ios & arm64e-apple-darwin targets](https://github.com/rust-lang/rust/pull/115526/) + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + + + +Libraries +--------- +- [Add a column number to `dbg!()`](https://github.com/rust-lang/rust/pull/114962/) +- [Add `std::hash::{DefaultHasher, RandomState}` exports](https://github.com/rust-lang/rust/pull/115694/) +- [Fix rounding issue with exponents in fmt](https://github.com/rust-lang/rust/pull/116301/) +- [Add T: ?Sized to `RwLockReadGuard` and `RwLockWriteGuard`'s Debug impls.](https://github.com/rust-lang/rust/pull/117138/) +- [Windows: Allow `File::create` to work on hidden files](https://github.com/rust-lang/rust/pull/116438/) + + + +Stabilized APIs +--------------- + +- [`Arc::unwrap_or_clone`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.unwrap_or_clone) +- [`Rc::unwrap_or_clone`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.unwrap_or_clone) +- [`Result::inspect`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.inspect) +- [`Result::inspect_err`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.inspect_err) +- [`Option::inspect`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.inspect) +- [`type_name_of_val`](https://doc.rust-lang.org/stable/std/any/fn.type_name_of_val.html) +- [`std::hash::{DefaultHasher, RandomState}`](https://doc.rust-lang.org/stable/std/hash/index.html#structs) + These were previously available only through `std::collections::hash_map`. +- [`ptr::{from_ref, from_mut}`](https://doc.rust-lang.org/stable/std/ptr/fn.from_ref.html) +- [`ptr::addr_eq`](https://doc.rust-lang.org/stable/std/ptr/fn.addr_eq.html) + + + +Cargo +----- + +See [Cargo release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-176-2024-02-08). + + + +Rustdoc +------- + +- [Don't merge cfg and doc(cfg) attributes for re-exports](https://github.com/rust-lang/rust/pull/113091/) +- [rustdoc: allow resizing the sidebar / hiding the top bar](https://github.com/rust-lang/rust/pull/115660/) +- [rustdoc-search: add support for traits and associated types](https://github.com/rust-lang/rust/pull/116085/) +- [rustdoc: Add highlighting for comments in items declaration](https://github.com/rust-lang/rust/pull/117869/) + + + +Compatibility Notes +------------------- +- [Add allow-by-default lint for unit bindings](https://github.com/rust-lang/rust/pull/112380/) + This is expected to be upgraded to a warning by default in a future Rust + release. Some macros emit bindings with type `()` with user-provided spans, + which means that this lint will warn for user code. +- [Remove x86_64-sun-solaris target.](https://github.com/rust-lang/rust/pull/118091/) +- [Remove asmjs-unknown-emscripten target](https://github.com/rust-lang/rust/pull/117338/) +- [Report errors in jobserver inherited through environment variables](https://github.com/rust-lang/rust/pull/113730/) + This [may warn](https://github.com/rust-lang/rust/issues/120515) on benign problems too. +- [Update the minimum external LLVM to 16.](https://github.com/rust-lang/rust/pull/117947/) +- [Improve `print_tts`](https://github.com/rust-lang/rust/pull/114571/) + This change can break some naive manual parsing of token trees in proc macro + code which expect a particular structure after `.to_string()`, rather than just arbitrary Rust code. +- [Make `IMPLIED_BOUNDS_ENTAILMENT` into a hard error from a lint](https://github.com/rust-lang/rust/pull/117984/) +- [Vec's allocation behavior was changed when collecting some iterators](https://github.com/rust-lang/rust/pull/110353) + Allocation behavior is currently not specified, nevertheless changes can be surprising. + See [`impl FromIterator for Vec`](https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#impl-FromIterator%3CT%3E-for-Vec%3CT%3E) + for more details. +- [Properly reject `default` on free const items](https://github.com/rust-lang/rust/pull/117818/) + Version 1.75.0 (2023-12-28) ========================== diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 90ddeec4bc7a4..5cb79d9eea53b 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -22,8 +22,6 @@ #![cfg_attr(test, feature(test))] #![feature(strict_provenance)] #![deny(unsafe_op_in_unsafe_fn)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine. diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4eb8169d0c37c..296a570de6b33 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -291,12 +291,16 @@ pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID}; #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] pub struct TraitBoundModifiers { pub constness: BoundConstness, + pub asyncness: BoundAsyncness, pub polarity: BoundPolarity, } impl TraitBoundModifiers { - pub const NONE: Self = - Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive }; + pub const NONE: Self = Self { + constness: BoundConstness::Never, + asyncness: BoundAsyncness::Normal, + polarity: BoundPolarity::Positive, + }; } /// The AST represents all type param bounds as types. @@ -2562,6 +2566,25 @@ impl BoundConstness { } } +/// The asyncness of a trait bound. +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] +#[derive(HashStable_Generic)] +pub enum BoundAsyncness { + /// `Type: Trait` + Normal, + /// `Type: async Trait` + Async(Span), +} + +impl BoundAsyncness { + pub fn as_str(self) -> &'static str { + match self { + Self::Normal => "", + Self::Async(_) => "async", + } + } +} + #[derive(Clone, Encodable, Decodable, Debug)] pub enum FnRetTy { /// Returns type is not specified. @@ -3300,7 +3323,7 @@ mod size_asserts { static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItemKind, 24); static_assert_size!(GenericArg, 24); - static_assert_size!(GenericBound, 72); + static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 40); static_assert_size!(Impl, 136); static_assert_size!(Item, 136); diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 76d838308b461..356e9fef439ed 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -18,8 +18,6 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(stmt_expr_attributes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 8615016cda599..37e45379ba9a2 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -11,6 +11,12 @@ ast_lowering_argument = argument ast_lowering_assoc_ty_parentheses = parenthesized generic arguments cannot be used in associated type constraints +ast_lowering_async_bound_not_on_trait = + `async` bound modifier only allowed on trait, not `{$descr}` + +ast_lowering_async_bound_only_for_fn_traits = + `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits + ast_lowering_async_coroutines_not_supported = `async` coroutines are not yet supported @@ -117,9 +123,6 @@ ast_lowering_never_pattern_with_guard = a guard on a never pattern will never be run .suggestion = remove this guard -ast_lowering_not_supported_for_lifetime_binder_async_closure = - `for<...>` binders on `async` closures are not currently supported - ast_lowering_previously_used_here = previously used here ast_lowering_register1 = register `{$reg1_name}` diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 3742cf9d881d8..fd717e82d26df 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -205,7 +205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); hir::InlineAsmOperand::SymStatic { path, def_id } diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index d310f72f7a3f8..865a56b2c1f15 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -85,7 +85,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = l .ty .as_ref() - .map(|t| self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 6ccf39b0cb167..d1ba93f067553 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -218,7 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &delegation.qself, &delegation.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let block = delegation.body.as_deref(); diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 51bb8a96fad26..6225358569573 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -1,4 +1,6 @@ -use rustc_errors::{codes::*, DiagnosticArgFromDisplay}; +use rustc_errors::{ + codes::*, AddToDiagnostic, Diagnostic, DiagnosticArgFromDisplay, SubdiagnosticMessageOp, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -38,14 +40,8 @@ pub struct InvalidAbi { pub struct InvalidAbiReason(pub &'static str); -impl rustc_errors::AddToDiagnostic for InvalidAbiReason { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { +impl AddToDiagnostic for InvalidAbiReason { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { #[allow(rustc::untranslatable_diagnostic)] diag.note(self.0); } @@ -326,13 +322,6 @@ pub struct MisplacedRelaxTraitBound { pub span: Span, } -#[derive(Diagnostic, Clone, Copy)] -#[diag(ast_lowering_not_supported_for_lifetime_binder_async_closure)] -pub struct NotSupportedForLifetimeBinderAsyncClosure { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(ast_lowering_match_arm_with_no_body)] pub struct MatchArmWithNoBody { @@ -395,3 +384,18 @@ pub(crate) struct GenericParamDefaultInBinder { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(ast_lowering_async_bound_not_on_trait)] +pub(crate) struct AsyncBoundNotOnTrait { + #[primary_span] + pub span: Span, + pub descr: &'static str, +} + +#[derive(Diagnostic)] +#[diag(ast_lowering_async_bound_only_for_fn_traits)] +pub(crate) struct AsyncBoundOnlyForFnTraits { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 0ad4a59c17eb1..942aae3d53600 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,9 +1,10 @@ +use std::assert_matches::assert_matches; + use super::errors::{ AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters, FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody, - NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure, - UnderscoreExprLhsAssign, + NeverPatternWithBody, NeverPatternWithGuard, UnderscoreExprLhsAssign, }; use super::ResolverAstLoweringExt; use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; @@ -98,7 +99,9 @@ impl<'hir> LoweringContext<'_, 'hir> { seg, ParamMode::Optional, ParenthesizedGenericArgs::Err, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + // Method calls can't have bound modifiers None, )); let receiver = self.lower_expr(receiver); @@ -138,13 +141,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ohs) => { @@ -264,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); hir::ExprKind::Path(qpath) @@ -292,7 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf( self.lower_ty( container, - &ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), + ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), ), self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))), ), @@ -311,7 +314,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, )), self.arena @@ -1026,30 +1029,27 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir> { - if let &ClosureBinder::For { span, .. } = binder { - self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); - } - let (binder_clause, generic_params) = self.lower_closure_binder(binder); + assert_matches!( + coroutine_kind, + CoroutineKind::Async { .. }, + "only async closures are supported currently" + ); + let body = self.with_new_scopes(fn_decl_span, |this| { + let inner_decl = + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; + // Transform `async |x: u8| -> X { ... }` into // `|x: u8| || -> X { ... }`. let body_id = this.lower_body(|this| { - let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { - let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); - Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx))) - } else { - None - }; - let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( - decl, + &inner_decl, |this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)), body.span, coroutine_kind, hir::CoroutineSource::Closure, - async_ret_ty, ); let hir_id = this.lower_node_id(coroutine_kind.closure_id()); @@ -1060,15 +1060,12 @@ impl<'hir> LoweringContext<'_, 'hir> { body_id }); - let outer_decl = - FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; - let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. let fn_decl = - self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); + self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { def_id: self.local_def_id(closure_id), @@ -1079,7 +1076,10 @@ impl<'hir> LoweringContext<'_, 'hir> { body, fn_decl_span: self.lower_span(fn_decl_span), fn_arg_span: Some(self.lower_span(fn_arg_span)), - kind: hir::ClosureKind::Closure, + // Lower this as a `CoroutineClosure`. That will ensure that HIR typeck + // knows that a `FnDecl` output type like `-> &str` actually means + // "coroutine that returns &str", rather than directly returning a `&str`. + kind: hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async), constness: hir::Constness::NotConst, }); hir::ExprKind::Closure(c) @@ -1241,7 +1241,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); // Destructure like a tuple struct. @@ -1261,7 +1261,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); // Destructure like a unit struct. @@ -1286,7 +1286,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let fields_omitted = match &se.rest { diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 993ddf00eb5b9..11aa6b250b129 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -15,7 +15,7 @@ struct NodeCollector<'a, 'hir> { bodies: &'a SortedMap>, /// Outputs - nodes: IndexVec>>, + nodes: IndexVec>, parenting: LocalDefIdMap, /// The parent of this node @@ -29,16 +29,19 @@ pub(super) fn index_hir<'hir>( tcx: TyCtxt<'hir>, item: hir::OwnerNode<'hir>, bodies: &SortedMap>, -) -> (IndexVec>>, LocalDefIdMap) { - let mut nodes = IndexVec::new(); + num_nodes: usize, +) -> (IndexVec>, LocalDefIdMap) { + let zero_id = ItemLocalId::new(0); + let err_node = ParentedNode { parent: zero_id, node: Node::Err(item.span()) }; + let mut nodes = IndexVec::from_elem_n(err_node, num_nodes); // This node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. Make it invalid (= ItemLocalId::MAX) to force an ICE whenever it is // used. - nodes.push(Some(ParentedNode { parent: ItemLocalId::INVALID, node: item.into() })); + nodes[zero_id] = ParentedNode { parent: ItemLocalId::INVALID, node: item.into() }; let mut collector = NodeCollector { tcx, owner: item.def_id(), - parent_node: ItemLocalId::new(0), + parent_node: zero_id, nodes, bodies, parenting: Default::default(), @@ -54,6 +57,14 @@ pub(super) fn index_hir<'hir>( OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item), }; + for (local_id, node) in collector.nodes.iter_enumerated() { + if let Node::Err(span) = node.node { + let hir_id = HirId { owner: item.def_id(), local_id }; + let msg = format!("ID {hir_id} not encountered when visiting item HIR"); + tcx.dcx().span_delayed_bug(*span, msg); + } + } + (collector.nodes, collector.parenting) } @@ -88,7 +99,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node }); + self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node }; } fn with_parent(&mut self, parent_node_id: HirId, f: F) { @@ -254,6 +265,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) { + // FIXME: walk path segment with `path_segment.hir_id` parent. self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment)); intravisit::walk_path_segment(self, path_segment); } @@ -348,4 +360,23 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_nested_foreign_item(id); } + + fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) { + match predicate { + WherePredicate::BoundPredicate(pred) => { + self.insert(pred.span, pred.hir_id, Node::WhereBoundPredicate(pred)); + self.with_parent(pred.hir_id, |this| { + intravisit::walk_where_predicate(this, predicate) + }) + } + _ => intravisit::walk_where_predicate(self, predicate), + } + } + + fn visit_array_length(&mut self, len: &'hir ArrayLen) { + match len { + ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)), + ArrayLen::Body(..) => intravisit::walk_array_len(self, len), + } + } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dd3f7289a60b2..fb52f9cf58f26 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -25,7 +25,7 @@ pub(super) struct ItemLowerer<'a, 'hir> { pub(super) tcx: TyCtxt<'hir>, pub(super) resolver: &'a mut ResolverAstLowering, pub(super) ast_index: &'a IndexSlice>, - pub(super) owners: &'a mut IndexVec>>, + pub(super) owners: &'a mut IndexVec>, } /// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span @@ -64,10 +64,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } } - pub(super) fn lower_node( - &mut self, - def_id: LocalDefId, - ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { + pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> { let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); if let hir::MaybeOwner::Phantom = owner { let node = self.ast_index[def_id]; @@ -192,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy) }, @@ -221,7 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = - this.lower_generics(generics, header.constness, id, &itctx, |this| { + this.lower_generics(generics, header.constness, id, itctx, |this| { this.lower_fn_decl( decl, id, @@ -266,7 +263,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let guar = this.dcx().span_delayed_bug( @@ -277,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } Some(ty) => this.lower_ty( ty, - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, ), }, ); @@ -288,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.arena.alloc_from_iter( enum_definition.variants.iter().map(|x| this.lower_variant(x)), @@ -302,7 +299,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); hir::ItemKind::Struct(struct_def, generics) @@ -312,7 +309,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); hir::ItemKind::Union(vdata, generics) @@ -342,23 +339,28 @@ impl<'hir> LoweringContext<'_, 'hir> { // parent lifetime. let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, *constness, id, &itctx, |this| { - let constness = match *constness { - Const::Yes(span) => BoundConstness::Maybe(span), - Const::No => BoundConstness::Never, + self.lower_generics(ast_generics, *constness, id, itctx, |this| { + let modifiers = TraitBoundModifiers { + constness: match *constness { + Const::Yes(span) => BoundConstness::Maybe(span), + Const::No => BoundConstness::Never, + }, + asyncness: BoundAsyncness::Normal, + // we don't use this in bound lowering + polarity: BoundPolarity::Positive, }; let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref( - constness, + modifiers, trait_ref, - &ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); let lowered_ty = this.lower_ty( ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), + ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), ); (trait_ref, lowered_ty) @@ -398,11 +400,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, constness, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let bounds = this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -418,11 +420,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, ); @@ -462,7 +464,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body: Option<&Expr>, impl_trait_position: ImplTraitPosition, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(impl_trait_position)); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position)); (ty, self.lower_const_body(span, body)) } @@ -496,8 +498,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - let res = - self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); + let res = self.lower_import_res(id, path.span); let path = self.lower_use_path(res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Single) } @@ -533,7 +534,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // for that we return the `{}` import (called the // `ListStem`). - let prefix = Path { segments, span: prefix.span.to(path.span), tokens: None }; + let span = prefix.span.to(path.span); + let prefix = Path { segments, span, tokens: None }; // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { @@ -567,9 +569,21 @@ impl<'hir> LoweringContext<'_, 'hir> { }); } - let res = - self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); - let path = self.lower_use_path(res, &prefix, ParamMode::Explicit); + // Condition should match `build_reduced_graph_for_use_tree`. + let path = if trees.is_empty() + && !(prefix.segments.is_empty() + || prefix.segments.len() == 1 + && prefix.segments[0].ident.name == kw::PathRoot) + { + // For empty lists we need to lower the prefix so it is checked for things + // like stability later. + let res = self.lower_import_res(id, span); + self.lower_use_path(res, &prefix, ParamMode::Explicit) + } else { + // For non-empty lists we can just drop all the data, the prefix is already + // present in HIR as a part of nested imports. + self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span }) + }; hir::ItemKind::Use(path, hir::UseKind::ListStem) } } @@ -624,7 +638,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, Const::No, i.id, &itctx, |this| { + self.lower_generics(generics, Const::No, i.id, itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl( @@ -641,8 +655,8 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(t, m, _) => { - let ty = self - .lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); + let ty = + self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); hir::ForeignItemKind::Static(ty, *m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -713,11 +727,11 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), + ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) + self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -746,12 +760,10 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { - let ty = this.lower_ty( - ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), - ); + let ty = this + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x))); hir::TraitItemKind::Const(ty, body) @@ -794,18 +806,18 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { this.lower_ty( x, - &ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy), + ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy), ) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, ) @@ -873,10 +885,10 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { - let ty = this - .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); + let ty = + this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = this.lower_const_body(i.span, expr.as_deref()); hir::ImplItemKind::Const(ty, body) @@ -907,7 +919,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let guar = this.dcx().span_delayed_bug( @@ -920,7 +932,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(ty) => { let ty = this.lower_ty( ty, - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, ); hir::ImplItemKind::Type(ty) } @@ -1089,7 +1101,6 @@ impl<'hir> LoweringContext<'_, 'hir> { body.span, coroutine_kind, hir::CoroutineSource::Fn, - None, ); // FIXME(async_fn_track_caller): Can this be moved above? @@ -1111,7 +1122,6 @@ impl<'hir> LoweringContext<'_, 'hir> { body_span: Span, coroutine_kind: CoroutineKind, coroutine_source: hir::CoroutineSource, - return_type_hint: Option>, ) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) { let mut parameters: Vec> = Vec::new(); let mut statements: Vec> = Vec::new(); @@ -1281,12 +1291,13 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let closure_id = coroutine_kind.closure_id(); let coroutine_expr = self.make_desugared_coroutine_expr( - // FIXME(async_closures): This should only move locals, - // and not upvars. Capturing closure upvars by ref doesn't - // work right now anyways, so whatever. - CaptureBy::Value { move_kw: rustc_span::DUMMY_SP }, + // The default capture mode here is by-ref. Later on during upvar analysis, + // we will force the captured arguments to by-move, but for async closures, + // we want to make sure that we avoid unnecessarily moving captures, or else + // all async closures would default to `FnOnce` as their calling mode. + CaptureBy::Ref, closure_id, - return_type_hint, + None, body_span, desugaring_kind, coroutine_source, @@ -1315,7 +1326,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // synthesize a host effect param for them. We reject `const` on them during AST validation. let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No }; let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, constness, id, &itctx, |this| { + let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| { this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) @@ -1393,7 +1404,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &Generics, constness: Const, parent_node_id: NodeId, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) { debug_assert!(self.impl_trait_defs.is_empty()); @@ -1599,7 +1610,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds: &[GenericBound], colon_span: Option, parent_span: Span, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, origin: PredicateOrigin, ) -> Option> { // Do not create a clause if we do not have anything inside it. @@ -1673,10 +1684,10 @@ impl<'hir> LoweringContext<'_, 'hir> { bound_generic_params: self .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), bounded_ty: self - .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), bounds: self.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), span: self.lower_span(*span), origin: PredicateOrigin::WhereClause, @@ -1687,7 +1698,7 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, }) @@ -1695,9 +1706,9 @@ impl<'hir> LoweringContext<'_, 'hir> { WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty: self - .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), rhs_ty: self - .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), span: self.lower_span(*span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3621844efc8d2..4ef9c7607be5e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -33,10 +33,9 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -63,7 +62,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{DesugaringKind, Span, DUMMY_SP}; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use thin_vec::ThinVec; @@ -99,7 +98,7 @@ struct LoweringContext<'a, 'hir> { /// Attributes inside the owner being lowered. attrs: SortedMap, /// Collect items that were created by lowering the current owner. - children: Vec<(LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>)>, + children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>, coroutine_kind: Option, @@ -131,6 +130,7 @@ struct LoweringContext<'a, 'hir> { allow_gen_future: Lrc<[Symbol]>, allow_async_iterator: Lrc<[Symbol]>, allow_for_await: Lrc<[Symbol]>, + allow_async_fn_traits: Lrc<[Symbol]>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic @@ -176,6 +176,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { [sym::gen_future].into() }, allow_for_await: [sym::async_iterator].into(), + allow_async_fn_traits: [sym::async_fn_traits].into(), // FIXME(gen_blocks): how does `closure_track_caller`/`async_fn_track_caller` // interact with `gen`/`async gen` blocks allow_async_iterator: [sym::gen_future, sym::async_iterator].into(), @@ -296,7 +297,6 @@ enum ImplTraitPosition { Path, Variable, Trait, - AsyncBlock, Bound, Generic, ExternFnParam, @@ -323,7 +323,6 @@ impl std::fmt::Display for ImplTraitPosition { ImplTraitPosition::Path => "paths", ImplTraitPosition::Variable => "the type of variable bindings", ImplTraitPosition::Trait => "traits", - ImplTraitPosition::AsyncBlock => "async blocks", ImplTraitPosition::Bound => "bounds", ImplTraitPosition::Generic => "generics", ImplTraitPosition::ExternFnParam => "`extern fn` parameters", @@ -415,7 +414,7 @@ fn index_crate<'a>( /// This hash will then be part of the crate_hash which is stored in the metadata. fn compute_hir_hash( tcx: TyCtxt<'_>, - owners: &IndexSlice>>, + owners: &IndexSlice>, ) -> Fingerprint { let mut hir_body_nodes: Vec<_> = owners .iter_enumerated() @@ -674,7 +673,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { (None, None) }; - let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies); + let num_nodes = self.item_local_id_counter.as_usize(); + let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes); let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash }; @@ -749,8 +749,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } - fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator> { - self.resolver.get_import_res(id).present_items() + fn lower_import_res(&mut self, id: NodeId, span: Span) -> SmallVec<[Res; 3]> { + let res = self.resolver.get_import_res(id).present_items(); + let res: SmallVec<_> = res.map(|res| self.lower_res(res)).collect(); + if res.is_empty() { + self.dcx().span_delayed_bug(span, "no resolution for an import"); + return smallvec![Res::Err]; + } + res } fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> { @@ -999,7 +1005,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocConstraint, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint @@ -1078,32 +1084,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Equality { term } } AssocConstraintKind::Bound { bounds } => { - enum DesugarKind<'a> { + enum DesugarKind { ImplTrait, - Error(&'a ImplTraitPosition), + Error(ImplTraitPosition), Bound, } // Piggy-back on the `impl Trait` context to figure out the correct behavior. let desugar_kind = match itctx { - // We are in the return position: - // - // fn foo() -> impl Iterator - // - // so desugar to - // - // fn foo() -> impl Iterator - ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::TypeAliasesOpaqueTy { .. } => DesugarKind::ImplTrait, - - // We are in the argument position, but within a dyn type: + // in an argument, RPIT, or TAIT, if we are within a dyn type: // // fn foo(x: dyn Iterator) // - // so desugar to + // then desugar to: // // fn foo(x: dyn Iterator) - ImplTraitContext::Universal if self.is_in_dyn_type => DesugarKind::ImplTrait, + // + // This is because dyn traits must have all of their associated types specified. + ImplTraitContext::ReturnPositionOpaqueTy { .. } + | ImplTraitContext::TypeAliasesOpaqueTy { .. } + | ImplTraitContext::Universal + if self.is_in_dyn_type => + { + DesugarKind::ImplTrait + } ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => { DesugarKind::Error(position) @@ -1156,7 +1160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { DesugarKind::Error(position) => { let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding { span: constraint.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }); let err_ty = &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); @@ -1203,7 +1207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_arg( &mut self, arg: &ast::GenericArg, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)), @@ -1282,7 +1286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> { + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { self.arena.alloc(self.lower_ty_direct(t, itctx)) } @@ -1292,7 +1296,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option>, path: &Path, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in @@ -1311,7 +1315,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: t.span, }, itctx, - ast::BoundConstness::Never, + TraitBoundModifiers::NONE, ); let bounds = this.arena.alloc_from_iter([bound]); let lifetime_bound = this.elided_dyn_bound(t.span); @@ -1334,7 +1338,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => { @@ -1426,7 +1430,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx, // Still, don't pass along the constness here; we don't want to // synthesize any host effect args, it'd only cause problems. - ast::BoundConstness::Never, + TraitBoundModifiers { + constness: BoundConstness::Never, + ..*modifiers + }, )) } BoundPolarity::Maybe(_) => None, @@ -1450,13 +1457,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::ReturnPositionOpaqueTy { origin, fn_kind } => self .lower_opaque_impl_trait( span, - *origin, + origin, *def_node_id, bounds, - Some(*fn_kind), + Some(fn_kind), itctx, ), - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self .lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias { in_assoc_ty }, @@ -1503,9 +1510,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .create_feature_err( MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }, - *feature, + feature, ) .emit(); hir::TyKind::Err(guar) @@ -1513,7 +1520,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(position) => { let guar = self.dcx().emit_err(MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }); hir::TyKind::Err(guar) } @@ -1571,7 +1578,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_node_id: NodeId, bounds: &GenericBounds, fn_kind: Option, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1838,7 +1845,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam) } }; - self.lower_ty_direct(¶m.ty, &itctx) + self.lower_ty_direct(¶m.ty, itctx) })); let output = match coro { @@ -1866,7 +1873,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::PointerReturn) } }; - hir::FnRetTy::Return(self.lower_ty(ty, &itctx)) + hir::FnRetTy::Return(self.lower_ty(ty, itctx)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), }, @@ -1967,7 +1974,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output: &FnRetTy, coro: CoroutineKind, opaque_ty_span: Span, - nested_impl_trait_context: ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { @@ -1975,7 +1982,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, &nested_impl_trait_context) + self.lower_ty(ty, itctx) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2015,11 +2022,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait( - self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()), + self.lower_poly_trait_ref(p, itctx, *modifiers), self.lower_trait_bound_modifiers(*modifiers), ), GenericBound::Outlives(lifetime) => { @@ -2154,7 +2161,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .map(|def| { self.lower_ty( def, - &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), + ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), ) }); @@ -2164,7 +2171,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericParamKind::Const { ty, kw_span: _, default } => { let ty = self - .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); // Not only do we deny const param defaults in binders but we also map them to `None` // since later compiler stages cannot handle them (and shouldn't need to be able to). @@ -2192,9 +2199,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_ref( &mut self, - constness: ast::BoundConstness, + modifiers: ast::TraitBoundModifiers, p: &TraitRef, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TraitRef<'hir> { let path = match self.lower_qpath( p.ref_id, @@ -2202,7 +2209,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &p.path, ParamMode::Explicit, itctx, - Some(constness), + Some(modifiers), ) { hir::QPath::Resolved(None, path) => path, qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"), @@ -2214,16 +2221,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: &ImplTraitContext, - constness: ast::BoundConstness, + itctx: ImplTraitContext, + modifiers: ast::TraitBoundModifiers, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); - let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx); + let trait_ref = self.lower_trait_ref(modifiers, &p.trait_ref, itctx); hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> { + fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } @@ -2231,7 +2238,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds( &mut self, bounds: &[GenericBound], - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBounds<'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } @@ -2239,7 +2246,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], - itctx: &'s ImplTraitContext, + itctx: ImplTraitContext, ) -> impl Iterator> + Captures<'s> + Captures<'a> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } @@ -2275,7 +2282,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds, /* colon_span */ None, span, - &ImplTraitContext::Universal, + ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 0af141ff99a27..c097feb6b3476 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -38,7 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); @@ -55,7 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); break hir::PatKind::Path(qpath); @@ -66,7 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index c679ee56fcd8b..48941a232c266 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -1,17 +1,21 @@ use crate::ImplTraitPosition; -use super::errors::{GenericTypeWithParentheses, UseAngleBrackets}; +use super::errors::{ + AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, GenericTypeWithParentheses, UseAngleBrackets, +}; use super::ResolverAstLoweringExt; use super::{GenericArgsCtor, LifetimeRes, ParenthesizedGenericArgs}; use super::{ImplTraitContext, LoweringContext, ParamMode}; use rustc_ast::{self as ast, *}; +use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; +use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; use rustc_middle::span_bug; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; @@ -23,9 +27,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option>, p: &Path, param_mode: ParamMode, - itctx: &ImplTraitContext, - // constness of the impl/bound if this is a trait path - constness: Option, + itctx: ImplTraitContext, + // modifiers of the impl/bound if this is a trait path + modifiers: Option, ) -> hir::QPath<'hir> { let qself_position = qself.as_ref().map(|q| q.position); let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); @@ -35,10 +39,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let base_res = partial_res.base_res(); let unresolved_segments = partial_res.unresolved_segments(); + let mut res = self.lower_res(base_res); + + // When we have an `async` kw on a bound, map the trait it resolves to. + let mut bound_modifier_allowed_features = None; + if let Some(TraitBoundModifiers { asyncness: BoundAsyncness::Async(_), .. }) = modifiers { + match res { + Res::Def(DefKind::Trait, def_id) => { + if let Some((async_def_id, features)) = self.map_trait_to_async_trait(def_id) { + res = Res::Def(DefKind::Trait, async_def_id); + bound_modifier_allowed_features = Some(features); + } else { + self.dcx().emit_err(AsyncBoundOnlyForFnTraits { span: p.span }); + } + } + Res::Err => { + // No additional error. + } + _ => { + // This error isn't actually emitted AFAICT, but it's best to keep + // it around in case the resolver doesn't always check the defkind + // of an item or something. + self.dcx().emit_err(AsyncBoundNotOnTrait { span: p.span, descr: res.descr() }); + } + } + } + let path_span_lo = p.span.shrink_to_lo(); let proj_start = p.segments.len() - unresolved_segments; let path = self.arena.alloc(hir::Path { - res: self.lower_res(base_res), + res, segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map( |(i, segment)| { let param_mode = match (qself_position, param_mode) { @@ -77,7 +107,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parenthesized_generic_args, itctx, // if this is the last segment, add constness to the trait path - if i == proj_start - 1 { constness } else { None }, + if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None }, + bound_modifier_allowed_features.clone(), ) }, )), @@ -88,6 +119,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ), }); + if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features { + path.span = self.mark_span_with_reason( + DesugaringKind::BoundModifier, + path.span, + Some(bound_modifier_allowed_features), + ); + } + // Simple case, either no projections, or only fully-qualified. // E.g., `std::mem::size_of` or `::Item`. if unresolved_segments == 0 { @@ -125,6 +164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ParenthesizedGenericArgs::Err, itctx, None, + None, )); let qpath = hir::QPath::TypeRelative(ty, hir_segment); @@ -156,6 +196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &Path, param_mode: ParamMode, ) -> &'hir hir::UsePath<'hir> { + assert!((1..=3).contains(&res.len())); self.arena.alloc(hir::UsePath { res, segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { @@ -164,7 +205,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, None, ) })), @@ -178,8 +220,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, constness: Option, + // Additional features ungated with a bound modifier like `async`. + // This is passed down to the implicit associated type binding in + // parenthesized bounds. + bound_modifier_allowed_features: Option>, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment); let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() { @@ -188,9 +234,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } GenericArgs::Parenthesized(data) => match parenthesized_generic_args { - ParenthesizedGenericArgs::ParenSugar => { - self.lower_parenthesized_parameter_data(data, itctx) - } + ParenthesizedGenericArgs::ParenSugar => self + .lower_parenthesized_parameter_data( + data, + itctx, + bound_modifier_allowed_features, + ), ParenthesizedGenericArgs::Err => { // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait` let sub = if !data.inputs.is_empty() { @@ -325,7 +374,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) @@ -356,7 +405,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_parenthesized_parameter_data( &mut self, data: &ParenthesizedArgs, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, + bound_modifier_allowed_features: Option>, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this // means that we permit things like `&Ref`, where `Ref` has @@ -365,7 +415,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { // Only allow `impl Trait` in return position. i.e.: @@ -379,7 +429,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.lower_ty( ty, - &ImplTraitContext::FeatureGated( + ImplTraitContext::FeatureGated( ImplTraitPosition::FnTraitReturn, sym::impl_trait_in_fn_trait_return, ), @@ -387,12 +437,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } FnRetTy::Ty(ty) => { - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; - let binding = self.assoc_ty_binding(sym::Output, output_ty.span, output_ty); + + // If we have a bound like `async Fn() -> T`, make sure that we mark the + // `Output = T` associated type bound with the right feature gates. + let mut output_span = output_ty.span; + if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features { + output_span = self.mark_span_with_reason( + DesugaringKind::BoundModifier, + output_span, + Some(bound_modifier_allowed_features), + ); + } + let binding = self.assoc_ty_binding(sym::Output, output_span, output_ty); + ( GenericArgsCtor { args, @@ -429,4 +491,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { kind, } } + + /// When a bound is annotated with `async`, it signals to lowering that the trait + /// that the bound refers to should be mapped to the "async" flavor of the trait. + /// + /// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one + /// that is generic over `async`ness, if that's ever possible, or modify the + /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`. + fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<(DefId, Lrc<[Symbol]>)> { + let lang_items = self.tcx.lang_items(); + if Some(def_id) == lang_items.fn_trait() { + Some((lang_items.async_fn_trait()?, self.allow_async_fn_traits.clone())) + } else if Some(def_id) == lang_items.fn_mut_trait() { + Some((lang_items.async_fn_mut_trait()?, self.allow_async_fn_traits.clone())) + } else if Some(def_id) == lang_items.fn_once_trait() { + Some((lang_items.async_fn_once_trait()?, self.allow_async_fn_traits.clone())) + } else { + None + } + } } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 5f54a0ddf8c38..9662c73ca8532 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by ast_passes. use rustc_ast::ParamKindOrd; -use rustc_errors::{codes::*, AddToDiagnostic, Applicability}; +use rustc_errors::{codes::*, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -372,13 +372,7 @@ pub struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl AddToDiagnostic for EmptyLabelManySpans { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_labels(self.0, ""); } } @@ -735,13 +729,7 @@ pub struct StableFeature { } impl AddToDiagnostic for StableFeature { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.arg("name", self.name); diag.arg("since", self.since); diag.help(fluent::ast_passes_stable_since); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 82236d2e30678..409aef9185d92 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -362,6 +362,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } + fn visit_generic_args(&mut self, args: &'a ast::GenericArgs) { + // This check needs to happen here because the never type can be returned from a function, + // but cannot be used in any other context. If this check was in `visit_fn_ret_ty`, it + // include both functions and generics like `impl Fn() -> !`. + if let ast::GenericArgs::Parenthesized(generic_args) = args + && let ast::FnRetTy::Ty(ref ty) = generic_args.output + && matches!(ty.kind, ast::TyKind::Never) + { + gate!(&self, never_type, ty.span, "the `!` type is experimental"); + } + visit::walk_generic_args(self, args); + } + fn visit_expr(&mut self, e: &'a ast::Expr) { match e.kind { ast::ExprKind::TryBlock(_) => { diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index fa6cdd55c3dcb..74d0fff2734fc 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -11,8 +11,6 @@ #![feature(if_let_guard)] #![feature(iter_is_partitioned)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] pub mod ast_validation; mod errors; diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 61617beb86b5a..b9e217a21e39f 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -1,8 +1,6 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![feature(box_patterns)] mod helpers; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index c2fd4558fd76e..731232bce65cb 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -8,6 +8,7 @@ mod item; use crate::pp::Breaks::{Consistent, Inconsistent}; use crate::pp::{self, Breaks}; use crate::pprust::state::expr::FixupContext; +use ast::TraitBoundModifiers; use rustc_ast::attr::AttrIdGenerator; use rustc_ast::ptr::P; use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind}; @@ -160,6 +161,10 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { use TokenTree::Delimited as Del; use TokenTree::Token as Tok; + fn is_punct(tt: &TokenTree) -> bool { + matches!(tt, TokenTree::Token(tok, _) if tok.is_punct()) + } + // Each match arm has one or more examples in comments. The default is to // insert space between adjacent tokens, except for the cases listed in // this match. @@ -167,24 +172,35 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { // No space after line doc comments. (Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false, - // `.` + ANYTHING: `x.y`, `tup.0` - // `$` + ANYTHING: `$e` - (Tok(Token { kind: Dot | Dollar, .. }, _), _) => false, - - // ANYTHING + `,`: `foo,` - // ANYTHING + `.`: `x.y`, `tup.0` - // ANYTHING + `!`: `foo! { ... }` - // - // FIXME: Incorrect cases: - // - Logical not: `x =! y`, `if! x { f(); }` - // - Never type: `Fn() ->!` - (_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false, - - // IDENT + `(`: `f(3)` - // - // FIXME: Incorrect cases: - // - Let: `let(a, b) = (1, 2)` - (Tok(Token { kind: Ident(..), .. }, _), Del(_, _, Parenthesis, _)) => false, + // `.` + NON-PUNCT: `x.y`, `tup.0` + (Tok(Token { kind: Dot, .. }, _), tt2) if !is_punct(tt2) => false, + + // `$` + IDENT: `$e` + (Tok(Token { kind: Dollar, .. }, _), Tok(Token { kind: Ident(..), .. }, _)) => false, + + // NON-PUNCT + `,`: `foo,` + // NON-PUNCT + `;`: `x = 3;`, `[T; 3]` + // NON-PUNCT + `.`: `x.y`, `tup.0` + (tt1, Tok(Token { kind: Comma | Semi | Dot, .. }, _)) if !is_punct(tt1) => false, + + // IDENT + `!`: `println!()`, but `if !x { ... }` needs a space after the `if` + (Tok(Token { kind: Ident(sym, is_raw), span }, _), Tok(Token { kind: Not, .. }, _)) + if !Ident::new(*sym, *span).is_reserved() || *is_raw => + { + false + } + + // IDENT|`fn`|`Self`|`pub` + `(`: `f(3)`, `fn(x: u8)`, `Self()`, `pub(crate)`, + // but `let (a, b) = (1, 2)` needs a space after the `let` + (Tok(Token { kind: Ident(sym, is_raw), span }, _), Del(_, _, Parenthesis, _)) + if !Ident::new(*sym, *span).is_reserved() + || *sym == kw::Fn + || *sym == kw::SelfUpper + || *sym == kw::Pub + || *is_raw => + { + false + } // `#` + `[`: `#[attr]` (Tok(Token { kind: Pound, .. }, _), Del(_, _, Bracket, _)) => false, @@ -1575,18 +1591,28 @@ impl<'a> State<'a> { } match bound { - GenericBound::Trait(tref, modifier) => { - match modifier.constness { + GenericBound::Trait( + tref, + TraitBoundModifiers { constness, asyncness, polarity }, + ) => { + match constness { ast::BoundConstness::Never => {} ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => { - self.word_space(modifier.constness.as_str()); + self.word_space(constness.as_str()); + } + } + + match asyncness { + ast::BoundAsyncness::Normal => {} + ast::BoundAsyncness::Async(_) => { + self.word_space(asyncness.as_str()); } } - match modifier.polarity { + match polarity { ast::BoundPolarity::Positive => {} ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => { - self.word(modifier.polarity.as_str()); + self.word(polarity.as_str()); } } diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 3c5bcecddeaa4..dd87a5c4dc384 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -8,8 +8,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 948af03953718..6a683d129ded1 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::path_utils::allow_two_phase_borrow; use crate::place_ext::PlaceExt; use crate::BorrowIndex; diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 8a275a8363010..429bcb74a8efc 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{codes::*, struct_span_code_err, DiagCtxt, DiagnosticBuilder}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; @@ -130,7 +133,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { noun_old: &str, old_opt_via: &str, previous_end_span: Option, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_code_err!( self.dcx(), new_loan_span, @@ -162,7 +165,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_opt_via: &str, previous_end_span: Option, second_borrow_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_code_err!( self.dcx(), new_loan_span, @@ -194,7 +197,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { kind_old: &str, msg_old: &str, old_load_end_span: Option, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_code_err!( self.dcx(), @@ -235,7 +238,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, borrow_span: Span, desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { struct_span_code_err!( self.dcx(), span, @@ -252,7 +255,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { span: Span, desc: &str, is_arg: bool, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc) } @@ -265,7 +268,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, move_from_desc: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { struct_span_code_err!( self.dcx(), move_from_span, @@ -283,7 +286,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { move_from_span: Span, ty: Ty<'_>, is_index: Option, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let type_name = match (&ty.kind(), is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", @@ -304,7 +307,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { &self, move_from_span: Span, container_ty: Ty<'_>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { struct_span_code_err!( self.dcx(), move_from_span, diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 041ac75ec016e..ff11e4db12133 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use rustc_data_structures::graph::scc::Sccs; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::ConstraintCategory; diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index becfa535a59cc..a58fe2b744701 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 1bd891bdd685c..bc5bd7879563a 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::WithSuccessors; use rustc_index::bit_set::BitSet; diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index d0cf339e7ba41..6fd80d005d9e3 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_middle::mir::visit::{ MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, }; diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index bb5335febbf5e..a540fcee871c7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use rustc_errors::DiagnosticBuilder; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2e83072b8d132..f87269960bc84 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,5 +1,8 @@ // ignore-tidy-filelength +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use either::Either; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; @@ -327,7 +330,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, mpi: MovePathIndex, move_span: Span, - err: &mut DiagnosticBuilder<'_>, + err: &mut DiagnosticBuilder<'tcx>, in_pattern: &mut bool, move_spans: UseSpans<'_>, ) { @@ -401,66 +404,60 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let typeck = self.infcx.tcx.typeck(self.mir_def_id()); let hir_id = hir.parent_id(expr.hir_id); - if let Some(parent) = self.infcx.tcx.opt_hir_node(hir_id) { - let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind - && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) - { - (def_id.as_local(), args, 1) - } else if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::Call(call, args) = parent_expr.kind - && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() - { - (def_id.as_local(), args, 0) - } else { - (None, &[][..], 0) + let parent = self.infcx.tcx.hir_node(hir_id); + let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind + && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) + { + (def_id.as_local(), args, 1) + } else if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call, args) = parent_expr.kind + && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() + { + (def_id.as_local(), args, 0) + } else { + (None, &[][..], 0) + }; + if let Some(def_id) = def_id + && let node = + self.infcx.tcx.hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id)) + && let Some(fn_sig) = node.fn_sig() + && let Some(ident) = node.ident() + && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) + && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) + { + let mut span: MultiSpan = arg.span.into(); + span.push_span_label( + arg.span, + "this parameter takes ownership of the value".to_string(), + ); + let descr = match node.fn_kind() { + Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", + Some(hir::intravisit::FnKind::Method(..)) => "method", + Some(hir::intravisit::FnKind::Closure) => "closure", }; - if let Some(def_id) = def_id - && let Some(node) = self - .infcx - .tcx - .opt_hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id)) - && let Some(fn_sig) = node.fn_sig() - && let Some(ident) = node.ident() - && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) - && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) - { - let mut span: MultiSpan = arg.span.into(); - span.push_span_label( - arg.span, - "this parameter takes ownership of the value".to_string(), - ); - let descr = match node.fn_kind() { - Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", - Some(hir::intravisit::FnKind::Method(..)) => "method", - Some(hir::intravisit::FnKind::Closure) => "closure", - }; - span.push_span_label(ident.span, format!("in this {descr}")); - err.span_note( - span, - format!( - "consider changing this parameter type in {descr} `{ident}` to \ + span.push_span_label(ident.span, format!("in this {descr}")); + err.span_note( + span, + format!( + "consider changing this parameter type in {descr} `{ident}` to \ borrow instead if owning the value isn't necessary", - ), - ); - } - let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(self.body, self.infcx.tcx).ty; - if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind - && let hir::ExprKind::Path(hir::QPath::LangItem( - LangItem::IntoIterIntoIter, - _, - )) = 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, expr, move_span); - } + ), + ); + } + let place = &self.move_data.move_paths[mpi].place; + let ty = place.ty(self.body, self.infcx.tcx).ty; + if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind + && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) = + 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, expr, move_span); } } if let Some(pat) = finder.pat { @@ -486,7 +483,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { desired_action: InitializationRequiringAction, span: Span, use_spans: UseSpans<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { // We need all statements in the body where the binding was assigned to later find all // the branching code paths where the binding *wasn't* assigned to. let inits = &self.move_data.init_path_map[mpi]; @@ -858,7 +855,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span }, - hir::ClosureKind::Closure => MoveUseInClosure { var_span }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + MoveUseInClosure { var_span } + } } }); @@ -880,7 +879,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, (place, _span): (Place<'tcx>, Span), borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.args_or_use(); @@ -905,7 +904,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { BorrowUsePlaceCoroutine { place: desc_place, var_span, is_single_var: true } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true } } } @@ -930,7 +929,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (place, span): (Place<'tcx>, Span), gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let issued_spans = self.retrieve_borrow_spans(issued_borrow); let issued_span = issued_spans.args_or_use(); @@ -1056,7 +1055,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { var_span, is_single_var: true, }, - hir::ClosureKind::Closure => BorrowUsePlaceClosure { + hir::ClosureKind::Closure + | hir::ClosureKind::CoroutineClosure(_) => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true, @@ -1140,7 +1140,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { var_span, is_single_var: false, }, - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } } } @@ -1158,7 +1158,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { FirstBorrowUsePlaceCoroutine { place: borrow_place_desc, var_span } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span } } } @@ -1175,7 +1175,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { SecondBorrowUsePlaceCoroutine { place: desc_place, var_span } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { SecondBorrowUsePlaceClosure { place: desc_place, var_span } } } @@ -1759,7 +1759,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn_decl: hir::FnDecl { inputs, .. }, .. }) = e.kind - && let Some(hir::Node::Expr(body)) = self.tcx.opt_hir_node(body.hir_id) + && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id) { self.suggest_arg = "this: &Self".to_string(); if inputs.len() > 0 { @@ -1825,11 +1825,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - if let Some(hir::Node::ImplItem(hir::ImplItem { + if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(_fn_sig, body_id), .. - })) = self.infcx.tcx.opt_hir_node(self.mir_hir_id()) - && let Some(hir::Node::Expr(expr)) = self.infcx.tcx.opt_hir_node(body_id.hir_id) + }) = self.infcx.tcx.hir_node(self.mir_hir_id()) + && let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id) { let mut finder = ExpressionFinder { capture_span: *capture_kind_span, @@ -2129,7 +2129,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span: Span, borrow_spans: UseSpans<'tcx>, explanation: BorrowExplanation<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { debug!( "report_local_value_does_not_live_long_enough(\ {:?}, {:?}, {:?}, {:?}, {:?}\ @@ -2304,7 +2304,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, drop_span: Span, borrow_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { debug!( "report_thread_local_value_does_not_live_long_enough(\ {:?}, {:?}\ @@ -2329,7 +2329,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans: UseSpans<'tcx>, proper_span: Span, explanation: BorrowExplanation<'tcx>, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } = explanation { @@ -2397,8 +2397,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let proper_span = proper_span.source_callsite(); if let Some(scope) = self.body.source_scopes.get(source_info.scope) && let ClearCrossCrate::Set(scope_data) = &scope.local_data - && let Some(node) = self.infcx.tcx.opt_hir_node(scope_data.lint_root) - && let Some(id) = node.body_id() + && let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id() && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind { for stmt in block.stmts { @@ -2440,7 +2439,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "consider consuming the `{ty}` when turning it into an \ `Iterator`", ), - "into_iter".to_string(), + "into_iter", Applicability::MaybeIncorrect, ); } @@ -2496,7 +2495,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return_span: Span, category: ConstraintCategory<'tcx>, opt_place_desc: Option<&String>, - ) -> Option> { + ) -> Option> { let return_kind = match category { ConstraintCategory::Return(_) => "return", ConstraintCategory::Yield => "yield", @@ -2591,7 +2590,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { constraint_span: Span, captured_var: &str, scope: &str, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let tcx = self.infcx.tcx; let args_span = use_span.args_or_use(); @@ -2699,7 +2698,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { upvar_span: Span, upvar_name: Symbol, escape_span: Span, - ) -> DiagnosticBuilder<'cx> { + ) -> DiagnosticBuilder<'tcx> { let tcx = self.infcx.tcx; let escapes_from = tcx.def_descr(self.mir_def_id().to_def_id()); @@ -2942,7 +2941,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, - hir::ClosureKind::Closure => BorrowUseInClosure { var_span }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + BorrowUseInClosure { var_span } + } } }); @@ -2958,7 +2959,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, - hir::ClosureKind::Closure => BorrowUseInClosure { var_span }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + BorrowUseInClosure { var_span } + } } }); diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 4f66468a865f8..483ecee850b70 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -1,5 +1,8 @@ //! Print diagnostics to explain why values are borrowed. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; @@ -87,7 +90,7 @@ impl<'tcx> BorrowExplanation<'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind && let [hir::PathSegment { ident, args: None, .. }] = p.segments && let hir::def::Res::Local(hir_id) = p.res - && let Some(hir::Node::Pat(pat)) = tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(pat) = tcx.hir_node(hir_id) { err.span_label(pat.span, format!("binding `{ident}` declared here")); } diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs index 2c4d953f011fc..ff4f2bb9614f1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::collections::BTreeSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index 2495613fea1d2..94b17e0a2f99c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::collections::VecDeque; use std::rc::Rc; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index b35d4e16eccb0..59f3aa706edea 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -614,7 +614,7 @@ impl UseSpans<'_> { PartialAssignment => AssignPartInCoroutine { path_span }, }); } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { err.subdiagnostic(match action { Borrow => BorrowInClosure { path_span }, MatchOn | Use => UseInClosure { path_span }, @@ -1253,7 +1253,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { hir::ClosureKind::Coroutine(_) => { CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial } } - hir::ClosureKind::Closure => { + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial } } }) diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index fb3525e8998c0..126a50c91b494 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; @@ -288,7 +291,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &mut self, place: Place<'tcx>, span: Span, - ) -> DiagnosticBuilder<'a> { + ) -> DiagnosticBuilder<'tcx> { let description = if place.projection.len() == 1 { format!("static item {}", self.describe_any_place(place.as_ref())) } else { @@ -310,7 +313,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { deref_target_place: Place<'tcx>, span: Span, use_spans: Option>, - ) -> DiagnosticBuilder<'a> { + ) -> DiagnosticBuilder<'tcx> { // Inspect the type of the content behind the // borrow to provide feedback about why this // was a move rather than a copy. diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 0a6b758efa564..9e7fd45ec19ad 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use hir::ExprKind; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; @@ -198,12 +201,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { 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) { + if let Some((buffered_err, 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; + err = buffered_err; count = c + 1; if count == 2 { err.replace_span_with(span, false); @@ -396,7 +399,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_hir_id = captured_place.get_root_variable(); - if let Some(Node::Pat(pat)) = self.infcx.tcx.opt_hir_node(upvar_hir_id) + if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id) && let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, upvar_ident, _) = pat.kind { @@ -688,15 +691,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { break; } f_in_trait_opt.and_then(|f_in_trait| { - match self.infcx.tcx.opt_hir_node(f_in_trait) { - Some(Node::TraitItem(hir::TraitItem { + match self.infcx.tcx.hir_node(f_in_trait) { + Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn( hir::FnSig { decl: hir::FnDecl { inputs, .. }, .. }, _, ), .. - })) => { + }) => { let hir::Ty { span, .. } = inputs[local.index() - 1]; Some(span) } @@ -759,10 +762,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // // `let &b = a;` -> `let &(mut b) = a;` if let Some(hir_id) = hir_id - && let Some(hir::Node::Local(hir::Local { + && let hir::Node::Local(hir::Local { pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. }, .. - })) = self.infcx.tcx.opt_hir_node(hir_id) + }) = self.infcx.tcx.hir_node(hir_id) && let Ok(name) = self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span) { @@ -924,7 +927,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.span_suggestion_verbose( expr.span.shrink_to_lo(), "use a mutable iterator instead", - "mut ".to_string(), + "mut ", Applicability::MachineApplicable, ); } @@ -1206,7 +1209,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(hir_id) = hir_id - && let Some(hir::Node::Local(local)) = self.infcx.tcx.opt_hir_node(hir_id) + && let hir::Node::Local(local) = self.infcx.tcx.hir_node(hir_id) { let tables = self.infcx.tcx.typeck(def_id.as_local().unwrap()); if let Some(clone_trait) = self.infcx.tcx.lang_items().clone_trait() @@ -1472,7 +1475,7 @@ fn suggest_ampmut<'tcx>( } fn is_closure_or_coroutine(ty: Ty<'_>) -> bool { - ty.is_closure() || ty.is_coroutine() + ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() } /// Given a field that needs to be mutable, returns a span where the " mut " could go. diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index ad66c677c78f5..93e28a5f3f3e2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -1,6 +1,9 @@ //! Contains utilities for generating suggestions for borrowck errors related to unsatisfied //! outlives constraints. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_middle::ty::RegionVid; @@ -251,6 +254,6 @@ impl OutlivesSuggestionBuilder { diag.sort_span = mir_span.shrink_to_hi(); // Buffer the diagnostic - mbcx.buffer_non_error_diag(diag); + mbcx.buffer_non_error(diag); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8c8ca1ead400b..e69d2ca966ba0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; @@ -216,7 +214,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(id) = placeholder.bound.kind.get_id() && let Some(placeholder_id) = id.as_local() && let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id) - && let Some(generics_impl) = hir.get_parent(gat_hir_id).generics() + && let Some(generics_impl) = + hir.get_parent(hir.parent_id(gat_hir_id)).generics() { Some((gat_hir_id, generics_impl)) } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 15e1066e983a9..e008d230656f9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -1,6 +1,10 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use std::fmt::{self, Display}; use std::iter; +use rustc_data_structures::fx::IndexEntry; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -14,7 +18,7 @@ use crate::{universal_regions::DefiningTy, MirBorrowckCtxt}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) struct RegionName { /// The name of the region (interned). pub(crate) name: Symbol, @@ -25,7 +29,7 @@ pub(crate) struct RegionName { /// Denotes the source of a region that is named by a `RegionName`. For example, a free region that /// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`. /// This helps to print the right kinds of diagnostics. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) enum RegionNameSource { /// A bound (not free) region that was instantiated at the def site (not an HRTB). NamedEarlyParamRegion(Span), @@ -42,7 +46,7 @@ pub(crate) enum RegionNameSource { /// The region corresponding to the return type of a closure. AnonRegionFromOutput(RegionNameHighlight, &'static str), /// The region from a type yielded by a coroutine. - AnonRegionFromYieldTy(Span, String), + AnonRegionFromYieldTy(Span, Symbol), /// An anonymous region from an async fn. AnonRegionFromAsyncFn(Span), /// An anonymous region from an impl self type or trait @@ -51,7 +55,7 @@ pub(crate) enum RegionNameSource { /// Describes what to highlight to explain to the user that we're giving an anonymous region a /// synthesized name, and how to highlight it. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) enum RegionNameHighlight { /// The anonymous region corresponds to a reference that was found by traversing the type in the HIR. MatchedHirTy(Span), @@ -59,11 +63,11 @@ pub(crate) enum RegionNameHighlight { MatchedAdtAndSegment(Span), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. - CannotMatchHirTy(Span, String), + CannotMatchHirTy(Span, Symbol), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, and *even if* we print out the full name of the type, the region name won't /// be included. This currently occurs for opaque types like `impl Future`. - Occluded(Span, String), + Occluded(Span, Symbol), } impl RegionName { @@ -247,25 +251,28 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { assert!(self.regioncx.universal_regions().is_universal_region(fr)); - if let Some(value) = self.region_names.try_borrow_mut().unwrap().get(&fr) { - return Some(value.clone()); - } + match self.region_names.borrow_mut().entry(fr) { + IndexEntry::Occupied(precomputed_name) => Some(*precomputed_name.get()), + IndexEntry::Vacant(slot) => { + let new_name = self + .give_name_from_error_region(fr) + .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) + .or_else(|| { + self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr) + }); + + if let Some(new_name) = new_name { + slot.insert(new_name); + } + debug!("give_region_a_name: gave name {:?}", new_name); - let value = self - .give_name_from_error_region(fr) - .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr)); - - if let Some(value) = &value { - self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); + new_name + } } - - debug!("give_region_a_name: gave name {:?}", value); - value } /// Checks for the case where `fr` maps to something that the @@ -324,9 +331,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::BoundRegionKind::BrEnv => { let def_ty = self.regioncx.universal_regions().defining_ty; - let DefiningTy::Closure(_, args) = def_ty else { - // Can't have BrEnv in functions, constants or coroutines. - bug!("BrEnv outside of closure."); + let closure_kind = match def_ty { + DefiningTy::Closure(_, args) => args.as_closure().kind(), + DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().kind(), + _ => { + // Can't have BrEnv in functions, constants or coroutines. + bug!("BrEnv outside of closure."); + } }; let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) = tcx.hir().expect_expr(self.mir_hir_id()).kind @@ -334,21 +345,18 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { bug!("Closure is not defined by a closure expr"); }; let region_name = self.synthesize_region_name(); - - let closure_kind_ty = args.as_closure().kind_ty(); - let note = match closure_kind_ty.to_opt_closure_kind() { - Some(ty::ClosureKind::Fn) => { + let note = match closure_kind { + ty::ClosureKind::Fn => { "closure implements `Fn`, so references to captured variables \ can't escape the closure" } - Some(ty::ClosureKind::FnMut) => { + ty::ClosureKind::FnMut => { "closure implements `FnMut`, so references to captured variables \ can't escape the closure" } - Some(ty::ClosureKind::FnOnce) => { + ty::ClosureKind::FnOnce => { bug!("BrEnv in a `FnOnce` closure"); } - None => bug!("Closure kind not inferred in borrow check"), }; Some(RegionName { @@ -456,9 +464,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ); if type_name.contains(&format!("'{counter}")) { // Only add a label if we can confirm that a region was labelled. - RegionNameHighlight::CannotMatchHirTy(span, type_name) + RegionNameHighlight::CannotMatchHirTy(span, Symbol::intern(&type_name)) } else { - RegionNameHighlight::Occluded(span, type_name) + RegionNameHighlight::Occluded(span, Symbol::intern(&type_name)) } } @@ -692,7 +700,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Async, hir::CoroutineSource::Closure, - )) => " of async closure", + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => { + " of async closure" + } hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Async, @@ -719,7 +730,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Gen, hir::CoroutineSource::Closure, - )) => " of gen closure", + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => { + " of gen closure" + } hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::Gen, @@ -743,7 +757,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::AsyncGen, hir::CoroutineSource::Closure, - )) => " of async gen closure", + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::AsyncGen) => { + " of async gen closure" + } hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( hir::CoroutineDesugaring::AsyncGen, @@ -878,7 +895,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionName { name: self.synthesize_region_name(), - source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), + source: RegionNameSource::AnonRegionFromYieldTy(yield_span, Symbol::intern(&type_name)), }) } @@ -970,7 +987,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionName { name: region_name, source: RegionNameSource::AnonRegionFromArgument( - RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()), + RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?), ), }) } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 28e07f2a81edd..0479cd8af35e2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use crate::region_infer::RegionInferenceContext; use rustc_index::IndexSlice; use rustc_middle::mir::{Body, Local}; diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index c54e7070478ca..68dc9a6764bfc 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::location::{LocationIndex, LocationTable}; use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ea48e78509b7c..4dba34c11f945 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -3,6 +3,7 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] +#![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(let_chains)] @@ -19,7 +20,7 @@ extern crate tracing; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; -use rustc_errors::{Diagnostic, DiagnosticBuilder}; +use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::{BitSet, ChunkedBitSet}; @@ -110,14 +111,16 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); - if input_body.borrow().should_skip() { - debug!("Skipping borrowck because of injected body"); + let input_body: &Body<'_> = &input_body.borrow(); + + if input_body.should_skip() || input_body.tainted_by_errors.is_some() { + debug!("Skipping borrowck because of injected body or tainted body"); // Let's make up a borrowck result! Fun times! let result = BorrowCheckResult { concrete_opaque_types: FxIndexMap::default(), closure_requirements: None, used_mut_upvars: SmallVec::new(), - tainted_by_errors: None, + tainted_by_errors: input_body.tainted_by_errors, }; return tcx.arena.alloc(result); } @@ -126,7 +129,6 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); - let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0; debug!("mir_borrowck done"); @@ -173,12 +175,11 @@ fn do_mir_borrowck<'tcx>( } } - let mut errors = error::BorrowckErrors::new(infcx.tcx); + let mut diags = diags::BorrowckDiags::new(); // Gather the upvars of a closure, if any. if let Some(e) = input_body.tainted_by_errors { infcx.set_tainted_by_errors(e); - errors.set_tainted_by_errors(e); } // Replace all regions with fresh inference variables. This @@ -244,7 +245,7 @@ fn do_mir_borrowck<'tcx>( ®ioncx, &opt_closure_req, &opaque_type_values, - &mut errors, + &mut diags, ); // The various `flow_*` structures can be large. We drop `flow_inits` here @@ -305,11 +306,11 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output: None, move_errors: Vec::new(), - errors, + diags, }; MoveVisitor { ctxt: &mut promoted_mbcx }.visit_body(promoted_body); promoted_mbcx.report_move_errors(); - errors = promoted_mbcx.errors; + diags = promoted_mbcx.diags; struct MoveVisitor<'a, 'cx, 'tcx> { ctxt: &'a mut MirBorrowckCtxt<'cx, 'tcx>, @@ -346,7 +347,7 @@ fn do_mir_borrowck<'tcx>( next_region_name: RefCell::new(1), polonius_output, move_errors: Vec::new(), - errors, + diags, }; // Compute and report region errors, if any. @@ -574,7 +575,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> { /// Results of Polonius analysis. polonius_output: Option>, - errors: error::BorrowckErrors<'tcx>, + diags: diags::BorrowckDiags<'tcx>, move_errors: Vec>, } @@ -1304,7 +1305,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // moved into the closure and subsequently used by the closure, // in order to populate our used_mut set. match **aggregate_kind { - AggregateKind::Closure(def_id, _) | AggregateKind::Coroutine(def_id, _) => { + AggregateKind::Closure(def_id, _) + | AggregateKind::CoroutineClosure(def_id, _) + | AggregateKind::Coroutine(def_id, _) => { let def_id = def_id.expect_local(); let BorrowCheckResult { used_mut_upvars, .. } = self.infcx.tcx.mir_borrowck(def_id); @@ -1610,6 +1613,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -1634,7 +1638,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; } } - ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (), + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::Tuple(_) => (), ty::Bool | ty::Char | ty::Int(_) @@ -2125,7 +2132,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | WriteKind::MutableBorrow(BorrowKind::Fake), ) => { if self.is_mutable(place.as_ref(), is_local_mutation_allowed).is_err() - && !self.has_buffered_errors() + && !self.has_buffered_diags() { // rust-lang/rust#46908: In pure NLL mode this code path should be // unreachable, but we use `span_delayed_bug` because we can hit this when @@ -2383,17 +2390,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } -mod error { +mod diags { use rustc_errors::ErrorGuaranteed; use super::*; - pub struct BorrowckErrors<'tcx> { - tcx: TyCtxt<'tcx>, + enum BufferedDiag<'tcx> { + Error(DiagnosticBuilder<'tcx>), + NonError(DiagnosticBuilder<'tcx, ()>), + } + + impl<'tcx> BufferedDiag<'tcx> { + fn sort_span(&self) -> Span { + match self { + BufferedDiag::Error(diag) => diag.sort_span, + BufferedDiag::NonError(diag) => diag.sort_span, + } + } + } + + pub struct BorrowckDiags<'tcx> { /// This field keeps track of move errors that are to be reported for given move indices. /// - /// There are situations where many errors can be reported for a single move out (see #53807) - /// and we want only the best of those errors. + /// There are situations where many errors can be reported for a single move out (see + /// #53807) and we want only the best of those errors. /// /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of @@ -2406,51 +2426,38 @@ mod error { /// same primary span come out in a consistent order. buffered_move_errors: BTreeMap, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>, + buffered_mut_errors: FxIndexMap, usize)>, - /// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder` - /// because it has a mixture of error diagnostics and non-error diagnostics. - buffered: Vec, - /// Set to Some if we emit an error during borrowck - tainted_by_errors: Option, + + /// Buffer of diagnostics to be reported. A mixture of error and non-error diagnostics. + buffered_diags: Vec>, } - impl<'tcx> BorrowckErrors<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Self { - BorrowckErrors { - tcx, + impl<'tcx> BorrowckDiags<'tcx> { + pub fn new() -> Self { + BorrowckDiags { buffered_move_errors: BTreeMap::new(), buffered_mut_errors: Default::default(), - buffered: Default::default(), - tainted_by_errors: None, + buffered_diags: Default::default(), } } - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { - if let None = self.tainted_by_errors { - self.tainted_by_errors = Some(self.tcx.dcx().span_delayed_bug( - t.span.clone_ignoring_labels(), - "diagnostic buffered but not emitted", - )) - } - self.buffered.push(t.into_diagnostic()); + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) { + self.buffered_diags.push(BufferedDiag::Error(t)); } - pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { - self.buffered.push(t.into_diagnostic()); - } - - pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) { - self.tainted_by_errors = Some(e); + pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) { + self.buffered_diags.push(BufferedDiag::NonError(t)); } } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { - pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_>) { - self.errors.buffer_error(t); + pub fn buffer_error(&mut self, t: DiagnosticBuilder<'tcx>) { + self.diags.buffer_error(t); } - pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) { - self.errors.buffer_non_error_diag(t); + pub fn buffer_non_error(&mut self, t: DiagnosticBuilder<'tcx, ()>) { + self.diags.buffer_non_error(t); } pub fn buffer_move_error( @@ -2459,7 +2466,7 @@ mod error { place_and_err: (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>), ) -> bool { if let Some((_, diag)) = - self.errors.buffered_move_errors.insert(move_out_indices, place_and_err) + self.diags.buffered_move_errors.insert(move_out_indices, place_and_err) { // Cancel the old diagnostic so we don't ICE diag.cancel(); @@ -2473,47 +2480,50 @@ mod error { &mut self, span: Span, ) -> Option<(DiagnosticBuilder<'tcx>, usize)> { - self.errors.buffered_mut_errors.remove(&span) + self.diags.buffered_mut_errors.remove(&span) } pub fn buffer_mut_error(&mut self, span: Span, t: DiagnosticBuilder<'tcx>, count: usize) { - self.errors.buffered_mut_errors.insert(span, (t, count)); + self.diags.buffered_mut_errors.insert(span, (t, count)); } pub fn emit_errors(&mut self) -> Option { + let mut res = None; + // Buffer any move errors that we collected and de-duplicated. - for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) { + for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) { // We have already set tainted for this error, so just buffer it. - self.errors.buffered.push(diag.into_diagnostic()); + self.diags.buffered_diags.push(BufferedDiag::Error(diag)); } - for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) { + for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) { if count > 10 { diag.note(format!("...and {} other attempted mutable borrows", count - 10)); } - self.errors.buffered.push(diag.into_diagnostic()); + self.diags.buffered_diags.push(BufferedDiag::Error(diag)); } - if !self.errors.buffered.is_empty() { - self.errors.buffered.sort_by_key(|diag| diag.sort_span); - - let dcx = self.dcx(); - for diag in self.errors.buffered.drain(..) { - dcx.emit_diagnostic(diag); + if !self.diags.buffered_diags.is_empty() { + self.diags.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span()); + for buffered_diag in self.diags.buffered_diags.drain(..) { + match buffered_diag { + BufferedDiag::Error(diag) => res = Some(diag.emit()), + BufferedDiag::NonError(diag) => diag.emit(), + } } } - self.errors.tainted_by_errors + res } - pub fn has_buffered_errors(&self) -> bool { - self.errors.buffered.is_empty() + pub(crate) fn has_buffered_diags(&self) -> bool { + self.diags.buffered_diags.is_empty() } pub fn has_move_error( &self, move_out_indices: &[MoveOutIndex], - ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'cx>)> { - self.errors.buffered_move_errors.get(move_out_indices) + ) -> Option<&(PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)> { + self.diags.buffered_move_errors.get(move_out_indices) } } } diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 6f09393169f3d..63e59217e5d7d 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_index::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs index 842e90080582f..5129b32d492dd 100644 --- a/compiler/rustc_borrowck/src/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexMap; use rustc_index::{IndexSlice, IndexVec}; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index cc8208e9dc306..80d79e1beb708 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! The entry point of the NLL borrow checker. use polonius_engine::{Algorithm, Output}; @@ -184,7 +182,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let (closure_region_requirements, nll_errors) = - regioncx.solve(infcx, param_env, body, polonius_output.clone()); + regioncx.solve(infcx, body, polonius_output.clone()); if !nll_errors.is_empty() { // Suppress unhelpful extra errors in `infer_opaque_types`. @@ -264,7 +262,7 @@ pub(super) fn dump_annotation<'tcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, opaque_type_values: &FxIndexMap>, - errors: &mut crate::error::BorrowckErrors<'tcx>, + diags: &mut crate::diags::BorrowckDiags<'tcx>, ) { let tcx = infcx.tcx; let base_def_id = tcx.typeck_root_def_id(body.source.def_id()); @@ -310,7 +308,7 @@ pub(super) fn dump_annotation<'tcx>( err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}")); } - errors.buffer_non_error_diag(err); + diags.buffer_non_error(err); } fn for_each_region_constraint<'tcx>( diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 2d997dfadf004..adafad7fa2fde 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::places_conflict; use crate::AccessDepth; @@ -164,7 +162,7 @@ pub(crate) fn is_upvar_field_projection<'tcx>( match place_ref.last_projection() { Some((place_base, ProjectionElem::Field(field, _ty))) => { let base_ty = place_base.ty(body, tcx).ty; - if (base_ty.is_closure() || base_ty.is_coroutine()) + if (base_ty.is_closure() || base_ty.is_coroutine() || base_ty.is_coroutine_closure()) && (!by_ref || upvars[field.index()].is_by_ref()) { Some(field) diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index 3d7e8c6ebf330..b59ab7fafa576 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::LocalsStateAtExit; use rustc_hir as hir; use rustc_middle::mir::ProjectionElem; diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 777ebf0d438dc..7e8dba43b715e 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -50,8 +50,6 @@ //! and either equal or disjoint. //! - If we did run out of access, the borrow can access a part of it. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::ArtificialField; use crate::Overlap; use crate::{AccessDepth, Deep, Shallow}; diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 5c9056272cc0d..93aae1a7f9762 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue}; diff --git a/compiler/rustc_borrowck/src/polonius/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/loan_kills.rs index 5df943837025e..53adad5561e60 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_kills.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_kills.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index e9c9709bd1f1a..8bb3dc88b3467 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an //! place are formed by stripping away fields and derefs, except that //! we stop when we reach the deref of a shared reference. [...] " diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index cfbb2766c3397..53541b33c41d1 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! As part of generating the regions, if you enable `-Zdump-mir=nll`, //! we will generate an annotated copy of the MIR that includes the //! state of region inference. This code handles emitting the region diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 408c8390e763c..c103ba3c40709 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This module provides linkage between RegionInferenceContext and //! `rustc_graphviz` traits, specialized to attaching borrowck analysis //! data to rendered labels. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 89b203f80a435..3153b709ffe38 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -658,7 +658,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(super) fn solve( &mut self, infcx: &InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, polonius_output: Option>, ) -> (Option>, RegionErrors<'tcx>) { @@ -674,7 +673,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // eagerly. let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer); + self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer); debug!(?errors_buffer); debug!(?outlives_requirements); @@ -932,7 +931,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn check_type_tests( &self, infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, mut propagated_outlives_requirements: Option<&mut Vec>>, errors_buffer: &mut RegionErrors<'tcx>, ) { @@ -957,12 +955,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements { - if self.try_promote_type_test( - infcx, - body, - type_test, - propagated_outlives_requirements, - ) { + if self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) { continue; } } @@ -1016,7 +1009,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn try_promote_type_test( &self, infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, type_test: &TypeTest<'tcx>, propagated_outlives_requirements: &mut Vec>, ) -> bool { @@ -1179,35 +1171,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty))) } - /// Returns a universally quantified region that outlives the - /// value of `r` (`r` may be existentially or universally - /// quantified). - /// - /// Since `r` is (potentially) an existential region, it has some - /// value which may include (a) any number of points in the CFG - /// and (b) any number of `end('x)` elements of universally - /// quantified regions. To convert this into a single universal - /// region we do as follows: - /// - /// - Ignore the CFG points in `'r`. All universally quantified regions - /// include the CFG anyhow. - /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding - /// a result `'y`. - #[instrument(skip(self), level = "debug", ret)] - pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid { - debug!(r = %self.region_value_str(r)); - - // Find the smallest universal region that contains all other - // universal regions within `region`. - let mut lub = self.universal_regions.fr_fn_body; - let r_scc = self.constraint_sccs.scc(r); - for ur in self.scc_values.universal_regions_outlived_by(r_scc) { - lub = self.universal_region_relations.postdom_upper_bound(lub, ur); - } - - lub - } - /// Like `universal_upper_bound`, but returns an approximation more suitable /// for diagnostics. If `r` contains multiple disjoint universal regions /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 462b5c8da42c7..636c174e002d2 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -418,6 +418,8 @@ fn check_opaque_type_parameter_valid( .into_iter() .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) .collect(); + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] return Err(tcx .dcx() .struct_span_err(span, "non-defining opaque type use in defining scope") diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs index fe56bd54a3f17..eeb944702a7f9 100644 --- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs +++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::constraints::ConstraintSccIndex; use crate::RegionInferenceContext; use itertools::Itertools; diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index e147f62011db9..b1caaa6388186 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::SparseBitMatrix; diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index a31d39e14cd28..dca8df3280028 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::BorrowckInferCtxt; use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 21d8026e17089..c97e31701669c 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -5,10 +5,13 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; -use rustc_middle::ty::GenericArgKind; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::solve::deeply_normalize; +use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; +use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use crate::{ constraints::OutlivesConstraint, @@ -34,6 +37,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, category: ConstraintCategory<'tcx>, @@ -48,6 +52,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, param_env: ty::ParamEnv<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, category: ConstraintCategory<'tcx>, @@ -60,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { region_bound_pairs, implicit_region_bound, param_env, + known_type_outlives_obligations, locations, span, category, @@ -136,33 +142,69 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // Extract out various useful fields we'll need below. let ConstraintConversion { - tcx, region_bound_pairs, implicit_region_bound, param_env, .. + tcx, + infcx, + region_bound_pairs, + implicit_region_bound, + known_type_outlives_obligations, + .. } = *self; - let ty::OutlivesPredicate(k1, r2) = predicate; - match k1.unpack() { - GenericArgKind::Lifetime(r1) => { - let r1_vid = self.to_region_vid(r1); - let r2_vid = self.to_region_vid(r2); - self.add_outlives(r1_vid, r2_vid, constraint_category); + let mut outlives_predicates = vec![(predicate, constraint_category)]; + for iteration in 0.. { + if outlives_predicates.is_empty() { + break; } - GenericArgKind::Type(t1) => { - // we don't actually use this for anything, but - // the `TypeOutlives` code needs an origin. - let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + if !self.tcx.recursion_limit().value_within_limit(iteration) { + bug!( + "FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}" + ); + } - TypeOutlives::new( - &mut *self, - tcx, - region_bound_pairs, - Some(implicit_region_bound), - param_env, - ) - .type_must_outlive(origin, t1, r2, constraint_category); + let mut next_outlives_predicates = vec![]; + for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates { + match k1.unpack() { + GenericArgKind::Lifetime(r1) => { + let r1_vid = self.to_region_vid(r1); + let r2_vid = self.to_region_vid(r2); + self.add_outlives(r1_vid, r2_vid, constraint_category); + } + + GenericArgKind::Type(mut t1) => { + // Normalize the type we receive from a `TypeOutlives` obligation + // in the new trait solver. + if infcx.next_trait_solver() { + t1 = self.normalize_and_add_type_outlives_constraints( + t1, + &mut next_outlives_predicates, + ); + } + + // we don't actually use this for anything, but + // the `TypeOutlives` code needs an origin. + let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + + TypeOutlives::new( + &mut *self, + tcx, + region_bound_pairs, + Some(implicit_region_bound), + known_type_outlives_obligations, + ) + .type_must_outlive( + origin, + t1, + r2, + constraint_category, + ); + } + + GenericArgKind::Const(_) => unreachable!(), + } } - GenericArgKind::Const(_) => unreachable!(), + outlives_predicates = next_outlives_predicates; } } @@ -228,6 +270,42 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { debug!("add_type_test(type_test={:?})", type_test); self.constraints.type_tests.push(type_test); } + + fn normalize_and_add_type_outlives_constraints( + &self, + ty: Ty<'tcx>, + next_outlives_predicates: &mut Vec<( + ty::OutlivesPredicate, ty::Region<'tcx>>, + ConstraintCategory<'tcx>, + )>, + ) -> Ty<'tcx> { + let result = CustomTypeOp::new( + |ocx| { + deeply_normalize( + ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env), + ty, + ) + .map_err(|_| NoSolution) + }, + "normalize type outlives obligation", + ) + .fully_perform(self.infcx, self.span); + + match result { + Ok(TypeOpOutput { output: ty, constraints, .. }) => { + if let Some(constraints) = constraints { + assert!( + constraints.member_constraints.is_empty(), + "no member constraints expected from normalizing: {:#?}", + constraints.member_constraints + ); + next_outlives_predicates.extend(constraints.outlives.iter().copied()); + } + ty + } + Err(_) => ty, + } + } } impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> { diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 011b5b760c23a..2e0caf4481902 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -8,8 +8,11 @@ use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::OutlivesBound; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; -use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; +use rustc_trait_selection::solve::deeply_normalize; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; use type_op::TypeOpOutput; @@ -45,6 +48,7 @@ type NormalizedInputsAndOutput<'tcx> = Vec>; pub(crate) struct CreateResult<'tcx> { pub(crate) universal_region_relations: Frozen>, pub(crate) region_bound_pairs: RegionBoundPairs<'tcx>, + pub(crate) known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], pub(crate) normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } @@ -200,7 +204,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let defining_ty_def_id = self.universal_regions.defining_ty.def_id().expect_local(); let span = tcx.def_span(defining_ty_def_id); - // Insert the facts we know from the predicates. Why? Why not. + // Insert the `'a: 'b` we know from the predicates. + // This does not consider the type-outlives. let param_env = self.param_env; self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env)); @@ -217,6 +222,32 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.relate_universal_regions(fr, fr_fn_body); } + // Normalize the assumptions we use to borrowck the program. + let mut constraints = vec![]; + let mut known_type_outlives_obligations = vec![]; + for bound in param_env.caller_bounds() { + let Some(mut outlives) = bound.as_type_outlives_clause() else { continue }; + + // In the new solver, normalize the type-outlives obligation assumptions. + if self.infcx.next_trait_solver() { + match deeply_normalize( + self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env), + outlives, + ) { + Ok(normalized_outlives) => { + outlives = normalized_outlives; + } + Err(e) => { + self.infcx.err_ctxt().report_fulfillment_errors(e); + } + } + } + + known_type_outlives_obligations.push(outlives); + } + let known_type_outlives_obligations = + self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations); + let unnormalized_input_output_tys = self .universal_regions .unnormalized_input_tys @@ -234,7 +265,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // the `relations` is built. let mut normalized_inputs_and_output = Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1); - let mut constraints = vec![]; for ty in unnormalized_input_output_tys { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty. @@ -299,7 +329,19 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { } for c in constraints { - self.push_region_constraints(c, span); + constraint_conversion::ConstraintConversion::new( + self.infcx, + &self.universal_regions, + &self.region_bound_pairs, + self.implicit_region_bound, + param_env, + known_type_outlives_obligations, + Locations::All(span), + span, + ConstraintCategory::Internal, + self.constraints, + ) + .convert_all(c); } CreateResult { @@ -308,29 +350,12 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { outlives: self.outlives.freeze(), inverse_outlives: self.inverse_outlives.freeze(), }), + known_type_outlives_obligations, region_bound_pairs: self.region_bound_pairs, normalized_inputs_and_output, } } - #[instrument(skip(self, data), level = "debug")] - fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) { - debug!("constraints generated: {:#?}", data); - - constraint_conversion::ConstraintConversion::new( - self.infcx, - &self.universal_regions, - &self.region_bound_pairs, - self.implicit_region_bound, - self.param_env, - Locations::All(span), - span, - ConstraintCategory::Internal, - self.constraints, - ) - .convert_all(data); - } - /// Update the type of a single local, which should represent /// either the return type of the MIR or one of its arguments. At /// the same time, compute and add any implied bounds that come diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 59518f68ab149..a5a7ce4ea3e86 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,13 +7,18 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). +use std::assert_matches::assert_matches; + use itertools::Itertools; -use rustc_infer::infer::BoundRegionConversionTime; +use rustc_hir as hir; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; -use crate::universal_regions::UniversalRegions; +use crate::renumber::RegionCtxt; +use crate::universal_regions::{DefiningTy, UniversalRegions}; use super::{Locations, TypeChecker}; @@ -23,9 +28,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self, body), level = "debug")] pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) { let mir_def_id = body.source.def_id().expect_local(); + if !self.tcx().is_closure_or_coroutine(mir_def_id.to_def_id()) { return; } + let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id); // Instantiate the canonicalized variables from user-provided signature @@ -34,12 +41,75 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // so that they represent the view from "inside" the closure. let user_provided_sig = self .instantiate_canonical_with_fresh_inference_vars(body.span, &user_provided_poly_sig); - let user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( + let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( body.span, BoundRegionConversionTime::FnCall, user_provided_sig, ); + // FIXME(async_closures): It's kind of wacky that we must apply this + // transformation here, since we do the same thing in HIR typeck. + // Maybe we could just fix up the canonicalized signature during HIR typeck? + if let DefiningTy::CoroutineClosure(_, args) = + self.borrowck_context.universal_regions.defining_ty + { + assert_matches!( + self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)), + Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure + )), + "this needs to be modified if we're lowering non-async closures" + ); + // Make sure to use the args from `DefiningTy` so the right NLL region vids are prepopulated + // into the type. + let args = args.as_coroutine_closure(); + let tupled_upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( + self.tcx(), + args.kind(), + Ty::new_tup(self.tcx(), user_provided_sig.inputs()), + args.tupled_upvars_ty(), + args.coroutine_captures_by_ref_ty(), + self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(body.span), || { + RegionCtxt::Unknown + }), + ); + + let next_ty_var = || { + self.infcx.next_ty_var(TypeVariableOrigin { + span: body.span, + kind: TypeVariableOriginKind::MiscVariable, + }) + }; + let output_ty = Ty::new_coroutine( + self.tcx(), + self.tcx().coroutine_for_closure(mir_def_id), + ty::CoroutineArgs::new( + self.tcx(), + ty::CoroutineArgsParts { + parent_args: args.parent_args(), + kind_ty: Ty::from_closure_kind(self.tcx(), args.kind()), + return_ty: user_provided_sig.output(), + tupled_upvars_ty, + // For async closures, none of these can be annotated, so just fill + // them with fresh ty vars. + resume_ty: next_ty_var(), + yield_ty: next_ty_var(), + witness: next_ty_var(), + }, + ) + .args, + ); + + user_provided_sig = self.tcx().mk_fn_sig( + user_provided_sig.inputs().iter().copied(), + output_ty, + user_provided_sig.c_variadic, + user_provided_sig.unsafety, + user_provided_sig.abi, + ); + } + let is_coroutine_with_implicit_resume_ty = self.tcx().is_coroutine(mir_def_id.to_def_id()) && user_provided_sig.inputs().is_empty(); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 488dfc64cf6f0..cfb46f3ac8a96 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This pass type-checks the MIR to ensure it is not broken. use std::rc::Rc; @@ -152,6 +150,7 @@ pub(crate) fn type_check<'mir, 'tcx>( universal_region_relations, region_bound_pairs, normalized_inputs_and_output, + known_type_outlives_obligations, } = free_region_relations::create( infcx, param_env, @@ -176,6 +175,7 @@ pub(crate) fn type_check<'mir, 'tcx>( body, param_env, ®ion_bound_pairs, + known_type_outlives_obligations, implicit_region_bound, &mut borrowck_context, ); @@ -211,7 +211,6 @@ pub(crate) fn type_check<'mir, 'tcx>( CustomTypeOp::new( |ocx| { ocx.infcx.register_member_constraints( - param_env, opaque_type_key, decl.hidden_type.ty, decl.hidden_type.span, @@ -802,6 +801,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }), }; } + ty::CoroutineClosure(_, args) => { + return match args.as_coroutine_closure().upvar_tys().get(field.index()) { + Some(&ty) => Ok(ty), + None => Err(FieldAccessError::OutOfRange { + field_count: args.as_coroutine_closure().upvar_tys().len(), + }), + }; + } ty::Coroutine(_, args) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. @@ -850,6 +857,7 @@ struct TypeChecker<'a, 'tcx> { /// all of the promoted items. user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, reported_errors: FxIndexSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -1000,6 +1008,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { body: &'a Body<'tcx>, param_env: ty::ParamEnv<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, + known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, ) -> Self { @@ -1010,6 +1019,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { user_type_annotations: &body.user_type_annotations, param_env, region_bound_pairs, + known_type_outlives_obligations, implicit_region_bound, borrowck_context, reported_errors: Default::default(), @@ -1128,6 +1138,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.region_bound_pairs, self.implicit_region_bound, self.param_env, + self.known_type_outlives_obligations, locations, locations.span(self.body), category, @@ -1866,6 +1877,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }), } } + AggregateKind::CoroutineClosure(_, args) => { + match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), + None => Err(FieldAccessError::OutOfRange { + field_count: args.as_coroutine_closure().upvar_tys().len(), + }), + } + } AggregateKind::Array(ty) => Ok(ty), AggregateKind::Tuple => { unreachable!("This should have been covered in check_rvalues"); @@ -1962,6 +1981,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::SizedBound, ); } + &Rvalue::NullaryOp(NullOp::DebugAssertions, _) => {} Rvalue::ShallowInitBox(operand, ty) => { self.check_operand(operand, location); @@ -2469,6 +2489,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { AggregateKind::Tuple => None, AggregateKind::Closure(_, _) => None, AggregateKind::Coroutine(_, _) => None, + AggregateKind::CoroutineClosure(_, _) => None, }, } } @@ -2696,7 +2717,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // desugaring. A closure gets desugared to a struct, and // these extra requirements are basically like where // clauses on the struct. - AggregateKind::Closure(def_id, args) | AggregateKind::Coroutine(def_id, args) => ( + AggregateKind::Closure(def_id, args) + | AggregateKind::CoroutineClosure(def_id, args) + | AggregateKind::Coroutine(def_id, args) => ( def_id, self.prove_closure_bounds( tcx, @@ -2732,6 +2755,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.region_bound_pairs, self.implicit_region_bound, self.param_env, + self.known_type_outlives_obligations, locations, DUMMY_SP, // irrelevant; will be overridden. ConstraintCategory::Boring, // same as above. @@ -2745,10 +2769,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); let parent_args = match tcx.def_kind(def_id) { - DefKind::Closure if tcx.is_coroutine(def_id.to_def_id()) => { - args.as_coroutine().parent_args() + // We don't want to dispatch on 3 different kind of closures here, so take + // advantage of the fact that the `parent_args` is the same length as the + // `typeck_root_args`. + DefKind::Closure => { + // FIXME(async_closures): It may be useful to add a debug assert here + // to actually call `type_of` and check the `parent_args` are the same + // length as the `typeck_root_args`. + &args[..typeck_root_args.len()] } - DefKind::Closure => args.as_closure().parent_args(), DefKind::InlineConst => args.as_inline_const().parent_args(), other => bug!("unexpected item {:?}", other), }; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index ae8a135f09059..a7bdfa4eae769 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -12,6 +12,9 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -97,6 +100,13 @@ pub enum DefiningTy<'tcx> { /// `ClosureArgs::coroutine_return_ty`. Coroutine(DefId, GenericArgsRef<'tcx>), + /// The MIR is a special kind of closure that returns coroutines. + /// + /// See the documentation on `CoroutineClosureSignature` for details + /// on how to construct the callable signature of the coroutine from + /// its args. + CoroutineClosure(DefId, GenericArgsRef<'tcx>), + /// The MIR is a fn item with the given `DefId` and args. The signature /// of the function can be bound then with the `fn_sig` query. FnDef(DefId, GenericArgsRef<'tcx>), @@ -119,6 +129,7 @@ impl<'tcx> DefiningTy<'tcx> { pub fn upvar_tys(self) -> &'tcx ty::List> { match self { DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), + DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(), DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(), DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { ty::List::empty() @@ -131,7 +142,9 @@ impl<'tcx> DefiningTy<'tcx> { /// user's code. pub fn implicit_inputs(self) -> usize { match self { - DefiningTy::Closure(..) | DefiningTy::Coroutine(..) => 1, + DefiningTy::Closure(..) + | DefiningTy::CoroutineClosure(..) + | DefiningTy::Coroutine(..) => 1, DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0, } } @@ -147,6 +160,7 @@ impl<'tcx> DefiningTy<'tcx> { pub fn def_id(&self) -> DefId { match *self { DefiningTy::Closure(def_id, ..) + | DefiningTy::CoroutineClosure(def_id, ..) | DefiningTy::Coroutine(def_id, ..) | DefiningTy::FnDef(def_id, ..) | DefiningTy::Const(def_id, ..) @@ -355,6 +369,9 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(format!("late-bound region is {:?}", self.to_region_vid(r))); }); } + DefiningTy::CoroutineClosure(..) => { + todo!() + } DefiningTy::Coroutine(def_id, args) => { let v = with_no_trimmed_paths!( args[tcx.generics_of(def_id).parent_count..] @@ -568,6 +585,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { match *defining_ty.kind() { ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args), ty::Coroutine(def_id, args) => DefiningTy::Coroutine(def_id, args), + ty::CoroutineClosure(def_id, args) => { + DefiningTy::CoroutineClosure(def_id, args) + } ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args), _ => span_bug!( tcx.def_span(self.mir_def), @@ -623,6 +643,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); let fr_args = match defining_ty { DefiningTy::Closure(_, args) + | DefiningTy::CoroutineClosure(_, args) | DefiningTy::Coroutine(_, args) | DefiningTy::InlineConst(_, args) => { // In the case of closures, we rely on the fact that @@ -702,6 +723,55 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ty::Binder::dummy(inputs_and_output) } + // Construct the signature of the CoroutineClosure for the purposes of borrowck. + // This is pretty straightforward -- we: + // 1. first grab the `coroutine_closure_sig`, + // 2. compute the self type (`&`/`&mut`/no borrow), + // 3. flatten the tupled_input_tys, + // 4. construct the correct generator type to return with + // `CoroutineClosureSignature::to_coroutine_given_kind_and_upvars`. + // Then we wrap it all up into a list of inputs and output. + DefiningTy::CoroutineClosure(def_id, args) => { + assert_eq!(self.mir_def.to_def_id(), def_id); + let closure_sig = args.as_coroutine_closure().coroutine_closure_sig(); + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( + closure_sig + .bound_vars() + .iter() + .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BrEnv, + }; + let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); + let closure_kind = args.as_coroutine_closure().kind(); + + let closure_ty = tcx.closure_env_ty( + Ty::new_coroutine_closure(tcx, def_id, args), + closure_kind, + env_region, + ); + + let inputs = closure_sig.skip_binder().tupled_inputs_ty.tuple_fields(); + let output = closure_sig.skip_binder().to_coroutine_given_kind_and_upvars( + tcx, + args.as_coroutine_closure().parent_args(), + tcx.coroutine_for_closure(def_id), + closure_kind, + env_region, + args.as_coroutine_closure().tupled_upvars_ty(), + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + ); + + ty::Binder::bind_with_vars( + tcx.mk_type_list_from_iter( + iter::once(closure_ty).chain(inputs).chain(iter::once(output)), + ), + bound_vars, + ) + } + DefiningTy::FnDef(def_id, _) => { let sig = tcx.fn_sig(def_id).instantiate_identity(); let sig = indices.fold_to_region_vids(tcx, sig); diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 6ac8e1ba7156a..81757a62e5bc5 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index eadb48ddd36d8..8d2e06bf30dac 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, - Level, MultiSpan, SingleLabelManySpans, + codes::*, AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, + IntoDiagnostic, Level, MultiSpan, SingleLabelManySpans, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -611,13 +611,7 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl AddToDiagnostic for FormatUnusedArg { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { diag.arg("named", self.named); let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); diag.span_label(self.span, msg); diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index eb331ef585301..b66f7111ff006 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -139,7 +139,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult< _ => { let expr = p.parse_expr()?; if !args.named_args().is_empty() { - ecx.dcx().emit_err(errors::PositionalAfterNamed { + return Err(ecx.dcx().create_err(errors::PositionalAfterNamed { span: expr.span, args: args .named_args() @@ -147,7 +147,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult< .filter_map(|a| a.kind.ident().map(|ident| (a, ident))) .map(|(arg, n)| n.span.to(arg.expr.span)) .collect(), - }); + })); } args.add(FormatArgument { kind: FormatArgumentKind::Normal, expr }); } @@ -313,6 +313,8 @@ fn make_format_args( } use ArgRef::*; + let mut unnamed_arg_after_named_arg = false; + let mut lookup_arg = |arg: ArgRef<'_>, span: Option, used_as: PositionUsedAs, @@ -352,6 +354,7 @@ fn make_format_args( // For the moment capturing variables from format strings expanded from macros is // disabled (see RFC #2795) ecx.dcx().emit_err(errors::FormatNoArgNamed { span, name }); + unnamed_arg_after_named_arg = true; DummyResult::raw_expr(span, true) }; Ok(args.add(FormatArgument { kind: FormatArgumentKind::Captured(ident), expr })) @@ -510,7 +513,8 @@ fn make_format_args( }) .collect::>(); - if !unused.is_empty() { + let has_unused = !unused.is_empty(); + if has_unused { // If there's a lot of unused arguments, // let's check if this format arguments looks like another syntax (printf / shell). let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2; @@ -529,7 +533,7 @@ fn make_format_args( // Only check for unused named argument names if there are no other errors to avoid causing // too much noise in output errors, such as when a named argument is entirely unused. - if invalid_refs.is_empty() && ecx.dcx().has_errors().is_none() { + if invalid_refs.is_empty() && !has_unused && !unnamed_arg_after_named_arg { for &(index, span, used_as) in &numeric_refences_to_named_arg { let (position_sp_to_replace, position_sp_for_msg) = match used_as { Placeholder(pspan) => (span, pspan), diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 4d7957ef4ddb0..d30ccab239437 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -2,6 +2,8 @@ //! injecting code into the crate before it is lowered to HIR. #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(rustdoc_internals)] #![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 86bc7d0f067cb..b70a1234af398 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -4,13 +4,14 @@ version = 3 [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" dependencies = [ "cfg-if", "once_cell", "version_check", + "zerocopy", ] [[package]] @@ -293,6 +294,24 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "proc-macro2" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + [[package]] name = "regalloc2" version = "0.9.3" @@ -360,12 +379,29 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "syn" +version = "2.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "target-lexicon" version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "version_check" version = "0.9.4" @@ -536,3 +572,23 @@ name = "windows_x86_64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index abd70dd4458f6..0f0d828c8fc3f 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -56,11 +56,7 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented"); } - Conv::Msp430Intr - | Conv::PtxKernel - | Conv::AmdGpuKernel - | Conv::AvrInterrupt - | Conv::AvrNonBlockingInterrupt => { + Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => { unreachable!("tried to use {c:?} call conv which only exists on an unsupported target"); } } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 0afd6d0e670b3..a7e76fbc128ea 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -767,6 +767,15 @@ fn codegen_stmt<'tcx>( NullOp::OffsetOf(fields) => { layout.offset_of_subfield(fx, fields.iter()).bytes() } + NullOp::DebugAssertions => { + let val = fx.tcx.sess.opts.debug_assertions; + let val = CValue::by_val( + fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()), + fx.layout_of(fx.tcx.types.bool), + ); + lval.write_cvalue(fx, val); + return; + } }; let val = CValue::by_val( fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()), diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 416f87fcc87b3..7c432e9c59051 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -3,6 +3,8 @@ #![cfg_attr(doc, doc(rust_logo))] #![feature(rustc_private)] // Note: please avoid adding other feature gates where possible +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs index 9f361d3688695..142f86b003ddb 100644 --- a/compiler/rustc_codegen_gcc/src/attributes.rs +++ b/compiler/rustc_codegen_gcc/src/attributes.rs @@ -62,9 +62,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { func.add_attribute(FnAttribute::Cold); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { - func.add_attribute(FnAttribute::ReturnsTwice); - } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { func.add_attribute(FnAttribute::Pure); } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 03f8f43ff1643..863b6333bcc29 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -27,8 +27,6 @@ #![recursion_limit="256"] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] extern crate rustc_apfloat; extern crate rustc_ast; @@ -408,7 +406,7 @@ pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &Locke .filter(|_feature| { target_info.cpu_supports(_feature) /* - adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512ifma, + adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma, avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq, bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm, sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index e5c0b2de4ca46..25149b8020162 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -87,7 +87,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout // FIXME(eddyb) producing readable type names for trait objects can result // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | - ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str if !cx.sess().fewer_names() => { let mut name = with_no_trimmed_paths!(layout.ty.to_string()); diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index d5bc04f594da1..d14fe0299e64c 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -28,6 +28,8 @@ codegen_llvm_invalid_minimum_alignment_not_power_of_two = codegen_llvm_invalid_minimum_alignment_too_large = invalid minimum global alignment: {$align} is too large +codegen_llvm_invalid_target_feature_prefix = target feature `{$feature}` must begin with a `+` or `-`" + codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}" codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err} diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 0718bebb31bf8..b5b4f894e4d82 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -590,7 +590,6 @@ impl From for llvm::CallConv { Conv::Cold => llvm::ColdCallConv, Conv::PreserveMost => llvm::PreserveMost, Conv::PreserveAll => llvm::PreserveAll, - Conv::AmdGpuKernel => llvm::AmdGpuKernel, Conv::AvrInterrupt => llvm::AvrInterrupt, Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, Conv::ArmAapcs => llvm::ArmAapcsCallConv, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 0a7ea5994312e..07c83f1aa089a 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -356,9 +356,6 @@ pub fn from_fn_attrs<'ll, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { to_add.push(AttributeKind::Cold.create_attr(cx.llcx)); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { - to_add.push(AttributeKind::ReturnsTwice.create_attr(cx.llcx)); - } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { to_add.push(MemoryEffects::ReadOnly.create_attr(cx.llcx)); } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 6cb62280a595e..7dfcf1ab50e41 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -909,6 +909,7 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.is.constant.isize", fn(t_isize) -> i1); ifn!("llvm.is.constant.f32", fn(t_f32) -> i1); ifn!("llvm.is.constant.f64", fn(t_f64) -> i1); + ifn!("llvm.is.constant.ptr", fn(ptr) -> i1); ifn!("llvm.expect.i1", fn(i1, i1) -> i1); ifn!("llvm.eh.typeid.for", fn(ptr) -> t_i32); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 6116a6fd222b3..b1ceb1d4dd56d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -403,6 +403,7 @@ fn codegenned_and_inlined_items(tcx: TyCtxt<'_>) -> DefIdSet { let mut result = items.clone(); for cgu in cgus { + #[allow(rustc::potential_query_instability)] for item in cgu.items().keys() { if let mir::mono::MonoItem::Fn(ref instance) = item { let did = instance.def_id(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 76c9ac6614a30..f961cd2d00b06 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -461,6 +461,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D } ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id), ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), + ty::CoroutineClosure(..) => build_closure_env_di_node(cx, unique_type_id), ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id), ty::Adt(def, ..) => match def.adt_kind() { AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id), @@ -1068,6 +1069,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() { ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().prefix_tys()), ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()), + ty::CoroutineClosure(def_id, args) => (def_id, args.as_coroutine_closure().upvar_tys()), _ => { bug!( "build_upvar_field_di_nodes() called with non-closure-or-coroutine-type: {:?}", @@ -1153,7 +1155,8 @@ fn build_closure_env_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let closure_env_type = unique_type_id.expect_ty(); - let &ty::Closure(def_id, _args) = closure_env_type.kind() else { + let &(ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _)) = closure_env_type.kind() + else { bug!("build_closure_env_di_node() called with non-closure-type: {:?}", closure_env_type) }; let containing_scope = get_namespace_for_item(cx, def_id); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index d82ff6656f4d3..587c5e9e8d235 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -102,7 +102,7 @@ pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); impl IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> { fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level); - let (message, _) = diag.messages().first().expect("`LlvmError` with no message"); + let (message, _) = diag.messages.first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args()); DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config) @@ -253,3 +253,9 @@ pub struct MismatchedDataLayout<'a> { pub llvm_target: &'a str, pub llvm_layout: &'a str, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_invalid_target_feature_prefix)] +pub(crate) struct InvalidTargetFeaturePrefix<'a> { + pub feature: &'a str, +} diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f1a6f7bd8e690..e3e48ecb3aa5f 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -119,10 +119,18 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::likely => { self.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(true)]) } - sym::is_val_statically_known => self.call_intrinsic( - &format!("llvm.is.constant.{:?}", args[0].layout.immediate_llvm_type(self.cx)), - &[args[0].immediate()], - ), + sym::is_val_statically_known => { + let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx); + match self.type_kind(intrinsic_type) { + TypeKind::Pointer | TypeKind::Integer | TypeKind::Float | TypeKind::Double => { + self.call_intrinsic( + &format!("llvm.is.constant.{:?}", intrinsic_type), + &[args[0].immediate()], + ) + } + _ => self.const_bool(false), + } + } sym::unlikely => self .call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]), kw::Try => { @@ -1977,10 +1985,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match in_elem.kind() { ty::RawPtr(p) => { - let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); - assert!(!check_sized); // we are in codegen, so we shouldn't see these types require!( metadata.is_unit(), InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem } @@ -1992,10 +1999,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } match out_elem.kind() { ty::RawPtr(p) => { - let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); - assert!(!check_sized); // we are in codegen, so we shouldn't see these types require!( metadata.is_unit(), InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index f4f29078190a1..de96bf477adb7 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -15,8 +15,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(impl_trait_in_assoc_type)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ee73c6b4756f0..d0044086c616e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -106,7 +106,6 @@ pub enum CallConv { X86_Intr = 83, AvrNonBlockingInterrupt = 84, AvrInterrupt = 85, - AmdGpuKernel = 91, } /// LLVMRustLinkage @@ -185,7 +184,6 @@ pub enum AttributeKind { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, - ReturnsTwice = 25, ReadNone = 26, SanitizeHWAddress = 28, WillReturn = 29, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 99f4488ac0f97..4bb400b187989 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,7 +1,7 @@ use crate::back::write::create_informational_target_machine; use crate::errors::{ - PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, - UnknownCTargetFeaturePrefix, UnstableCTargetFeature, + InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, + UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; use libc::c_int; @@ -511,7 +511,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec Vec Vec Option<&str> { +fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { // features must start with a `+` or `-`. - let feature = s.strip_prefix(&['+', '-'][..]).unwrap_or_else(|| { - bug!("target feature `{}` must begin with a `+` or `-`", s); - }); + let feature = s + .strip_prefix(&['+', '-'][..]) + .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s })); // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index f796ce0990f12..f763071936837 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -123,6 +123,17 @@ impl CodegenCx<'_, '_> { return false; } + // Match clang by only supporting COFF and ELF for now. + if self.tcx.sess.target.is_like_osx { + return false; + } + + // With pie relocation model calls of functions defined in the translation + // unit can use copy relocations. + if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration { + return true; + } + // Thread-local variables generally don't support copy relocations. let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval) .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True); @@ -130,18 +141,12 @@ impl CodegenCx<'_, '_> { return false; } - // Match clang by only supporting COFF and ELF for now. - if self.tcx.sess.target.is_like_osx { - return false; + // Respect the direct-access-external-data to override default behavior if present. + if let Some(direct) = self.tcx.sess.direct_access_external_data() { + return direct; } // Static relocation model should force copy relocations everywhere. - if self.tcx.sess.relocation_model() == RelocModel::Static { - return true; - } - - // With pie relocation model calls of functions defined in the translation - // unit can use copy relocations. - self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration + self.tcx.sess.relocation_model() == RelocModel::Static } } diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index e88f4217c9dca..219c702531141 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -33,7 +33,7 @@ fn uncached_llvm_type<'a, 'tcx>( // FIXME(eddyb) producing readable type names for trait objects can result // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | - ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str // For performance reasons we use names only when emitting LLVM IR. if !cx.sess().fewer_names() => { diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 7d2f5bb193a39..c4aaf421444ec 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -9,7 +9,7 @@ ar_archive_writer = "0.1.5" bitflags = "2.4.1" cc = "1.0.69" itertools = "0.11" -jobserver = "0.1.27" +jobserver = "0.1.28" pathdiff = "0.2.0" regex = "1.4" rustc_arena = { path = "../rustc_arena" } diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index ad5a74b04e447..3e5a43c6e73a6 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -267,6 +267,7 @@ impl CguReuseTracker { fn check_expected_reuse(&self, sess: &Session) { if let Some(ref data) = self.data { + #[allow(rustc::potential_query_instability)] let mut keys = data.expected_reuse.keys().collect::>(); keys.sort_unstable(); for cgu_name in keys { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f098fc9cb5970..b29f71bfb9553 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -682,6 +682,7 @@ fn link_dwarf_object<'a>( } // Input rlibs contain .o/.dwo files from dependencies. + #[allow(rustc::potential_query_instability)] let input_rlibs = cg_results .crate_info .used_crate_source diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 06edb79453727..9b24339d2551f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -39,7 +39,6 @@ use rustc_target::spec::{MergeFunctions, SanitizerSet}; use crate::errors::ErrorCreatingRemarkDir; use std::any::Any; -use std::borrow::Cow; use std::fs; use std::io; use std::marker::PhantomData; @@ -1811,13 +1810,13 @@ impl Translate for SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { - let args: FxHashMap, DiagnosticArgValue> = + fn emit_diagnostic(&mut self, diag: rustc_errors::Diagnostic) { + let args: FxHashMap = diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect(); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { msgs: diag.messages.clone(), args: args.clone(), - code: diag.code.clone(), + code: diag.code, lvl: diag.level(), }))); for child in &diag.children { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 47b1b0801193a..b387d0b2258b0 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -103,9 +103,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { match name { sym::cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR, - sym::ffi_returns_twice => { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE - } sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST, sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 4f9f70648bd88..5bd7442822a21 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -398,7 +398,9 @@ fn push_debuginfo_type_name<'tcx>( // processing visited.remove(&t); } - ty::Closure(def_id, args) | ty::Coroutine(def_id, args, ..) => { + ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) + | ty::Coroutine(def_id, args, ..) => { // Name will be "{closure_env#0}", "{coroutine_env#0}", or // "{async_fn_env#0}", etc. // In the case of cpp-like debuginfo, the name additionally gets wrapped inside of @@ -768,6 +770,8 @@ fn push_closure_or_coroutine_name<'tcx>( // Truncate the args to the length of the above generics. This will cut off // anything closure- or coroutine-specific. + // FIXME(async_closures): This is probably not going to be correct w.r.t. + // multiple coroutine flavors. Maybe truncate to (parent + 1)? let args = args.truncate_to(tcx, generics); push_generic_params_internal(tcx, args, enclosing_fn_def_id, output, visited); } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index fc833a3863e40..1afc597a7ef01 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,6 +2,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 266505d3f2691..5c6060a7159aa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -672,17 +672,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = match null_op { mir::NullOp::SizeOf => { assert!(bx.cx().type_is_sized(ty)); - layout.size.bytes() + let val = layout.size.bytes(); + bx.cx().const_usize(val) } mir::NullOp::AlignOf => { assert!(bx.cx().type_is_sized(ty)); - layout.align.abi.bytes() + let val = layout.align.abi.bytes(); + bx.cx().const_usize(val) } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(bx.cx(), fields.iter()).bytes() + let val = layout.offset_of_subfield(bx.cx(), fields.iter()).bytes(); + bx.cx().const_usize(val) + } + mir::NullOp::DebugAssertions => { + let val = bx.tcx().sess.opts.debug_assertions; + bx.cx().const_bool(val) } }; - let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); OperandRef { val: OperandValue::Immediate(val), diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index a158fc6e26074..ac7dfbb261dec 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,5 +1,6 @@ use rustc_middle::mir; use rustc_middle::mir::NonDivergingIntrinsic; +use rustc_session::config::OptLevel; use super::FunctionCx; use super::LocalRef; @@ -67,8 +68,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_coverage(bx, coverage, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { - let op_val = self.codegen_operand(bx, op); - bx.assume(op_val.immediate()); + if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) { + let op_val = self.codegen_operand(bx, op); + bx.assume(op_val.immediate()); + } } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( mir::CopyNonOverlapping { ref count, ref src, ref dst }, diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index dabf78ef90e5f..62af21396ab4b 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -1,6 +1,8 @@ use std::mem; -use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg}; +use rustc_errors::{ + DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg, +}; use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::AssertKind; use rustc_middle::query::TyCtxtAt; @@ -32,10 +34,7 @@ impl MachineStopType for ConstEvalErrKind { AssertFailure(x) => x.diagnostic_message(), } } - fn add_args( - self: Box, - adder: &mut dyn FnMut(std::borrow::Cow<'static, str>, DiagnosticArgValue), - ) { + fn add_args(self: Box, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) { use ConstEvalErrKind::*; match *self { ConstAccessesStatic | ModifiedGlobal => {} @@ -50,9 +49,7 @@ impl MachineStopType for ConstEvalErrKind { } } -// The errors become `MachineStop` with plain strings when being raised. -// `ConstEvalErr` (in `librustc_middle/mir/interpret/error.rs`) knows to -// handle these. +/// The errors become [`InterpError::MachineStop`] when being raised. impl<'tcx> Into> for ConstEvalErrKind { fn into(self) -> InterpErrorInfo<'tcx> { err_machine_stop!(self).into() diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 6a92ed9717de5..a2d0f1c5583f3 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,5 +1,3 @@ -use std::mem; - use either::{Left, Right}; use rustc_hir::def::DefKind; @@ -24,12 +22,13 @@ use crate::interpret::{ }; // Returns a pointer to where the result lives +#[instrument(level = "trace", skip(ecx, body), ret)] fn eval_body_using_ecx<'mir, 'tcx>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, cid: GlobalId<'tcx>, body: &'mir mir::Body<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); + trace!(?ecx.param_env); let tcx = *ecx.tcx; assert!( cid.promoted.is_some() @@ -75,11 +74,8 @@ fn eval_body_using_ecx<'mir, 'tcx>( None => InternKind::Constant, } }; - let check_alignment = mem::replace(&mut ecx.machine.check_alignment, CheckAlignment::No); // interning doesn't need to respect alignment intern_const_alloc_recursive(ecx, intern_kind, &ret)?; - ecx.machine.check_alignment = check_alignment; - debug!("eval_body_using_ecx done: {:?}", ret); Ok(ret) } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 12544f5b02955..5c2bf4626c4c3 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -172,6 +172,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>( | ty::Infer(_) // FIXME(oli-obk): we can probably encode closures just like structs | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => Err(ValTreeCreationError::NonSupportedType), } @@ -301,6 +302,7 @@ pub fn valtree_to_const_value<'tcx>( | ty::Placeholder(..) | ty::Infer(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::FnPtr(_) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index c14bd142efacc..dd989ab80fd3c 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1007,6 +1007,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Error(_) => true, diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 751fbfacaad00..38e7843761be8 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -41,13 +41,12 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< /// allocation is interned immutably; if it is `Mutability::Mut`, then the allocation *must be* /// already mutable (as a sanity check). /// -/// `recursive_alloc` is called for all recursively encountered allocations. +/// Returns an iterator over all relocations referred to by this allocation. fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( ecx: &'rt mut InterpCx<'mir, 'tcx, M>, alloc_id: AllocId, mutability: Mutability, - mut recursive_alloc: impl FnMut(&InterpCx<'mir, 'tcx, M>, CtfeProvenance), -) -> Result<(), ()> { +) -> Result + 'tcx, ()> { trace!("intern_shallow {:?}", alloc_id); // remove allocation let Some((_kind, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) else { @@ -65,14 +64,10 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( assert_eq!(alloc.mutability, Mutability::Mut); } } - // record child allocations - for &(_, prov) in alloc.provenance().ptrs().iter() { - recursive_alloc(ecx, prov); - } // link the alloc id to the actual allocation let alloc = ecx.tcx.mk_const_alloc(alloc); ecx.tcx.set_alloc_id_memory(alloc_id, alloc); - Ok(()) + Ok(alloc.0.0.provenance().ptrs().iter().map(|&(_, prov)| prov)) } /// How a constant value should be interned. @@ -128,12 +123,16 @@ pub fn intern_const_alloc_recursive< } }; - // Initialize recursive interning. + // Intern the base allocation, and initialize todo list for recursive interning. let base_alloc_id = ret.ptr().provenance.unwrap().alloc_id(); - let mut todo = vec![(base_alloc_id, base_mutability)]; + // First we intern the base allocation, as it requires a different mutability. + // This gives us the initial set of nested allocations, which will then all be processed + // recursively in the loop below. + let mut todo: Vec<_> = + intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().map(|prov| prov).collect(); // We need to distinguish "has just been interned" from "was already in `tcx`", // so we track this in a separate set. - let mut just_interned = FxHashSet::default(); + let mut just_interned: FxHashSet<_> = std::iter::once(base_alloc_id).collect(); // Whether we encountered a bad mutable pointer. // We want to first report "dangling" and then "mutable", so we need to delay reporting these // errors. @@ -147,52 +146,56 @@ pub fn intern_const_alloc_recursive< // raw pointers, so we cannot rely on validation to catch them -- and since interning runs // before validation, and interning doesn't know the type of anything, this means we can't show // better errors. Maybe we should consider doing validation before interning in the future. - while let Some((alloc_id, mutability)) = todo.pop() { + while let Some(prov) = todo.pop() { + let alloc_id = prov.alloc_id(); + // Crucially, we check this *before* checking whether the `alloc_id` + // has already been interned. The point of this check is to ensure that when + // there are multiple pointers to the same allocation, they are *all* immutable. + // Therefore it would be bad if we only checked the first pointer to any given + // allocation. + // (It is likely not possible to actually have multiple pointers to the same allocation, + // so alternatively we could also check that and ICE if there are multiple such pointers.) + if intern_kind != InternKind::Promoted + && inner_mutability == Mutability::Not + && !prov.immutable() + { + if ecx.tcx.try_get_global_alloc(alloc_id).is_some() + && !just_interned.contains(&alloc_id) + { + // This is a pointer to some memory from another constant. We encounter mutable + // pointers to such memory since we do not always track immutability through + // these "global" pointers. Allowing them is harmless; the point of these checks + // during interning is to justify why we intern the *new* allocations immutably, + // so we can completely ignore existing allocations. We also don't need to add + // this to the todo list, since after all it is already interned. + continue; + } + // Found a mutable pointer inside a const where inner allocations should be + // immutable. We exclude promoteds from this, since things like `&mut []` and + // `&None::>` lead to promotion that can produce mutable pointers. We rely + // on the promotion analysis not screwing up to ensure that it is sound to intern + // promoteds as immutable. + found_bad_mutable_pointer = true; + } if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { // Already interned. debug_assert!(!ecx.memory.alloc_map.contains_key(&alloc_id)); continue; } just_interned.insert(alloc_id); - intern_shallow(ecx, alloc_id, mutability, |ecx, prov| { - let alloc_id = prov.alloc_id(); - if intern_kind != InternKind::Promoted - && inner_mutability == Mutability::Not - && !prov.immutable() - { - if ecx.tcx.try_get_global_alloc(alloc_id).is_some() - && !just_interned.contains(&alloc_id) - { - // This is a pointer to some memory from another constant. We encounter mutable - // pointers to such memory since we do not always track immutability through - // these "global" pointers. Allowing them is harmless; the point of these checks - // during interning is to justify why we intern the *new* allocations immutably, - // so we can completely ignore existing allocations. We also don't need to add - // this to the todo list, since after all it is already interned. - return; - } - // Found a mutable pointer inside a const where inner allocations should be - // immutable. We exclude promoteds from this, since things like `&mut []` and - // `&None::>` lead to promotion that can produce mutable pointers. We rely - // on the promotion analysis not screwing up to ensure that it is sound to intern - // promoteds as immutable. - found_bad_mutable_pointer = true; - } - // We always intern with `inner_mutability`, and furthermore we ensured above that if - // that is "immutable", then there are *no* mutable pointers anywhere in the newly - // interned memory -- justifying that we can indeed intern immutably. However this also - // means we can *not* easily intern immutably here if `prov.immutable()` is true and - // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and - // we'd have to somehow check that they are *all* immutable before deciding that this - // allocation can be made immutable. In the future we could consider analyzing all - // pointers before deciding which allocations can be made immutable; but for now we are - // okay with losing some potential for immutability here. This can anyway only affect - // `static mut`. - todo.push((alloc_id, inner_mutability)); - }) - .map_err(|()| { + // We always intern with `inner_mutability`, and furthermore we ensured above that if + // that is "immutable", then there are *no* mutable pointers anywhere in the newly + // interned memory -- justifying that we can indeed intern immutably. However this also + // means we can *not* easily intern immutably here if `prov.immutable()` is true and + // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and + // we'd have to somehow check that they are *all* immutable before deciding that this + // allocation can be made immutable. In the future we could consider analyzing all + // pointers before deciding which allocations can be made immutable; but for now we are + // okay with losing some potential for immutability here. This can anyway only affect + // `static mut`. + todo.extend(intern_shallow(ecx, alloc_id, inner_mutability).map_err(|()| { ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) - })?; + })?); } if found_bad_mutable_pointer { return Err(ecx @@ -220,13 +223,13 @@ pub fn intern_const_alloc_for_constprop< return Ok(()); } // Move allocation to `tcx`. - intern_shallow(ecx, alloc_id, Mutability::Not, |_ecx, _| { + for _ in intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))? { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a // proper recursive interning loop -- or just call `intern_const_alloc_recursive`. panic!("`intern_const_alloc_for_constprop` called on allocation with nested provenance") - }) - .map_err(|()| err_ub!(DeadLocal).into()) + } + Ok(()) } impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> @@ -247,15 +250,14 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> let dest = self.allocate(layout, MemoryKind::Stack)?; f(self, &dest.clone().into())?; let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance - intern_shallow(self, alloc_id, Mutability::Not, |ecx, prov| { + for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a // proper recursive interning loop -- or just call `intern_const_alloc_recursive`. - if !ecx.tcx.try_get_global_alloc(prov.alloc_id()).is_some() { + if !self.tcx.try_get_global_alloc(prov.alloc_id()).is_some() { panic!("`intern_with_temp_alloc` with nested allocations"); } - }) - .unwrap(); + } Ok(alloc_id) } } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1e9e7d94596f8..7991f90b81549 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -85,6 +85,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( | ty::FnPtr(_) | ty::Dynamic(_, _, _) | ty::Closure(_, _) + | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index d48329b6c6946..f0f1008aba80b 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -246,13 +246,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); } let val = match null_op { - mir::NullOp::SizeOf => layout.size.bytes(), - mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::SizeOf => { + let val = layout.size.bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::AlignOf => { + let val = layout.align.abi.bytes(); + Scalar::from_target_usize(val, self) + } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(self, fields.iter()).bytes() + let val = layout.offset_of_subfield(self, fields.iter()).bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::DebugAssertions => { + // The checks hidden behind this are always better done by the interpreter + // itself, because it knows the runtime state better. + Scalar::from_bool(false) } }; - self.write_scalar(Scalar::from_target_usize(val, self), &dest)?; + self.write_scalar(val, &dest)?; } ShallowInitBox(ref operand, _) => { diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 7b993279f18e8..ff20fc5092c60 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -373,12 +373,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let (Some(caller), Some(callee)) = (pointee_ty(caller.ty)?, pointee_ty(callee.ty)?) { // This is okay if they have the same metadata type. let meta_ty = |ty: Ty<'tcx>| { - let (meta, only_if_sized) = ty.ptr_metadata_ty(*self.tcx, |ty| ty); - assert!( - !only_if_sized, - "there should be no more 'maybe has that metadata' types during interpretation" - ); - meta + // Even if `ty` is normalized, the search for the unsized tail will project + // to fields, which can yield non-normalized types. So we need to provide a + // normalization function. + let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); + ty.ptr_metadata_ty(*self.tcx, normalize) }; return Ok(meta_ty(caller) == meta_ty(callee)); } @@ -541,6 +540,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index b5cd32595201f..90cde81c01874 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -644,6 +644,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' | ty::Str | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) => Ok(false), // Some types only occur during typechecking, they have no layout. // We should not see them here and we could not check them anyway. @@ -992,10 +993,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Complain about any other kind of error -- those are bad because we'd like to // report them in a way that shows *where* in the value the issue lies. Err(err) => { - bug!( - "Unexpected Undefined Behavior error during validation: {}", - self.format_error(err) - ); + bug!("Unexpected error during validation: {}", self.format_error(err)); } } } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 946a49982aa1a..839cfd8d85acf 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -5,9 +5,9 @@ Rust MIR: a lowered representation of Rust. */ #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] #![feature(rustdoc_internals)] #![doc(rust_logo)] -#![deny(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 89c65d9232586..ee3f349c6b83c 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -20,7 +20,7 @@ use std::mem; use std::ops::{ControlFlow, Deref}; use super::ops::{self, NonConstOp, Status}; -use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; +use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; use super::resolver::FlowSensitiveAnalysis; use super::{ConstCx, Qualif}; use crate::const_eval::is_unstable_const_fn; @@ -149,37 +149,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let return_loc = ccx.body.terminator_loc(return_block); - let custom_eq = match ccx.const_kind() { - // We don't care whether a `const fn` returns a value that is not structurally - // matchable. Functions calls are opaque and always use type-based qualification, so - // this value should never be used. - hir::ConstContext::ConstFn => true, - - // If we know that all values of the return type are structurally matchable, there's no - // need to run dataflow. - // Opaque types do not participate in const generics or pattern matching, so we can safely count them out. - _ if ccx.body.return_ty().has_opaque_types() - || !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => - { - false - } - - hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => { - let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx) - .into_engine(ccx.tcx, ccx.body) - .iterate_to_fixpoint() - .into_results_cursor(ccx.body); - - cursor.seek_after_primary_effect(return_loc); - cursor.get().contains(RETURN_PLACE) - } - }; - ConstQualifs { needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc), needs_non_const_drop: self.needs_non_const_drop(ccx, RETURN_PLACE, return_loc), has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc), - custom_eq, tainted_by_errors, } } @@ -571,7 +544,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {} + Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, + _, + ) => {} Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, operand) => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 1efa52df5817b..67fef20807910 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::*; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty}; use rustc_trait_selection::traits::{ - self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, + ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, }; use super::ConstCx; @@ -24,7 +24,6 @@ pub fn in_any_value_of_ty<'tcx>( has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty), needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty), needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), - custom_eq: CustomEq::in_any_value_of_ty(cx, ty), tainted_by_errors, } } @@ -213,35 +212,6 @@ impl Qualif for NeedsNonConstDrop { } } -/// A constant that cannot be used as part of a pattern in a `match` expression. -pub struct CustomEq; - -impl Qualif for CustomEq { - const ANALYSIS_NAME: &'static str = "flow_custom_eq"; - - fn in_qualifs(qualifs: &ConstQualifs) -> bool { - qualifs.custom_eq - } - - fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - // If *any* component of a composite data type does not implement `Structural{Partial,}Eq`, - // we know that at least some values of that type are not structural-match. I say "some" - // because that component may be part of an enum variant (e.g., - // `Option::::Some`), in which case some values of this type may be - // structural-match (`Option::None`). - traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some() - } - - fn in_adt_inherently<'tcx>( - cx: &ConstCx<'_, 'tcx>, - def: AdtDef<'tcx>, - args: GenericArgsRef<'tcx>, - ) -> bool { - let ty = Ty::new_adt(cx.tcx, def, args); - !ty.is_structural_eq_shallow(cx.tcx) - } -} - // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. /// Returns `true` if this `Rvalue` contains qualif `Q`. diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 21bdb66a27631..5ce6a71c4bdd5 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -58,7 +58,10 @@ impl<'tcx> MirPass<'tcx> for Validator { let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), ty::Closure(..) => Abi::RustCall, + ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + // No need to do MIR validation on error bodies + ty::Error(_) => return, _ => { span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase) } @@ -665,6 +668,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; check_equal(self, location, f_ty); } + ty::CoroutineClosure(_, args) => { + let args = args.as_coroutine_closure(); + let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else { + fail_out_of_bounds(self, location); + return; + }; + check_equal(self, location, f_ty); + } &ty::Coroutine(def_id, args) => { let f_ty = if let Some(var) = parent_ty.variant_index { let gen_body = if def_id == self.body.source.def_id() { @@ -861,6 +872,20 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } + AggregateKind::CoroutineClosure(_, args) => { + let upvars = args.as_coroutine_closure().upvar_tys(); + if upvars.len() != fields.len() { + self.fail( + location, + "coroutine-closure has the wrong number of initialized fields", + ); + } + for (src, dest) in std::iter::zip(fields, upvars) { + if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) { + self.fail(location, "coroutine-closure field has the wrong type"); + } + } + } }, Rvalue::Ref(_, BorrowKind::Fake, _) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { @@ -1116,7 +1141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::DebugAssertions, _) | Rvalue::Discriminant(_) => {} } self.super_rvalue(rvalue, location); diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 976e42ad76836..2b80623ab4545 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -51,6 +51,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 08aa68ca54a7a..0635d8552ae55 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -11,7 +11,7 @@ either = "1.0" elsa = "=1.7.1" ena = "0.14.2" indexmap = { version = "2.0.0" } -jobserver_crate = { version = "0.1.27", package = "jobserver" } +jobserver_crate = { version = "0.1.28", package = "jobserver" } libc = "0.2" measureme = "11" rustc-hash = "1.1.0" diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs index 412e33aaa6551..89088bc5c1b87 100644 --- a/compiler/rustc_data_structures/src/jobserver.rs +++ b/compiler/rustc_data_structures/src/jobserver.rs @@ -23,7 +23,10 @@ static GLOBAL_CLIENT: LazyLock> = LazyLock::new(|| { if matches!( error.kind(), - FromEnvErrorKind::NoEnvVar | FromEnvErrorKind::NoJobserver | FromEnvErrorKind::Unsupported + FromEnvErrorKind::NoEnvVar + | FromEnvErrorKind::NoJobserver + | FromEnvErrorKind::NegativeFd + | FromEnvErrorKind::Unsupported ) { return Ok(default_client()); } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 563d8501890ce..2b799d6f5d3b8 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -11,8 +11,6 @@ #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![cfg_attr(not(parallel_compiler), feature(cell_leak))] -#![deny(rustc::diagnostic_outside_of_impl)] -#![deny(rustc::untranslatable_diagnostic)] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] @@ -148,7 +146,7 @@ pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl Printer { f } } -// See comments in src/librustc_middle/lib.rs +// See comments in compiler/rustc_middle/src/tests.rs #[doc(hidden)] pub fn __noop_fix_for_27438() {} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 5903c43ae98af..60f11b1bdd490 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -12,8 +12,6 @@ #![feature(let_chains)] #![feature(panic_update_hook)] #![feature(result_flattening)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -24,7 +22,9 @@ use rustc_data_structures::profiling::{ get_resident_set_size, print_time_passes_entry, TimePassesFormat, }; use rustc_errors::registry::Registry; -use rustc_errors::{markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, PResult}; +use rustc_errors::{ + markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult, +}; use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; @@ -1231,11 +1231,10 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { /// The compiler currently unwinds with a special sentinel value to abort /// compilation on fatal errors. This function catches that sentinel and turns /// the panic into a `Result` instead. -pub fn catch_fatal_errors R, R>(f: F) -> Result { +pub fn catch_fatal_errors R, R>(f: F) -> Result { catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { if value.is::() { - #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + FatalError } else { panic::resume_unwind(value); } @@ -1245,9 +1244,9 @@ pub fn catch_fatal_errors R, R>(f: F) -> Result interface::Result<()>) -> i32 { - match catch_fatal_errors(f).flatten() { - Ok(()) => EXIT_SUCCESS, - Err(_) => EXIT_FAILURE, + match catch_fatal_errors(f) { + Ok(Ok(())) => EXIT_SUCCESS, + _ => EXIT_FAILURE, } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0091.md b/compiler/rustc_error_codes/src/error_codes/E0091.md index 03cb32803715e..3bf4e907ecb1f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0091.md +++ b/compiler/rustc_error_codes/src/error_codes/E0091.md @@ -1,11 +1,11 @@ -An unnecessary type or const parameter was given in a type alias. +An unnecessary type parameter was given in a type alias. Erroneous code example: ```compile_fail,E0091 -type Foo = u32; // error: type parameter `T` is unused +type Foo = u32; // error: type parameter `T` is never used // or: -type Foo = Box; // error: type parameter `B` is unused +type Foo = Box; // error: type parameter `B` is never used ``` Please check you didn't write too many parameters. Example: diff --git a/compiler/rustc_error_codes/src/error_codes/E0264.md b/compiler/rustc_error_codes/src/error_codes/E0264.md index d790607622992..33ddf3405acca 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0264.md +++ b/compiler/rustc_error_codes/src/error_codes/E0264.md @@ -13,7 +13,7 @@ extern "C" { ``` A list of available external lang items is available in -`src/librustc_middle/middle/weak_lang_items.rs`. Example: +`compiler/rustc_hir/src/weak_lang_items.rs`. Example: ``` #![feature(lang_items)] diff --git a/compiler/rustc_error_codes/src/error_codes/E0724.md b/compiler/rustc_error_codes/src/error_codes/E0724.md index 70578acbe0d5f..bcefd0a74798b 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0724.md +++ b/compiler/rustc_error_codes/src/error_codes/E0724.md @@ -1,9 +1,12 @@ +#### Note: this error code is no longer emitted by the compiler. + + `#[ffi_returns_twice]` was used on something other than a foreign function declaration. Erroneous code example: -```compile_fail,E0724 +```compile_fail #![feature(ffi_returns_twice)] #![crate_type = "lib"] @@ -15,7 +18,7 @@ pub fn foo() {} For example, we might correct the previous example by declaring the function inside of an `extern` block. -``` +```compile_fail #![feature(ffi_returns_twice)] extern "C" { diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 5b2766618fccb..da688e385aa09 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -5,8 +5,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![deny(rustdoc::invalid_codeblock_attributes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] // This higher-order macro defines the error codes that are in use. It is used // in the `rustc_errors` crate. Removed error codes are listed in the comment diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 8fd7c5764797e..e174cba7813f5 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -3,8 +3,6 @@ #![feature(lazy_cell)] #![feature(rustc_attrs)] #![feature(type_alias_impl_trait)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] @@ -378,7 +376,7 @@ impl From> for DiagnosticMessage { } } -/// A workaround for "good path" ICEs when formatting types in disabled lints. +/// A workaround for good_path_delayed_bug ICEs when formatting types in disabled lints. /// /// Delays formatting until `.into(): DiagnosticMessage` is used. pub struct DelayDm(pub F); diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 949f52ef6b586..37f568f12a797 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -44,15 +44,15 @@ impl Translate for AnnotateSnippetEmitter { impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { let fluent_args = to_fluent_args(diag.args()); - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); + let mut suggestions = diag.suggestions.unwrap_or(vec![]); + self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &mut primary_span, - &mut children, + &mut diag.span, + &mut diag.children, &diag.level, self.macro_backtrace, ); @@ -62,9 +62,9 @@ impl Emitter for AnnotateSnippetEmitter { &diag.messages, &fluent_args, &diag.code, - &primary_span, - &children, - suggestions, + &diag.span, + &diag.children, + &suggestions, ); } @@ -85,7 +85,11 @@ fn source_string(file: Lrc, line: &Line) -> String { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error, + Level::Bug + | Level::Fatal + | Level::Error + | Level::DelayedBug + | Level::GoodPathDelayedBug => AnnotationType::Error, Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning, Level::Note | Level::OnceNote => AnnotationType::Note, Level::Help | Level::OnceHelp => AnnotationType::Help, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index bf1ab37a1cf48..03717a4d654c7 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,8 +1,7 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, - ErrCode, Level, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, - SuggestionStyle, + CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, ErrCode, Level, + MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_error_messages::fluent_value_from_str_list_sep_by_and; @@ -33,7 +32,10 @@ pub type DiagnosticArgName = Cow<'static, str>; #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DiagnosticArgValue { Str(Cow<'static, str>), - Number(i128), + // This gets converted to a `FluentNumber`, which is an `f64`. An `i32` + // safely fits in an `f64`. Any integers bigger than that will be converted + // to strings in `into_diagnostic_arg` and stored using the `Str` variant. + Number(i32), StrListSepByAnd(Vec>), } @@ -75,11 +77,12 @@ where /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used /// (to optionally perform eager translation). - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F); } +pub trait SubdiagnosticMessageOp = + Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; + /// Trait implemented by lint types. This should not be implemented manually. Instead, use /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. #[rustc_diagnostic_item = "DecorateLint"] @@ -109,13 +112,11 @@ pub struct Diagnostic { /// `span` if there is one. Otherwise, it is `DUMMY_SP`. pub sort_span: Span, - /// If diagnostic is from Lint, custom hash function ignores children. - /// Otherwise hash is based on the all the fields. pub is_lint: Option, /// With `-Ztrack_diagnostics` enabled, /// we print where in rustc this error was emitted. - pub emitted_at: DiagnosticLocation, + pub(crate) emitted_at: DiagnosticLocation, } #[derive(Clone, Debug, Encodable, Decodable)] @@ -164,10 +165,10 @@ impl DiagnosticStyledString { DiagnosticStyledString(vec![]) } pub fn push_normal>(&mut self, t: S) { - self.0.push(StringPart::Normal(t.into())); + self.0.push(StringPart::normal(t)); } pub fn push_highlighted>(&mut self, t: S) { - self.0.push(StringPart::Highlighted(t.into())); + self.0.push(StringPart::highlighted(t)); } pub fn push>(&mut self, t: S, highlight: bool) { if highlight { @@ -177,35 +178,34 @@ impl DiagnosticStyledString { } } pub fn normal>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::Normal(t.into())]) + DiagnosticStyledString(vec![StringPart::normal(t)]) } pub fn highlighted>(t: S) -> DiagnosticStyledString { - DiagnosticStyledString(vec![StringPart::Highlighted(t.into())]) + DiagnosticStyledString(vec![StringPart::highlighted(t)]) } pub fn content(&self) -> String { - self.0.iter().map(|x| x.content()).collect::() + self.0.iter().map(|x| x.content.as_str()).collect::() } } #[derive(Debug, PartialEq, Eq)] -pub enum StringPart { - Normal(String), - Highlighted(String), +pub struct StringPart { + content: String, + style: Style, } impl StringPart { - pub fn content(&self) -> &str { - match self { - &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s, - } + pub fn normal>(content: S) -> StringPart { + StringPart { content: content.into(), style: Style::NoStyle } + } + + pub fn highlighted>(content: S) -> StringPart { + StringPart { content: content.into(), style: Style::Highlight } } } -// Note: most of these methods are setters that return `&mut Self`. The small -// number of simple getter functions all have `get_` prefixes to distinguish -// them from the setters. impl Diagnostic { #[track_caller] pub fn new>(level: Level, message: M) -> Self { @@ -235,19 +235,16 @@ impl Diagnostic { pub fn is_error(&self) -> bool { match self.level { - Level::Bug - | Level::DelayedBug(DelayedBugKind::Normal) - | Level::Fatal - | Level::Error - | Level::FailureNote => true, + Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true, - Level::ForceWarning(_) + Level::GoodPathDelayedBug + | Level::ForceWarning(_) | Level::Warning - | Level::DelayedBug(DelayedBugKind::GoodPath) | Level::Note | Level::OnceNote | Level::Help | Level::OnceHelp + | Level::FailureNote | Level::Allow | Level::Expect(_) => false, } @@ -306,11 +303,11 @@ impl Diagnostic { #[track_caller] pub fn downgrade_to_delayed_bug(&mut self) { assert!( - self.is_error(), + matches!(self.level, Level::Error | Level::DelayedBug), "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", self.level ); - self.level = Level::DelayedBug(DelayedBugKind::Normal); + self.level = Level::DelayedBug; } /// Appends a labeled span to the diagnostic. @@ -391,19 +388,16 @@ impl Diagnostic { } else { (0, found_label.len() - expected_label.len()) }; - let mut msg: Vec<_> = - vec![(format!("{}{} `", " ".repeat(expected_padding), expected_label), Style::NoStyle)]; - msg.extend(expected.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push((format!("`{expected_extra}\n"), Style::NoStyle)); - msg.push((format!("{}{} `", " ".repeat(found_padding), found_label), Style::NoStyle)); - msg.extend(found.0.iter().map(|x| match *x { - StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), - StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), - })); - msg.push((format!("`{found_extra}"), Style::NoStyle)); + let mut msg = vec![StringPart::normal(format!( + "{}{} `", + " ".repeat(expected_padding), + expected_label + ))]; + msg.extend(expected.0.into_iter()); + msg.push(StringPart::normal(format!("`{expected_extra}\n"))); + msg.push(StringPart::normal(format!("{}{} `", " ".repeat(found_padding), found_label))); + msg.extend(found.0.into_iter()); + msg.push(StringPart::normal(format!("`{found_extra}"))); // For now, just attach these as notes. self.highlighted_note(msg); @@ -412,9 +406,9 @@ impl Diagnostic { pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self { self.highlighted_note(vec![ - (format!("`{name}` from trait: `"), Style::NoStyle), - (signature, Style::Highlight), - ("`".to_string(), Style::NoStyle), + StringPart::normal(format!("`{name}` from trait: `")), + StringPart::highlighted(signature), + StringPart::normal("`"), ]); self } @@ -426,10 +420,7 @@ impl Diagnostic { self } - fn highlighted_note>( - &mut self, - msg: Vec<(M, Style)>, - ) -> &mut Self { + fn highlighted_note(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Note, msg, MultiSpan::new()); self } @@ -498,7 +489,7 @@ impl Diagnostic { } /// Add a help message attached to this diagnostic with a customizable highlighted message. - pub fn highlighted_help(&mut self, msg: Vec<(String, Style)>) -> &mut Self { + pub fn highlighted_help(&mut self, msg: Vec) -> &mut Self { self.sub_with_highlights(Level::Help, msg, MultiSpan::new()); self } @@ -892,15 +883,6 @@ impl Diagnostic { self } - pub fn clear_code(&mut self) -> &mut Self { - self.code = None; - self - } - - pub fn get_code(&self) -> Option { - self.code - } - pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { self.messages[0] = (msg.into(), Style::NoStyle); self @@ -915,7 +897,7 @@ impl Diagnostic { pub fn arg( &mut self, - name: impl Into>, + name: impl Into, arg: impl IntoDiagnosticArg, ) -> &mut Self { self.args.insert(name.into(), arg.into_diagnostic_arg()); @@ -926,10 +908,6 @@ impl Diagnostic { self.args = args; } - pub fn messages(&self) -> &[(DiagnosticMessage, Style)] { - &self.messages - } - /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by /// combining it with the primary message of the diagnostic (if translatable, otherwise it just /// passes the user's string along). @@ -960,15 +938,10 @@ impl Diagnostic { /// Convenience function for internal use, clients should use one of the /// public methods above. - fn sub_with_highlights>( - &mut self, - level: Level, - messages: Vec<(M, Style)>, - span: MultiSpan, - ) { + fn sub_with_highlights(&mut self, level: Level, messages: Vec, span: MultiSpan) { let messages = messages .into_iter() - .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.0), m.1)) + .map(|m| (self.subdiagnostic_message_to_diagnostic_message(m.content), m.style)) .collect(); let sub = SubDiagnostic { level, messages, span }; self.children.push(sub); @@ -980,22 +953,24 @@ impl Diagnostic { ) -> ( &Level, &[(DiagnosticMessage, Style)], - Vec<(&Cow<'static, str>, &DiagnosticArgValue)>, &Option, - &Option, &MultiSpan, + &[SubDiagnostic], &Result, SuggestionsDisabled>, - Option<&[SubDiagnostic]>, + Vec<(&DiagnosticArgName, &DiagnosticArgValue)>, + &Option, ) { ( &self.level, &self.messages, - self.args().collect(), &self.code, - &self.is_lint, &self.span, + &self.children, &self.suggestions, - (if self.is_lint.is_some() { None } else { Some(&self.children) }), + self.args().collect(), + // omit self.sort_span + &self.is_lint, + // omit self.emitted_at ) } } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 8bfb181648628..e484bef0e0bc9 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -99,16 +99,20 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } /// `ErrorGuaranteed::emit_producing_guarantee` uses this. - // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { let diag = self.take_diag(); - // Only allow a guarantee if the `level` wasn't switched to a - // non-error. The field isn't `pub`, but the whole `Diagnostic` can be - // overwritten with a new one, thanks to `DerefMut`. + // The only error levels that produce `ErrorGuaranteed` are + // `Error` and `DelayedBug`. But `DelayedBug` should never occur here + // because delayed bugs have their level changed to `Bug` when they are + // actually printed, so they produce an ICE. + // + // (Also, even though `level` isn't `pub`, the whole `Diagnostic` could + // be overwritten with a new one thanks to `DerefMut`. So this assert + // protects against that, too.) assert!( - diag.is_error(), - "emitted non-error ({:?}) diagnostic from `DiagnosticBuilder`", + matches!(diag.level, Level::Error | Level::DelayedBug), + "invalid diagnostic level ({:?})", diag.level, ); @@ -255,13 +259,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Stashes diagnostic for possible later improvement in a different, /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. - pub fn stash(self, span: Span, key: StashKey) { - self.dcx.stash_diagnostic(span, key, self.into_diagnostic()); - } - - /// Converts the builder to a `Diagnostic` for later emission. - pub fn into_diagnostic(mut self) -> Diagnostic { - self.take_diag() + pub fn stash(mut self, span: Span, key: StashKey) { + self.dcx.stash_diagnostic(span, key, self.take_diag()); } /// Delay emission of this diagnostic as a bug. diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index faab3fc663a82..e936ebc7185fa 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -2,7 +2,7 @@ use crate::diagnostic::DiagnosticLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; use crate::{ DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic, - IntoDiagnosticArg, Level, + IntoDiagnosticArg, Level, SubdiagnosticMessageOp, }; use rustc_ast as ast; use rustc_ast_pretty::pprust; @@ -63,12 +63,8 @@ macro_rules! into_diagnostic_arg_for_number { $( impl IntoDiagnosticArg for $ty { fn into_diagnostic_arg(self) -> DiagnosticArgValue { - // HACK: `FluentNumber` the underline backing struct represent - // numbers using a f64 which can't represent all the i128 numbers - // So in order to be able to use fluent selectors and still - // have all the numbers representable we only convert numbers - // below a certain threshold. - if let Ok(n) = TryInto::::try_into(self) && n >= -100 && n <= 100 { + // Convert to a string if it won't fit into `Number`. + if let Ok(n) = TryInto::::try_into(self) { DiagnosticArgValue::Number(n) } else { self.to_string().into_diagnostic_arg() @@ -303,7 +299,7 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl AddToDiagnostic for SingleLabelManySpans { - fn add_to_diagnostic_with(self, diag: &mut crate::Diagnostic, _: F) { + fn add_to_diagnostic_with(self, diag: &mut crate::Diagnostic, _: F) { diag.span_labels(self.spans, self.label); } } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 9f76c1dd248b0..b9e92dbb31c64 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -193,7 +193,7 @@ pub type DynEmitter = dyn Emitter + DynSend; /// Emitter trait for emitting errors. pub trait Emitter: Translate { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, diag: &Diagnostic); + fn emit_diagnostic(&mut self, diag: Diagnostic); /// Emit a notification that an artifact has been output. /// Currently only supported for the JSON format. @@ -230,17 +230,17 @@ pub trait Emitter: Translate { /// /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, /// we format the `help` suggestion depending on the content of the - /// substitutions. In that case, we return the modified span only. + /// substitutions. In that case, we modify the span and clear the + /// suggestions. /// /// * If the current `Diagnostic` has multiple suggestions, - /// we return the original `primary_span` and the original suggestions. - fn primary_span_formatted<'a>( + /// we leave `primary_span` and the suggestions untouched. + fn primary_span_formatted( &mut self, - diag: &'a Diagnostic, + primary_span: &mut MultiSpan, + suggestions: &mut Vec, fluent_args: &FluentArgs<'_>, - ) -> (MultiSpan, &'a [CodeSuggestion]) { - let mut primary_span = diag.span.clone(); - let suggestions = diag.suggestions.as_deref().unwrap_or(&[]); + ) { if let Some((sugg, rest)) = suggestions.split_first() { let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap(); if rest.is_empty() && @@ -287,16 +287,15 @@ pub trait Emitter: Translate { primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); // We return only the modified primary_span - (primary_span, &[]) + suggestions.clear(); } else { // if there are multiple suggestions, print them all in full // to be consistent. We could try to figure out if we can // make one (or the first one) inline, but that would give // undue importance to a semi-random suggestion - (primary_span, suggestions) } } else { - (primary_span, suggestions) + // do nothing } } @@ -518,16 +517,15 @@ impl Emitter for HumanEmitter { self.sm.as_ref() } - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { let fluent_args = to_fluent_args(diag.args()); - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); - debug!("emit_diagnostic: suggestions={:?}", suggestions); + let mut suggestions = diag.suggestions.unwrap_or(vec![]); + self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &mut primary_span, - &mut children, + &mut diag.span, + &mut diag.children, &diag.level, self.macro_backtrace, ); @@ -537,9 +535,9 @@ impl Emitter for HumanEmitter { &diag.messages, &fluent_args, &diag.code, - &primary_span, - &children, - suggestions, + &diag.span, + &diag.children, + &suggestions, self.track_diagnostics.then_some(&diag.emitted_at), ); } @@ -558,7 +556,7 @@ impl Emitter for HumanEmitter { /// failures of rustc, as witnessed e.g. in issue #89358. pub struct SilentEmitter { pub fatal_dcx: DiagCtxt, - pub fatal_note: Option, + pub fatal_note: String, } impl Translate for SilentEmitter { @@ -576,13 +574,10 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, d: &Diagnostic) { - if d.level == Level::Fatal { - let mut d = d.clone(); - if let Some(ref note) = self.fatal_note { - d.note(note.clone()); - } - self.fatal_dcx.emit_diagnostic(d); + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { + if diag.level == Level::Fatal { + diag.note(self.fatal_note.clone()); + self.fatal_dcx.emit_diagnostic(diag); } } } @@ -2118,6 +2113,7 @@ impl HumanEmitter { } if !self.short_message { for child in children { + assert!(child.level.can_be_top_or_sub().1); let span = &child.span; if let Err(err) = self.emit_messages_default_inner( span, diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 6f92299827950..470e3d52452cf 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -176,7 +176,7 @@ impl Translate for JsonEmitter { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) { + fn emit_diagnostic(&mut self, diag: crate::Diagnostic) { let data = Diagnostic::from_errors_diagnostic(diag, self); let result = self.emit(EmitTyped::Diagnostic(data)); if let Err(e) = result { @@ -201,7 +201,7 @@ impl Emitter for JsonEmitter { } FutureBreakageItem { diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( - &diag, self, + diag, self, )), } }) @@ -340,7 +340,7 @@ struct UnusedExterns<'a, 'b, 'c> { } impl Diagnostic { - fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { + fn from_errors_diagnostic(diag: crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { let args = to_fluent_args(diag.args()); let sugg = diag.suggestions.iter().flatten().map(|sugg| { let translated_message = @@ -382,6 +382,28 @@ impl Diagnostic { Ok(()) } } + + let translated_message = je.translate_messages(&diag.messages, &args); + + let code = if let Some(code) = diag.code { + Some(DiagnosticCode { + code: code.to_string(), + explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), + }) + } else if let Some(IsLint { name, .. }) = &diag.is_lint { + Some(DiagnosticCode { code: name.to_string(), explanation: None }) + } else { + None + }; + let level = diag.level.to_str(); + let spans = DiagnosticSpan::from_multispan(&diag.span, &args, je); + let children = diag + .children + .iter() + .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) + .chain(sugg) + .collect(); + let buf = BufWriter::default(); let output = buf.clone(); je.json_rendered @@ -398,30 +420,12 @@ impl Diagnostic { let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); - let translated_message = je.translate_messages(&diag.messages, &args); - - let code = if let Some(code) = diag.code { - Some(DiagnosticCode { - code: code.to_string(), - explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), - }) - } else if let Some(IsLint { name, .. }) = &diag.is_lint { - Some(DiagnosticCode { code: name.to_string(), explanation: None }) - } else { - None - }; - Diagnostic { message: translated_message.to_string(), code, - level: diag.level.to_str(), - spans: DiagnosticSpan::from_multispan(&diag.span, &args, je), - children: diag - .children - .iter() - .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) - .chain(sugg) - .collect(), + level, + spans, + children, rendered: Some(output), } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9090adea1562d..7216fa8f5e4f6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,6 +5,8 @@ // tidy-alphabetical-start #![allow(incomplete_features)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] @@ -19,6 +21,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] // tidy-alphabetical-end @@ -34,7 +37,8 @@ extern crate self as rustc_errors; pub use codes::*; pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName, - DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, + DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, StringPart, SubDiagnostic, + SubdiagnosticMessageOp, }; pub use diagnostic_builder::{ BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic, @@ -102,7 +106,6 @@ pub type PResult<'a, T> = Result>; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // `PResult` is used a lot. Make sure it doesn't unintentionally get bigger. -// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.) #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16); #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] @@ -430,6 +433,10 @@ struct DiagCtxtInner { /// The number of non-lint errors that have been emitted, including duplicates. err_count: usize, + /// The number of stashed errors. Unlike the other counts, this can go up + /// and down, so it doesn't guarantee anything. + stashed_err_count: usize, + /// The error count shown to the user at the end. deduplicated_err_count: usize, /// The warning count shown to the user at the end. @@ -440,7 +447,7 @@ struct DiagCtxtInner { has_printed: bool, emitter: Box, - span_delayed_bugs: Vec, + delayed_bugs: Vec, good_path_delayed_bugs: Vec, /// This flag indicates that an expected diagnostic was emitted and suppressed. /// This is used for the `good_path_delayed_bugs` check. @@ -514,6 +521,7 @@ pub enum StashKey { MaybeForgetReturn, /// Query cycle detected, stashing in favor of a better error. Cycle, + UndeterminedMacroResolution, } fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { @@ -523,8 +531,7 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { pub static TRACK_DIAGNOSTIC: AtomicRef = AtomicRef::new(&(default_track_diagnostic as _)); -#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] -pub enum DelayedBugKind { +enum DelayedBugKind { Normal, GoodPath, } @@ -557,11 +564,6 @@ impl Drop for DiagCtxtInner { self.flush_delayed(DelayedBugKind::Normal) } - // FIXME(eddyb) this explains what `good_path_delayed_bugs` are! - // They're `span_delayed_bugs` but for "require some diagnostic happened" - // instead of "require some error happened". Sadly that isn't ideal, as - // lints can be `#[allow]`'d, potentially leading to this triggering. - // Also, "good path" should be replaced with a better naming. if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() { self.flush_delayed(DelayedBugKind::GoodPath); } @@ -604,11 +606,12 @@ impl DiagCtxt { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, lint_err_count: 0, err_count: 0, + stashed_err_count: 0, deduplicated_err_count: 0, deduplicated_warn_count: 0, has_printed: false, emitter, - span_delayed_bugs: Vec::new(), + delayed_bugs: Vec::new(), good_path_delayed_bugs: Vec::new(), suppressed_expected_diag: false, taught_diagnostics: Default::default(), @@ -645,7 +648,8 @@ impl DiagCtxt { } // This is here to not allow mutation of flags; - // as of this writing it's only used in tests in librustc_middle. + // as of this writing it's used in Session::consider_optimizing and + // in tests in rustc_interface. pub fn can_emit_warnings(&self) -> bool { self.inner.borrow_mut().flags.can_emit_warnings } @@ -659,12 +663,13 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); inner.lint_err_count = 0; inner.err_count = 0; + inner.stashed_err_count = 0; inner.deduplicated_err_count = 0; inner.deduplicated_warn_count = 0; inner.has_printed = false; // actually free the underlying memory (which `clear` would not do) - inner.span_delayed_bugs = Default::default(); + inner.delayed_bugs = Default::default(); inner.good_path_delayed_bugs = Default::default(); inner.taught_diagnostics = Default::default(); inner.emitted_diagnostic_codes = Default::default(); @@ -680,10 +685,8 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if diag.is_lint.is_some() { - inner.lint_err_count += 1; - } else { - inner.err_count += 1; + if diag.is_lint.is_none() { + inner.stashed_err_count += 1; } } @@ -699,10 +702,8 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if diag.is_lint.is_some() { - inner.lint_err_count -= 1; - } else { - inner.err_count -= 1; + if diag.is_lint.is_none() { + inner.stashed_err_count -= 1; } } Some(DiagnosticBuilder::new_diagnostic(self, diag)) @@ -713,7 +714,7 @@ impl DiagCtxt { } /// Emit all stashed diagnostics. - pub fn emit_stashed_diagnostics(&self) -> Option { + pub fn emit_stashed_diagnostics(&self) { self.inner.borrow_mut().emit_stashed_diagnostics() } @@ -850,6 +851,7 @@ impl DiagCtxt { self.struct_span_warn(span, msg).emit() } + #[track_caller] pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { self.struct_span_bug(span, msg).emit() } @@ -865,8 +867,7 @@ impl DiagCtxt { /// directly). #[track_caller] pub fn delayed_bug(&self, msg: impl Into) -> ErrorGuaranteed { - DiagnosticBuilder::::new(self, DelayedBug(DelayedBugKind::Normal), msg) - .emit() + DiagnosticBuilder::::new(self, DelayedBug, msg).emit() } /// Like `delayed_bug`, but takes an additional span. @@ -879,15 +880,12 @@ impl DiagCtxt { sp: impl Into, msg: impl Into, ) -> ErrorGuaranteed { - DiagnosticBuilder::::new(self, DelayedBug(DelayedBugKind::Normal), msg) - .with_span(sp) - .emit() + DiagnosticBuilder::::new(self, DelayedBug, msg).with_span(sp).emit() } - // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's - // where the explanation of what "good path" is (also, it should be renamed). + /// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`. pub fn good_path_delayed_bug(&self, msg: impl Into) { - DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit() + DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit() } #[track_caller] @@ -931,40 +929,52 @@ impl DiagCtxt { self.struct_bug(msg).emit() } - /// This excludes lint errors and delayed bugs. + /// This excludes lint errors, delayed bugs, and stashed errors. #[inline] pub fn err_count(&self) -> usize { self.inner.borrow().err_count } - /// This excludes lint errors and delayed bugs. + /// This excludes normal errors, lint errors and delayed bugs. Unless + /// absolutely necessary, avoid using this. It's dubious because stashed + /// errors can later be cancelled, so the presence of a stashed error at + /// some point of time doesn't guarantee anything -- there are no + /// `ErrorGuaranteed`s here. + pub fn stashed_err_count(&self) -> usize { + self.inner.borrow().stashed_err_count + } + + /// This excludes lint errors, delayed bugs, and stashed errors. pub fn has_errors(&self) -> Option { self.inner.borrow().has_errors().then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } - /// This excludes delayed bugs. Unless absolutely necessary, prefer - /// `has_errors` to this method. + /// This excludes delayed bugs and stashed errors. Unless absolutely + /// necessary, prefer `has_errors` to this method. pub fn has_errors_or_lint_errors(&self) -> Option { let inner = self.inner.borrow(); let result = inner.has_errors() || inner.lint_err_count > 0; result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } - /// Unless absolutely necessary, prefer `has_errors` or - /// `has_errors_or_lint_errors` to this method. + /// This excludes stashed errors. Unless absolutely necessary, prefer + /// `has_errors` or `has_errors_or_lint_errors` to this method. pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option { let inner = self.inner.borrow(); let result = - inner.has_errors() || inner.lint_err_count > 0 || !inner.span_delayed_bugs.is_empty(); + inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty(); result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } @@ -990,9 +1000,13 @@ impl DiagCtxt { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => inner - .emitter - .emit_diagnostic(&Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))), + (0, _) => { + // Use `inner.emitter` directly, otherwise the warning might not be emitted, e.g. + // with a configuration like `--cap-lints allow --force-warn bare_trait_objects`. + inner + .emitter + .emit_diagnostic(Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))); + } (_, 0) => { inner.emit_diagnostic(Diagnostic::new(Fatal, errors)); } @@ -1038,10 +1052,6 @@ impl DiagCtxt { } } - pub fn take_future_breakage_diagnostics(&self) -> Vec { - std::mem::take(&mut self.inner.borrow_mut().future_breakage_diagnostics) - } - pub fn abort_if_errors(&self) { let mut inner = self.inner.borrow_mut(); inner.emit_stashed_diagnostics(); @@ -1060,7 +1070,7 @@ impl DiagCtxt { } pub fn force_print_diagnostic(&self, db: Diagnostic) { - self.inner.borrow_mut().emitter.emit_diagnostic(&db); + self.inner.borrow_mut().emitter.emit_diagnostic(db); } pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option { @@ -1149,8 +1159,12 @@ impl DiagCtxt { self.inner.borrow_mut().emitter.emit_artifact_notification(path, artifact_type); } - pub fn emit_future_breakage_report(&self, diags: Vec) { - self.inner.borrow_mut().emitter.emit_future_breakage_report(diags) + pub fn emit_future_breakage_report(&self) { + let mut inner = self.inner.borrow_mut(); + let diags = std::mem::take(&mut inner.future_breakage_diagnostics); + if !diags.is_empty() { + inner.emitter.emit_future_breakage_report(diags); + } } pub fn emit_unused_externs( @@ -1221,17 +1235,13 @@ impl DiagCtxt { // `DiagCtxtInner::foo`. impl DiagCtxtInner { /// Emit all stashed diagnostics. - fn emit_stashed_diagnostics(&mut self) -> Option { + fn emit_stashed_diagnostics(&mut self) { let has_errors = self.has_errors(); - let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::>(); - let mut reported = None; - for diag in diags { + for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if diag.is_lint.is_some() { - self.lint_err_count -= 1; - } else { - self.err_count -= 1; + if diag.is_lint.is_none() { + self.stashed_err_count -= 1; } } else { // Unless they're forced, don't flush stashed warnings when @@ -1241,52 +1251,25 @@ impl DiagCtxtInner { continue; } } - let reported_this = self.emit_diagnostic(diag); - reported = reported.or(reported_this); + self.emit_diagnostic(diag); } - reported } + // Return value is only `Some` if the level is `Error` or `DelayedBug`. fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { - // The `LintExpectationId` can be stable or unstable depending on when it was created. - // Diagnostics created before the definition of `HirId`s are unstable and can not yet - // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by - // a stable one by the `LintLevelsBuilder`. - if let Some(LintExpectationId::Unstable { .. }) = diagnostic.level.get_expectation_id() { - self.unstable_expect_diagnostics.push(diagnostic.clone()); - return None; - } - - // FIXME(eddyb) this should check for `has_errors` and stop pushing - // once *any* errors were emitted (and truncate `span_delayed_bugs` - // when an error is first emitted, also), but maybe there's a case - // in which that's not sound? otherwise this is really inefficient. - match diagnostic.level { - DelayedBug(_) if self.flags.eagerly_emit_delayed_bugs => { - diagnostic.level = Error; - } - DelayedBug(DelayedBugKind::Normal) => { - let backtrace = std::backtrace::Backtrace::capture(); - self.span_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); - - #[allow(deprecated)] - return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); - } - DelayedBug(DelayedBugKind::GoodPath) => { - let backtrace = std::backtrace::Backtrace::capture(); - self.good_path_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace)); + assert!(diagnostic.level.can_be_top_or_sub().0); + if let Some(expectation_id) = diagnostic.level.get_expectation_id() { + // The `LintExpectationId` can be stable or unstable depending on when it was created. + // Diagnostics created before the definition of `HirId`s are unstable and can not yet + // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by + // a stable one by the `LintLevelsBuilder`. + if let LintExpectationId::Unstable { .. } = expectation_id { + self.unstable_expect_diagnostics.push(diagnostic); return None; } - _ => {} - } - - // This must come after the possible promotion of `DelayedBug` to - // `Error` above. - if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { - diagnostic.level = Bug; + self.suppressed_expected_diag = true; + self.fulfilled_expectations.insert(expectation_id.normalize()); } if diagnostic.has_future_breakage() { @@ -1297,21 +1280,45 @@ impl DiagCtxtInner { self.future_breakage_diagnostics.push(diagnostic.clone()); } - if let Some(expectation_id) = diagnostic.level.get_expectation_id() { - self.suppressed_expected_diag = true; - self.fulfilled_expectations.insert(expectation_id.normalize()); + if matches!(diagnostic.level, DelayedBug | GoodPathDelayedBug) + && self.flags.eagerly_emit_delayed_bugs + { + diagnostic.level = Error; } - if diagnostic.level == Warning && !self.flags.can_emit_warnings { - if diagnostic.has_future_breakage() { + match diagnostic.level { + // This must come after the possible promotion of `DelayedBug`/`GoodPathDelayedBug` to + // `Error` above. + Fatal | Error if self.treat_next_err_as_bug() => { + diagnostic.level = Bug; + } + DelayedBug => { + // FIXME(eddyb) this should check for `has_errors` and stop pushing + // once *any* errors were emitted (and truncate `delayed_bugs` + // when an error is first emitted, also), but maybe there's a case + // in which that's not sound? otherwise this is really inefficient. + let backtrace = std::backtrace::Backtrace::capture(); + self.delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + #[allow(deprecated)] + return Some(ErrorGuaranteed::unchecked_error_guaranteed()); + } + GoodPathDelayedBug => { + let backtrace = std::backtrace::Backtrace::capture(); + self.good_path_delayed_bugs + .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + return None; + } + Warning if !self.flags.can_emit_warnings => { + if diagnostic.has_future_breakage() { + (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); + } + return None; + } + Allow | Expect(_) => { (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); + return None; } - return None; - } - - if matches!(diagnostic.level, Expect(_) | Allow) { - (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); - return None; + _ => {} } let mut guaranteed = None; @@ -1327,11 +1334,16 @@ impl DiagCtxtInner { !self.emitted_diagnostics.insert(diagnostic_hash) }; + let level = diagnostic.level; + let is_error = diagnostic.is_error(); + let is_lint = diagnostic.is_lint.is_some(); + // 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) { debug!(?diagnostic); debug!(?self.emitted_diagnostics); + let already_emitted_sub = |sub: &mut SubDiagnostic| { debug!(?sub); if sub.level != OnceNote && sub.level != OnceHelp { @@ -1343,7 +1355,6 @@ impl DiagCtxtInner { debug!(?diagnostic_hash); !self.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {}); if already_emitted { diagnostic.note( @@ -1351,26 +1362,28 @@ impl DiagCtxtInner { ); } - self.emitter.emit_diagnostic(&diagnostic); - if diagnostic.is_error() { + if is_error { self.deduplicated_err_count += 1; } else if matches!(diagnostic.level, ForceWarning(_) | Warning) { self.deduplicated_warn_count += 1; } self.has_printed = true; + + self.emitter.emit_diagnostic(diagnostic); } - if diagnostic.is_error() { - if diagnostic.is_lint.is_some() { + + if is_error { + if is_lint { self.lint_err_count += 1; } else { self.err_count += 1; } self.panic_if_treat_err_as_bug(); + } - #[allow(deprecated)] - { - guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); - } + #[allow(deprecated)] + if level == Level::Error { + guaranteed = Some(ErrorGuaranteed::unchecked_error_guaranteed()); } }); @@ -1399,12 +1412,12 @@ impl DiagCtxtInner { fn flush_delayed(&mut self, kind: DelayedBugKind) { let (bugs, note1) = match kind { DelayedBugKind::Normal => ( - std::mem::take(&mut self.span_delayed_bugs), - "no errors encountered even though `span_delayed_bug` issued", + std::mem::take(&mut self.delayed_bugs), + "no errors encountered even though delayed bugs were created", ), DelayedBugKind::GoodPath => ( std::mem::take(&mut self.good_path_delayed_bugs), - "no warnings or errors encountered even though `good_path_delayed_bugs` issued", + "no warnings or errors encountered even though good path delayed bugs were created", ), }; let note2 = "those delayed bugs will now be shown as internal compiler errors"; @@ -1423,7 +1436,7 @@ impl DiagCtxtInner { &mut out, "delayed span bug: {}\n{}\n", bug.inner - .messages() + .messages .iter() .filter_map(|(msg, _)| msg.as_str()) .collect::(), @@ -1443,8 +1456,8 @@ impl DiagCtxtInner { let mut bug = if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; - // "Undelay" the `DelayedBug`s (into plain `Bug`s). - if !matches!(bug.level, DelayedBug(_)) { + // "Undelay" the delayed bugs (into plain `Bug`s). + if !matches!(bug.level, DelayedBug | GoodPathDelayedBug) { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { @@ -1510,35 +1523,59 @@ impl DelayedDiagnostic { } } +/// Level is_error EmissionGuarantee Top-level Sub Used in lints? +/// ----- -------- ----------------- --------- --- -------------- +/// Bug yes BugAbort yes - - +/// Fatal yes FatalAbort/FatalError(*) yes - - +/// Error yes ErrorGuaranteed yes - yes +/// DelayedBug yes ErrorGuaranteed yes - - +/// GoodPathDelayedBug - () yes - - +/// ForceWarning - () yes - lint-only +/// Warning - () yes yes yes +/// Note - () rare yes - +/// OnceNote - () - yes lint-only +/// Help - () rare yes - +/// OnceHelp - () - yes lint-only +/// FailureNote - () rare - - +/// Allow - () yes - lint-only +/// Expect - () yes - lint-only +/// +/// (*) `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is +/// occasionally used. +/// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { /// For bugs in the compiler. Manifests as an ICE (internal compiler error) panic. - /// - /// Its `EmissionGuarantee` is `BugAbort`. Bug, - /// This is a strange one: lets you register an error without emitting it. If compilation ends - /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be - /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths - /// that should only be reached when compiling erroneous code. - /// - /// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for - /// `GoodPath` delayed bugs. - DelayedBug(DelayedBugKind), - /// An error that causes an immediate abort. Used for things like configuration errors, /// internal overflows, some file operation errors. - /// - /// Its `EmissionGuarantee` is `FatalAbort`, except in the non-aborting "almost fatal" case - /// that is occasionally used, where it is `FatalError`. Fatal, /// An error in the code being compiled, which prevents compilation from finishing. This is the /// most common case. - /// - /// Its `EmissionGuarantee` is `ErrorGuaranteed`. Error, + /// This is a strange one: lets you register an error without emitting it. If compilation ends + /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be + /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths + /// that should only be reached when compiling erroneous code. + DelayedBug, + + /// Like `DelayedBug`, but weaker: lets you register an error without emitting it. If + /// compilation ends without any other diagnostics being emitted (and without an expected lint + /// being suppressed), this will be emitted as a bug. Otherwise, it will be silently dropped. + /// I.e. "expect other diagnostics are emitted (or suppressed)" semantics. Useful on code paths + /// that should only be reached when emitting diagnostics, e.g. for expensive one-time + /// diagnostic formatting operations. + /// + /// FIXME(nnethercote) good path delayed bugs are semantically strange: if printed they produce + /// an ICE, but they don't satisfy `is_error` and they don't guarantee an error is emitted. + /// Plus there's the extra complication with expected (suppressed) lints. They have limited + /// use, and are used in very few places, and "good path" isn't a good name. It would be good + /// to remove them. + GoodPathDelayedBug, + /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation /// from finishing. /// @@ -1547,45 +1584,28 @@ pub enum Level { ForceWarning(Option), /// A warning about the code being compiled. Does not prevent compilation from finishing. - /// - /// Its `EmissionGuarantee` is `()`. Warning, - /// A message giving additional context. Rare, because notes are more commonly attached to other - /// diagnostics such as errors. - /// - /// Its `EmissionGuarantee` is `()`. + /// A message giving additional context. Note, - /// A note that is only emitted once. Rare, mostly used in circumstances relating to lints. - /// - /// Its `EmissionGuarantee` is `()`. + /// A note that is only emitted once. OnceNote, - /// A message suggesting how to fix something. Rare, because help messages are more commonly - /// attached to other diagnostics such as errors. - /// - /// Its `EmissionGuarantee` is `()`. + /// A message suggesting how to fix something. Help, - /// A help that is only emitted once. Rare. - /// - /// Its `EmissionGuarantee` is `()`. + /// A help that is only emitted once. OnceHelp, - /// Similar to `Note`, but used in cases where compilation has failed. Rare. - /// - /// Its `EmissionGuarantee` is `()`. + /// Similar to `Note`, but used in cases where compilation has failed. When printed for human + /// consumption, it doesn't have any kind of `note:` label. FailureNote, /// Only used for lints. - /// - /// Its `EmissionGuarantee` is `()`. Allow, /// Only used for lints. - /// - /// Its `EmissionGuarantee` is `()`. Expect(LintExpectationId), } @@ -1599,7 +1619,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | DelayedBug(_) | Fatal | Error => { + Bug | Fatal | Error | DelayedBug | GoodPathDelayedBug => { spec.set_fg(Some(Color::Red)).set_intense(true); } ForceWarning(_) | Warning => { @@ -1619,7 +1639,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { - Bug | DelayedBug(_) => "error: internal compiler error", + Bug | DelayedBug | GoodPathDelayedBug => "error: internal compiler error", Fatal | Error => "error", ForceWarning(_) | Warning => "warning", Note | OnceNote => "note", @@ -1639,6 +1659,19 @@ impl Level { _ => None, } } + + // Can this level be used in a top-level diagnostic message and/or a + // subdiagnostic message? + fn can_be_top_or_sub(&self) -> (bool, bool) { + match self { + Bug | DelayedBug | Fatal | Error | GoodPathDelayedBug | ForceWarning(_) + | FailureNote | Allow | Expect(_) => (true, false), + + Warning | Note | Help => (true, true), + + OnceNote | OnceHelp => (false, true), + } + } } // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. diff --git a/compiler/rustc_errors/src/snippet.rs b/compiler/rustc_errors/src/snippet.rs index 98eb70b5fceee..b55f78538852a 100644 --- a/compiler/rustc_errors/src/snippet.rs +++ b/compiler/rustc_errors/src/snippet.rs @@ -197,7 +197,7 @@ pub struct StyledString { pub style: Style, } -#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum Style { MainHeaderMsg, HeaderMsg, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 657e19277a7ed..cfeb31fc4c813 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] - use crate::base::ast::NestedMetaItem; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index f9bfebee12e92..5879e025e7dbd 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -141,6 +141,7 @@ impl<'a> ExtCtxt<'a> { } else { ast::BoundConstness::Never }, + asyncness: ast::BoundAsyncness::Normal, }, ) } diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 2cf6a8df7c5ff..4da86d77dc88f 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -10,7 +10,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 1a39708ed8ed8..83e0f870c8a25 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -485,7 +485,9 @@ pub fn compile_declarative_macro( ) .pop() .unwrap(); - valid &= check_lhs_nt_follows(sess, def, &tt); + // We don't handle errors here, the driver will abort + // after parsing/expansion. we can report every error in every macro this way. + valid &= check_lhs_nt_follows(sess, def, &tt).is_ok(); return tt; } sess.dcx().span_bug(def.span, "wrong-structured lhs") @@ -589,18 +591,19 @@ pub fn compile_declarative_macro( (mk_syn_ext(expander), rule_spans) } -fn check_lhs_nt_follows(sess: &Session, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { +fn check_lhs_nt_follows( + sess: &Session, + def: &ast::Item, + lhs: &mbe::TokenTree, +) -> Result<(), ErrorGuaranteed> { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. if let mbe::TokenTree::Delimited(.., delimited) = lhs { check_matcher(sess, def, &delimited.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; - sess.dcx().span_err(lhs.span(), msg); - false + Err(sess.dcx().span_err(lhs.span(), msg)) } - // we don't abort on errors on rejection, the driver will do that for us - // after parsing/expansion. we can report every error in every macro this way. } fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool { @@ -675,12 +678,15 @@ fn check_rhs(sess: &Session, rhs: &mbe::TokenTree) -> bool { false } -fn check_matcher(sess: &Session, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool { +fn check_matcher( + sess: &Session, + def: &ast::Item, + matcher: &[mbe::TokenTree], +) -> Result<(), ErrorGuaranteed> { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); - let err = sess.dcx().err_count(); - check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix); - err == sess.dcx().err_count() + check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix)?; + Ok(()) } fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool { @@ -1020,11 +1026,13 @@ fn check_matcher_core<'tt>( first_sets: &FirstSets<'tt>, matcher: &'tt [mbe::TokenTree], follow: &TokenSet<'tt>, -) -> TokenSet<'tt> { +) -> Result, ErrorGuaranteed> { use mbe::TokenTree; let mut last = TokenSet::empty(); + let mut errored = Ok(()); + // 2. For each token and suffix [T, SUFFIX] in M: // ensure that T can be followed by SUFFIX, and if SUFFIX may be empty, // then ensure T can also be followed by any element of FOLLOW. @@ -1068,7 +1076,7 @@ fn check_matcher_core<'tt>( token::CloseDelim(d.delim), span.close, )); - check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix); + check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix)?; // don't track non NT tokens last.replace_with_irrelevant(); @@ -1100,7 +1108,7 @@ fn check_matcher_core<'tt>( // At this point, `suffix_first` is built, and // `my_suffix` is some TokenSet that we can use // for checking the interior of `seq_rep`. - let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix); + let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix)?; if next.maybe_empty { last.add_all(&next); } else { @@ -1206,14 +1214,15 @@ fn check_matcher_core<'tt>( )); } } - err.emit(); + errored = Err(err.emit()); } } } } } } - last + errored?; + Ok(last) } fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 1155366db85e3..18f6ae35054b4 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -77,7 +77,7 @@ declare_features! ( /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720)), /// Allows `c"foo"` literals. - (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723)), + (accepted, c_str_literals, "1.77.0", Some(105723)), /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881)), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 68b6f69854dd6..019cc1c847e91 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -440,9 +440,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ experimental!(optimize), ), - gated!( - ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) - ), gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)), gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)), gated!( diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index cd1d9b13daa15..f1c8f2e2dde5c 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -15,8 +15,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![feature(lazy_cell)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] mod accepted; mod builtin_attrs; diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 67ee53d8ae53f..008c59e1be3db 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -32,6 +32,8 @@ declare_features! ( // feature-group-start: removed features // ------------------------------------------------------------------------- + /// Allows using the `amdgpu-kernel` ABI. + (removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None), (removed, advanced_slice_patterns, "1.0.0", Some(62254), Some("merged into `#![feature(slice_patterns)]`")), (removed, allocator, "1.0.0", None, None), @@ -95,6 +97,9 @@ declare_features! ( /// Allows `#[doc(include = "some-file")]`. (removed, external_doc, "1.54.0", Some(44732), Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), + /// Allows using `#[ffi_returns_twice]` on foreign functions. + (removed, ffi_returns_twice, "CURRENT_RUSTC_VERSION", Some(58314), + Some("being investigated by the ffi-unwind project group")), /// Allows generators to be cloned. (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")), /// Allows defining generators. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e66a66e23dc4f..42fc24c937bfc 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -321,8 +321,6 @@ declare_features! ( // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - /// Allows using the `amdgpu-kernel` ABI. - (unstable, abi_amdgpu_kernel, "1.29.0", Some(51575)), /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. (unstable, abi_avr_interrupt, "1.45.0", Some(69664)), /// Allows `extern "C-cmse-nonsecure-call" fn()`. @@ -358,7 +356,7 @@ declare_features! ( /// Allows `#[track_caller]` on async functions. (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. - (unstable, async_for_loop, "CURRENT_RUSTC_VERSION", Some(118898)), + (unstable, async_for_loop, "1.77.0", Some(118898)), /// Allows builtin # foo() syntax (unstable, builtin_syntax, "1.71.0", Some(110680)), /// Treat `extern "C"` function as nounwind. @@ -372,7 +370,7 @@ declare_features! ( /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. (unstable, cfg_sanitize, "1.41.0", Some(39699)), /// Allows `cfg(sanitizer_cfi_generalize_pointers)` and `cfg(sanitizer_cfi_normalize_integers)`. - (unstable, cfg_sanitizer_cfi, "CURRENT_RUSTC_VERSION", Some(89653)), + (unstable, cfg_sanitizer_cfi, "1.77.0", Some(89653)), /// Allows `cfg(target_abi = "...")`. (unstable, cfg_target_abi, "1.55.0", Some(80970)), /// Allows `cfg(target(abi = "..."))`. @@ -467,8 +465,6 @@ declare_features! ( (unstable, ffi_const, "1.45.0", Some(58328)), /// Allows the use of `#[ffi_pure]` on foreign functions. (unstable, ffi_pure, "1.45.0", Some(58329)), - /// Allows using `#[ffi_returns_twice]` on foreign functions. - (unstable, ffi_returns_twice, "1.34.0", Some(58314)), /// Allows using `#[repr(align(...))]` on function items (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. @@ -498,7 +494,7 @@ declare_features! ( /// Allow anonymous constants from an inline `const` block (unstable, inline_const, "1.49.0", Some(76001)), /// Allow anonymous constants from an inline `const` block in pattern position - (incomplete, inline_const_pat, "1.58.0", Some(76001)), + (unstable, inline_const_pat, "1.58.0", Some(76001)), /// Allows using `pointer` and `reference` in intra-doc links (unstable, intra_doc_pointers, "1.51.0", Some(80896)), // Allows setting the threshold for the `large_assignments` lint. @@ -518,7 +514,7 @@ declare_features! ( (unstable, marker_trait_attr, "1.30.0", Some(29864)), /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are /// unambiguously sound. - (incomplete, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)), + (incomplete, min_exhaustive_patterns, "1.77.0", Some(119612)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. @@ -554,7 +550,7 @@ declare_features! ( /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using multiple nested field accesses in offset_of! - (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)), + (unstable, offset_of_nested, "1.77.0", Some(120140)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows macro attributes on expressions, statements and non-inline modules. diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index fc65d1eb8c4ce..e3784409af8fd 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -4,8 +4,6 @@ #![feature(rustdoc_internals)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(rustc::default_hash_types)] use proc_macro::TokenStream; diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 81d6333814544..3359fef8c1c46 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -1,6 +1,4 @@ #![feature(absolute_path)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use std::ffi::CString; use std::fs; diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index eba3215d93153..43bee5c4be029 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -276,8 +276,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use LabelText::*; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 681e228a0f2ff..abf7a695fd2d1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -163,10 +163,6 @@ impl Lifetime { (LifetimeSuggestionPosition::Normal, self.ident.span) } } - - pub fn is_static(&self) -> bool { - self.res == LifetimeName::Static - } } /// A `Path` is essentially Rust's notion of a name; for instance, @@ -835,7 +831,7 @@ pub struct OwnerNodes<'tcx> { // The zeroth node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally // used. - pub nodes: IndexVec>>, + pub nodes: IndexVec>, /// Content of local bodies. pub bodies: SortedMap>, } @@ -843,9 +839,8 @@ pub struct OwnerNodes<'tcx> { impl<'tcx> OwnerNodes<'tcx> { pub fn node(&self) -> OwnerNode<'tcx> { use rustc_index::Idx; - let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; - let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. - node + // Indexing must ensure it is an OwnerNode. + self.nodes[ItemLocalId::new(0)].node.as_owner().unwrap() } } @@ -860,9 +855,7 @@ impl fmt::Debug for OwnerNodes<'_> { .nodes .iter_enumerated() .map(|(id, parented_node)| { - let parented_node = parented_node.as_ref().map(|node| node.parent); - - debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})")) + debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent)) }) .collect::>(), ) @@ -894,34 +887,23 @@ impl<'tcx> OwnerInfo<'tcx> { } #[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum MaybeOwner { - Owner(T), +pub enum MaybeOwner<'tcx> { + Owner(&'tcx OwnerInfo<'tcx>), NonOwner(HirId), /// Used as a placeholder for unused LocalDefId. Phantom, } -impl MaybeOwner { - pub fn as_owner(self) -> Option { +impl<'tcx> MaybeOwner<'tcx> { + pub fn as_owner(self) -> Option<&'tcx OwnerInfo<'tcx>> { match self { MaybeOwner::Owner(i) => Some(i), MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None, } } - pub fn map(self, f: impl FnOnce(T) -> U) -> MaybeOwner { - match self { - MaybeOwner::Owner(i) => MaybeOwner::Owner(f(i)), - MaybeOwner::NonOwner(hir_id) => MaybeOwner::NonOwner(hir_id), - MaybeOwner::Phantom => MaybeOwner::Phantom, - } - } - - pub fn unwrap(self) -> T { - match self { - MaybeOwner::Owner(i) => i, - MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => panic!("Not a HIR owner"), - } + pub fn unwrap(self) -> &'tcx OwnerInfo<'tcx> { + self.as_owner().unwrap_or_else(|| panic!("Not a HIR owner")) } } @@ -933,7 +915,7 @@ impl MaybeOwner { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(Debug)] pub struct Crate<'hir> { - pub owners: IndexVec>>, + pub owners: IndexVec>, // Only present when incr. comp. is enabled. pub opt_hir_hash: Option, } @@ -963,6 +945,11 @@ pub enum ClosureKind { /// usage (e.g. `let x = || { yield (); }`) or from a desugared expression /// (e.g. `async` and `gen` blocks). Coroutine(CoroutineKind), + /// This is a coroutine-closure, which is a special sugared closure that + /// returns one of the sugared coroutine (`async`/`gen`/`async gen`). It + /// additionally allows capturing the coroutine's upvars by ref, and therefore + /// needs to be specially treated during analysis and borrowck. + CoroutineClosure(CoroutineDesugaring), } /// A block of statements `{ .. }`, which may have a label (in this case the @@ -3357,13 +3344,15 @@ impl<'hir> OwnerNode<'hir> { } } - pub fn span(&self) -> Span { + // Span by reference to pass to `Node::Err`. + #[allow(rustc::pass_by_value)] + pub fn span(&self) -> &'hir Span { match self { OwnerNode::Item(Item { span, .. }) | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) - | OwnerNode::TraitItem(TraitItem { span, .. }) => *span, - OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span, + | OwnerNode::TraitItem(TraitItem { span, .. }) => span, + OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span, } } @@ -3492,17 +3481,19 @@ pub enum Node<'hir> { Arm(&'hir Arm<'hir>), Block(&'hir Block<'hir>), Local(&'hir Local<'hir>), - /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants /// with synthesized constructors. Ctor(&'hir VariantData<'hir>), - Lifetime(&'hir Lifetime), GenericParam(&'hir GenericParam<'hir>), - Crate(&'hir Mod<'hir>), - Infer(&'hir InferArg), + WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>), + // FIXME: Merge into `Node::Infer`. + ArrayLenInfer(&'hir InferArg), + // Span by reference to minimize `Node`'s size + #[allow(rustc::pass_by_value)] + Err(&'hir Span), } impl<'hir> Node<'hir> { @@ -3547,7 +3538,10 @@ impl<'hir> Node<'hir> { | Node::Crate(..) | Node::Ty(..) | Node::TraitRef(..) - | Node::Infer(..) => None, + | Node::Infer(..) + | Node::WhereBoundPredicate(..) + | Node::ArrayLenInfer(..) + | Node::Err(..) => None, } } @@ -3709,6 +3703,7 @@ impl<'hir> Node<'hir> { expect_generic_param, &'hir GenericParam<'hir>, Node::GenericParam(n), n; expect_crate, &'hir Mod<'hir>, Node::Crate(n), n; expect_infer, &'hir InferArg, Node::Infer(n), n; + expect_closure, &'hir Closure<'hir>, Node::Expr(Expr { kind: ExprKind::Closure(n), .. }), n; } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 27c834d848fc4..52e1109ff9215 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -108,8 +108,8 @@ impl<'a> FnKind<'a> { /// An abstract representation of the HIR `rustc_middle::hir::map::Map`. pub trait Map<'hir> { - /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. - fn find(&self, hir_id: HirId) -> Option>; + /// Retrieves the `Node` corresponding to `id`. + fn hir_node(&self, hir_id: HirId) -> Node<'hir>; fn body(&self, id: BodyId) -> &'hir Body<'hir>; fn item(&self, id: ItemId) -> &'hir Item<'hir>; fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>; @@ -119,7 +119,7 @@ pub trait Map<'hir> { // Used when no map is actually available, forcing manual implementation of nested visitors. impl<'hir> Map<'hir> for ! { - fn find(&self, _: HirId) -> Option> { + fn hir_node(&self, _: HirId) -> Node<'hir> { *self; } fn body(&self, _: BodyId) -> &'hir Body<'hir> { @@ -669,6 +669,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { match len { + // FIXME: Use `visit_infer` here. ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), ArrayLen::Body(c) => visitor.visit_anon_const(c), } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 8e327c029dffc..9c9e72d6e6512 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -209,6 +209,7 @@ language_item_table! { AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1); + AsyncFnKindHelper, sym::async_fn_kind_helper,async_fn_kind_helper, Target::Trait, GenericRequirement::Exact(1); FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 6c64d802e68f1..aff946ac58081 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -9,8 +9,6 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 432c9c12cbfbc..d6f604c180bf6 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -33,10 +33,6 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the as hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes -hir_analysis_async_trait_impl_should_be_async = - method `{$method_name}` should be async because the method from the trait is async - .trait_item_label = required because the trait method is async - hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` .label = deref recursion limit reached .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) @@ -210,6 +206,9 @@ hir_analysis_manual_implementation = .label = manual implementations of `{$trait_name}` are experimental .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable +hir_analysis_method_should_return_future = method should be `async` or return a future, but it is synchronous + .note = this method is `async` so it expects a future to be returned + hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}` .label = missing one of `{$missing_items_msg}` in implementation .note = required because of this annotation @@ -434,6 +433,17 @@ hir_analysis_unused_associated_type_bounds = .note = this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. .suggestion = remove this bound +hir_analysis_unused_generic_parameter = + {$param_def_kind} `{$param_name}` is never used + .label = unused {$param_def_kind} + .const_param_help = if you intended `{$param_name}` to be a const parameter, use `const {$param_name}: /* Type */` instead +hir_analysis_unused_generic_parameter_adt_help = + consider removing `{$param_name}`, referring to it in a field, or using a marker such as `{$phantom_data}` +hir_analysis_unused_generic_parameter_adt_no_phantom_data_help = + consider removing `{$param_name}` or referring to it in a field +hir_analysis_unused_generic_parameter_ty_alias_help = + consider removing `{$param_name}` or referring to it in the body of the type alias + hir_analysis_value_of_associated_struct_already_specified = the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified .label = re-bound here diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index c22daad334fc5..1ae267d1a4059 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -28,6 +28,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let tcx = self.tcx(); let sized_def_id = tcx.lang_items().sized_trait(); let mut seen_negative_sized_bound = false; + let mut seen_positive_sized_bound = false; // Try to find an unbound in bounds. let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); @@ -45,6 +46,13 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { seen_negative_sized_bound = true; } } + hir::TraitBoundModifier::None => { + if let Some(sized_def_id) = sized_def_id + && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) + { + seen_positive_sized_bound = true; + } + } _ => {} } } @@ -82,11 +90,11 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { ); } - if seen_sized_unbound || seen_negative_sized_bound { - // There was in fact a `?Sized` or `!Sized` bound; + if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound { + // There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound; // we don't need to do anything. } else if sized_def_id.is_some() { - // There was no `?Sized` or `!Sized` bound; + // There was no `?Sized`, `!Sized` or explicit `Sized` bound; // add `Sized` if it's available. bounds.push_sized(tcx, self_ty, span); } @@ -235,9 +243,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { speculative: bool, dup_bindings: &mut FxHashMap, path_span: Span, - constness: ty::BoundConstness, only_self_bounds: OnlySelfBounds, - polarity: ty::ImplPolarity, ) -> Result<(), ErrorGuaranteed> { // Given something like `U: SomeTrait`, we want to produce a // predicate like `::T = X`. This is somewhat diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 407517b15ef5e..3c64b102bae8d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -14,6 +14,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; +use rustc_middle::query::Key; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; @@ -247,7 +248,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_suggestion_verbose( assoc_name.span, fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, - suggested_name.to_string(), + suggested_name, Applicability::MaybeIncorrect, ); } @@ -859,6 +860,56 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.set_tainted_by_errors(err.emit()); } + + /// On ambiguous associated type, look for an associated function whose name matches the + /// extended path and, if found, emit an E0223 error with a structured suggestion. + /// e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195) + pub(crate) fn maybe_report_similar_assoc_fn( + &self, + span: Span, + qself_ty: Ty<'tcx>, + qself: &hir::Ty<'_>, + ) -> Result<(), ErrorGuaranteed> { + let tcx = self.tcx(); + if let Some((_, node)) = tcx.hir().parent_iter(qself.hir_id).skip(1).next() + && let hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Path(hir::QPath::TypeRelative( + hir::Ty { + kind: + hir::TyKind::Path(hir::QPath::TypeRelative( + _, + hir::PathSegment { ident: ident2, .. }, + )), + .. + }, + hir::PathSegment { ident: ident3, .. }, + )), + .. + }) = node + && let Some(ty_def_id) = qself_ty.ty_def_id() + && let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id) + && let name = format!("{ident2}_{ident3}") + && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx + .associated_items(inherent_impl) + .filter_by_name_unhygienic(Symbol::intern(&name)) + .next() + { + let reported = + struct_span_code_err!(tcx.dcx(), span, E0223, "ambiguous associated type") + .with_span_suggestion_verbose( + ident2.span.to(ident3.span), + format!("there is an associated function with a similar name: `{name}`"), + name, + Applicability::MaybeIncorrect, + ) + .emit(); + self.set_tainted_by_errors(reported); + Err(reported) + } else { + Ok(()) + } + } } /// Emits an error regarding forbidden type binding associations diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 30b10446afcc9..aa826c1f26805 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt, }; use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; -use rustc_span::{symbol::kw, Span}; +use rustc_span::symbol::kw; use smallvec::SmallVec; /// Report an error that a generic argument did not match the generic parameter that was @@ -404,7 +404,6 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>( /// Used specifically for function calls. pub fn check_generic_arg_count_for_call( tcx: TyCtxt<'_>, - span: Span, def_id: DefId, generics: &ty::Generics, seg: &hir::PathSegment<'_>, @@ -418,17 +417,7 @@ pub fn check_generic_arg_count_for_call( }; let has_self = generics.parent.is_none() && generics.has_self; - check_generic_arg_count( - tcx, - span, - def_id, - seg, - generics, - gen_args, - gen_pos, - has_self, - seg.infer_args, - ) + check_generic_arg_count(tcx, def_id, seg, generics, gen_args, gen_pos, has_self, seg.infer_args) } /// Checks that the correct number of generic arguments have been provided. @@ -436,7 +425,6 @@ pub fn check_generic_arg_count_for_call( #[instrument(skip(tcx, gen_pos), level = "debug")] pub(crate) fn check_generic_arg_count( tcx: TyCtxt<'_>, - span: Span, def_id: DefId, seg: &hir::PathSegment<'_>, gen_params: &ty::Generics, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 89f39897ea874..d438d3e7c60bb 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -12,7 +12,7 @@ use crate::astconv::errors::prohibit_assoc_ty_binding; use crate::astconv::generics::{check_generic_arg_count, create_args_for_parent_generic_args}; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; -use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed}; +use crate::errors::AmbiguousLifetimeBound; use crate::middle::resolve_bound_vars as rbv; use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; @@ -25,13 +25,13 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; -use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; +use rustc_hir::{GenericArg, GenericArgs}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty, - TyCtxt, TypeVisitableExt, + self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; @@ -379,7 +379,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut arg_count = check_generic_arg_count( tcx, - span, def_id, seg, generics, @@ -773,9 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { speculative, &mut dup_bindings, binding.span, - constness, only_self_bounds, - polarity, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). } @@ -1373,6 +1370,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .emit() // Already reported in an earlier stage. } else { + self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?; + let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident); @@ -2491,7 +2490,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let opaque_ty = tcx.hir().item(item_id); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => { + hir::ItemKind::OpaqueTy(&hir::OpaqueTy { .. }) => { let local_def_id = item_id.owner_id.def_id; // If this is an RPITIT and we are using the new RPITIT lowering scheme, we // generate the def_id of an associated type for the trait and return as @@ -2501,7 +2500,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { local_def_id.to_def_id() }; - self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait) + self.impl_trait_ty_to_ty(def_id, lifetimes, in_trait) } ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } @@ -2537,21 +2536,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ty::new_array_with_const_len(tcx, self.ast_ty_to_ty(ty), length) } - hir::TyKind::Typeof(e) => { - let ty_erased = tcx.type_of(e.def_id).instantiate_identity(); - let ty = tcx.fold_regions(ty_erased, |r, _| { - if r.is_erased() { tcx.lifetimes.re_static } else { r } - }); - let span = ast_ty.span; - let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) { - (ty, Some((span, Applicability::MachineApplicable))) - } else { - (ty, None) - }; - tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); - - ty - } + hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), hir::TyKind::Infer => { // Infer also appears as the type of arguments or return // values in an ExprKind::Closure, or as @@ -2571,7 +2556,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, def_id: DefId, lifetimes: &[hir::GenericArg<'_>], - origin: OpaqueTyOrigin, in_trait: bool, ) -> Ty<'tcx> { debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 2fe3499e8e690..50809a571b8dc 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -31,6 +31,7 @@ use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _}; use rustc_type_ir::fold::TypeFoldable; +use std::cell::LazyCell; use std::ops::ControlFlow; pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { @@ -520,9 +521,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } DefKind::TyAlias => { - let pty_ty = tcx.type_of(def_id).instantiate_identity(); - let generics = tcx.generics_of(def_id); - check_type_params_are_used(tcx, generics, pty_ty); + check_type_alias_type_params_are_used(tcx, def_id); } DefKind::ForeignMod => { let it = tcx.hir().expect_item(def_id); @@ -1269,28 +1268,51 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) } } -pub(super) fn check_type_params_are_used<'tcx>( - tcx: TyCtxt<'tcx>, - generics: &ty::Generics, - ty: Ty<'tcx>, -) { - debug!("check_type_params_are_used(generics={:?}, ty={:?})", generics, ty); - - assert_eq!(generics.parent, None); +fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { + if tcx.type_alias_is_lazy(def_id) { + // Since we compute the variances for lazy type aliases and already reject bivariant + // parameters as unused, we can and should skip this check for lazy type aliases. + return; + } + let generics = tcx.generics_of(def_id); if generics.own_counts().types == 0 { return; } - let mut params_used = BitSet::new_empty(generics.params.len()); - + let ty = tcx.type_of(def_id).instantiate_identity(); if ty.references_error() { - // If there is already another error, do not emit - // an error for not using a type parameter. + // If there is already another error, do not emit an error for not using a type parameter. assert!(tcx.dcx().has_errors().is_some()); return; } + // Lazily calculated because it is only needed in case of an error. + let bounded_params = LazyCell::new(|| { + tcx.explicit_predicates_of(def_id) + .predicates + .iter() + .filter_map(|(predicate, span)| { + let bounded_ty = match predicate.kind().skip_binder() { + ty::ClauseKind::Trait(pred) => pred.trait_ref.self_ty(), + ty::ClauseKind::TypeOutlives(pred) => pred.0, + _ => return None, + }; + if let ty::Param(param) = bounded_ty.kind() { + Some((param.index, span)) + } else { + None + } + }) + // FIXME: This assumes that elaborated `Sized` bounds come first (which does hold at the + // time of writing). This is a bit fragile since we later use the span to detect elaborated + // `Sized` bounds. If they came last for example, this would break `Trait + /*elab*/Sized` + // since it would overwrite the span of the user-written bound. This could be fixed by + // folding the spans with `Span::to` which requires a bit of effort I think. + .collect::>() + }); + + let mut params_used = BitSet::new_empty(generics.params.len()); for leaf in ty.walk() { if let GenericArgKind::Type(leaf_ty) = leaf.unpack() && let ty::Param(param) = leaf_ty.kind() @@ -1305,15 +1327,24 @@ pub(super) fn check_type_params_are_used<'tcx>( && let ty::GenericParamDefKind::Type { .. } = param.kind { let span = tcx.def_span(param.def_id); - struct_span_code_err!( - tcx.dcx(), + let param_name = Ident::new(param.name, span); + + // The corresponding predicates are post-`Sized`-elaboration. Therefore we + // * check for emptiness to detect lone user-written `?Sized` bounds + // * compare the param span to the pred span to detect lone user-written `Sized` bounds + let has_explicit_bounds = bounded_params.is_empty() + || (*bounded_params).get(¶m.index).is_some_and(|&&pred_sp| pred_sp != span); + let const_param_help = (!has_explicit_bounds).then_some(()); + + let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { span, - E0091, - "type parameter `{}` is unused", - param.name, - ) - .with_span_label(span, "unused type parameter") - .emit(); + param_name, + param_def_kind: tcx.def_descr(param.def_id), + help: errors::UnusedGenericParameterHelp::TyAlias { param_name }, + const_param_help, + }); + diag.code(E0091); + diag.emit(); } } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 479421af77fef..6edd68f1baebe 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1,5 +1,5 @@ use super::potentially_plural_count; -use crate::errors::LifetimesOrBoundsMismatchOnTrait; +use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; @@ -10,7 +10,7 @@ use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::util; +use rustc_infer::traits::{util, FulfillmentError}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; @@ -20,6 +20,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericParamDefKind, TyCtxt}; use rustc_span::Span; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::{ @@ -73,7 +74,6 @@ fn check_method_is_structurally_compatible<'tcx>( compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?; compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?; compare_synthetic_generics(tcx, impl_m, trait_m, delay)?; - compare_asyncness(tcx, impl_m, trait_m, delay)?; check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?; Ok(()) } @@ -413,36 +413,6 @@ impl<'tcx> TypeFolder> for RemapLateBound<'_, 'tcx> { } } -fn compare_asyncness<'tcx>( - tcx: TyCtxt<'tcx>, - impl_m: ty::AssocItem, - trait_m: ty::AssocItem, - delay: bool, -) -> Result<(), ErrorGuaranteed> { - if tcx.asyncness(trait_m.def_id).is_async() { - match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() { - ty::Alias(ty::Opaque, ..) => { - // allow both `async fn foo()` and `fn foo() -> impl Future` - } - ty::Error(_) => { - // We don't know if it's ok, but at least it's already an error. - } - _ => { - return Err(tcx - .dcx() - .create_err(crate::errors::AsyncTraitImplShouldBeAsync { - span: tcx.def_span(impl_m.def_id), - method_name: trait_m.name, - trait_item_span: tcx.hir().span_if_local(trait_m.def_id), - }) - .emit_unless(delay)); - } - }; - } - - 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` @@ -694,8 +664,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // RPITs. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(errors); - return Err(reported); + if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig) + { + return Err(guar); + } + + let guar = infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(guar); } // Finally, resolve all regions. This catches wily misuses of @@ -1989,6 +1964,10 @@ pub(super) fn check_type_bounds<'tcx>( impl_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure().coherent_trait(impl_trait_ref.def_id)?; + let param_env = tcx.param_env(impl_ty.def_id); debug!(?param_env); @@ -2247,3 +2226,47 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { ty::AssocKind::Type => "type", } } + +/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`, +/// and extract a better error if so. +fn try_report_async_mismatch<'tcx>( + tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, + errors: &[FulfillmentError<'tcx>], + trait_m: ty::AssocItem, + impl_m: ty::AssocItem, + impl_sig: ty::FnSig<'tcx>, +) -> Result<(), ErrorGuaranteed> { + if !tcx.asyncness(trait_m.def_id).is_async() { + return Ok(()); + } + + let ty::Alias(ty::Projection, ty::AliasTy { def_id: async_future_def_id, .. }) = + *tcx.fn_sig(trait_m.def_id).skip_binder().skip_binder().output().kind() + else { + bug!("expected `async fn` to return an RPITIT"); + }; + + for error in errors { + if let traits::BindingObligation(def_id, _) = *error.root_obligation.cause.code() + && def_id == async_future_def_id + && let Some(proj) = error.root_obligation.predicate.to_opt_poly_projection_pred() + && let Some(proj) = proj.no_bound_vars() + && infcx.can_eq( + error.root_obligation.param_env, + proj.term.ty().unwrap(), + impl_sig.output(), + ) + { + // FIXME: We should suggest making the fn `async`, but extracting + // the right span is a bit difficult. + return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture { + span: tcx.def_span(impl_m.def_id), + method_name: trait_m.name, + trait_item_span: tcx.hir().span_if_local(trait_m.def_id), + })); + } + } + + Ok(()) +} diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 6d2ebb150b957..3d3b21eabb383 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -8,6 +8,7 @@ use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::Span; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{ elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, }; diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 9fe95487bb9e0..7b60457affa82 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -8,6 +8,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, TyCtxt}; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::{self, ObligationCtxt}; use crate::errors; @@ -188,6 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => { format!("{b}: {a}", a = ty::Region::new_var(tcx, a)) } + RegionResolutionError::CannotNormalize(..) => unreachable!(), }; guar = Some( struct_span_code_err!( diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 649ac6c5aebbf..3d803258c8e5e 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -43,8 +43,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { generics.params.is_empty().not().then_some(generics.span) } _ => { @@ -58,8 +58,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { Some(generics.where_clause_span) } _ => { @@ -80,8 +80,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => { Some(fn_sig.decl.output.span()) } _ => { @@ -202,7 +202,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { let start_t = tcx.type_of(start_def_id).instantiate_identity(); match start_t.kind() { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.opt_hir_node(start_id) { + if let Node::Item(it) = tcx.hir_node(start_id) { if let hir::ItemKind::Fn(sig, generics, _) = &it.kind { let mut error = false; if !generics.params.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 2d0d6611444c5..96b0cffc8a3d4 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -112,7 +112,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir | sym::forget | sym::black_box | sym::variant_count - | sym::ptr_mask => hir::Unsafety::Normal, + | sym::ptr_mask + | sym::debug_assertions => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, }; @@ -461,6 +462,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize) } + sym::debug_assertions => (0, Vec::new(), tcx.types.bool), + other => { tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other }); return; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 28c8f846c23a9..b74431983113a 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -578,7 +578,7 @@ pub fn check_function_signature<'tcx>( fn_id: LocalDefId, ) -> rustc_span::Span { let mut args = { - let node = tcx.hir().expect_owner(fn_id); + let node = tcx.expect_hir_owner_node(fn_id); let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node)); decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span())) }; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0978a5e65969a..646a84b043c82 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1,19 +1,16 @@ use crate::autoderef::Autoderef; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; +use crate::errors; use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_errors::{ - codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, -}; +use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::ItemKind; -use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs}; -use rustc_infer::infer::outlives::obligations::TypeOutlives; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_middle::mir::ConstraintCategory; use rustc_middle::query::Providers; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::trait_def::TraitSpecializationKind; @@ -23,9 +20,10 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArgKind, GenericArgs}; use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Ident, Symbol}; +use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::regions::InferCtxtRegionExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError, @@ -189,7 +187,7 @@ where } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> { - let node = tcx.hir().owner(def_id); + let node = tcx.hir_owner_node(def_id); let mut res = match node { hir::OwnerNode::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"), hir::OwnerNode::Item(item) => check_item(tcx, item), @@ -731,10 +729,12 @@ fn ty_known_to_outlive<'tcx>( ty: Ty<'tcx>, region: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |infcx, region_bound_pairs| { - let origin = infer::RelateParamBound(DUMMY_SP, ty, None); - let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env); - outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation); + test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { + infcx.register_region_obligation(infer::RegionObligation { + sub_region: region, + sup_type: ty, + origin: infer::RelateParamBound(DUMMY_SP, ty, None), + }); }) } @@ -748,40 +748,32 @@ fn region_known_to_outlive<'tcx>( region_a: ty::Region<'tcx>, region_b: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |mut infcx, _| { - use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; - let origin = infer::RelateRegionParamBound(DUMMY_SP); - // `region_a: region_b` -> `region_b <= region_a` - infcx.push_sub_region_constraint( - origin, - region_b, - region_a, - ConstraintCategory::BoringNoLocation, - ); + test_region_obligations(tcx, id, param_env, wf_tys, |infcx| { + infcx.sub_regions(infer::RelateRegionParamBound(DUMMY_SP), region_b, region_a); }) } /// Given a known `param_env` and a set of well formed types, set up an /// `InferCtxt`, call the passed function (to e.g. set up region constraints /// to be tested), then resolve region and return errors -fn resolve_regions_with_wf_tys<'tcx>( +fn test_region_obligations<'tcx>( tcx: TyCtxt<'tcx>, id: LocalDefId, param_env: ty::ParamEnv<'tcx>, wf_tys: &FxIndexSet>, - add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>), + add_constraints: impl FnOnce(&InferCtxt<'tcx>), ) -> bool { // Unfortunately, we have to use a new `InferCtxt` each call, because // region constraints get added and solved there and we need to test each // call individually. let infcx = tcx.infer_ctxt().build(); + + add_constraints(&infcx); + let outlives_environment = OutlivesEnvironment::with_bounds( param_env, infcx.implied_bounds_tys(param_env, id, wf_tys), ); - let region_bound_pairs = outlives_environment.region_bound_pairs(); - - add_constraints(&infcx, region_bound_pairs); let errors = infcx.resolve_regions(&outlives_environment); debug!(?errors, "errors"); @@ -1013,6 +1005,11 @@ fn check_associated_item( enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| { let item = tcx.associated_item(item_id); + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure() + .coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?; + let self_ty = match item.container { ty::TraitContainer => tcx.types.self_param, ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(), @@ -1299,6 +1296,9 @@ fn check_impl<'tcx>( // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity(); + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure().coherent_trait(trait_ref.def_id)?; let trait_ref = wfcx.normalize( ast_trait_ref.path.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), @@ -1876,7 +1876,7 @@ fn check_variances_for_type_defn<'tcx>( hir::ParamName::Error => {} _ => { let has_explicit_bounds = explicitly_bounded_params.contains(¶meter); - report_bivariance(tcx, hir_param, has_explicit_bounds); + report_bivariance(tcx, hir_param, has_explicit_bounds, item.kind); } } } @@ -1886,30 +1886,38 @@ fn report_bivariance( tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>, has_explicit_bounds: bool, + item_kind: ItemKind<'_>, ) -> ErrorGuaranteed { - let span = param.span; - let param_name = param.name.ident().name; - let mut err = error_392(tcx, span, param_name); - - let suggested_marker_id = tcx.lang_items().phantom_data(); - // Help is available only in presence of lang items. - let msg = if let Some(def_id) = suggested_marker_id { - format!( - "consider removing `{}`, referring to it in a field, or using a marker such as `{}`", - param_name, - tcx.def_path_str(def_id), - ) - } else { - format!("consider removing `{param_name}` or referring to it in a field") + let param_name = param.name.ident(); + + let help = match item_kind { + ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { + if let Some(def_id) = tcx.lang_items().phantom_data() { + errors::UnusedGenericParameterHelp::Adt { + param_name, + phantom_data: tcx.def_path_str(def_id), + } + } else { + errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name } + } + } + ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name }, + item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"), }; - err.help(msg); - if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds { - err.help(format!( - "if you intended `{param_name}` to be a const parameter, use `const {param_name}: usize` instead" - )); - } - err.emit() + let const_param_help = + matches!(param.kind, hir::GenericParamKind::Type { .. } if !has_explicit_bounds) + .then_some(()); + + let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter { + span: param.span, + param_name, + param_def_kind: tcx.def_descr(param.def_id.to_def_id()), + help, + const_param_help, + }); + diag.code(E0392); + diag.emit() } impl<'tcx> WfCheckingCtxt<'_, 'tcx> { @@ -1974,11 +1982,6 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error res } -fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> { - struct_span_code_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used") - .with_span_label(span, "unused parameter") -} - pub fn provide(providers: &mut Providers) { *providers = Providers { check_mod_type_wf, check_well_formed, ..*providers }; } diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index abef365c3ca3c..0df5a57bc2c45 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -171,6 +171,7 @@ impl<'tcx> InherentCollect<'tcx> { } ty::FnDef(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Bound(..) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 1736de760d5a6..45641be52d2f2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -244,6 +244,7 @@ fn do_orphan_check_impl<'tcx>( | ty::Tuple(..) => (LocalImpl::Allow, NonlocalImpl::DisallowOther), ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Bound(..) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8d862d5eb715f..fbcebb7c87c9b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -81,6 +81,7 @@ pub fn provide(providers: &mut Providers) { impl_trait_ref, impl_polarity, coroutine_kind, + coroutine_for_closure, collect_mod_item_types, is_type_alias_impl_trait, ..*providers @@ -1531,6 +1532,29 @@ fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option, def_id: LocalDefId) -> DefId { + let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } = + tcx.hir_node_by_def_id(def_id).expect_closure() + else { + bug!() + }; + + let &hir::Expr { + kind: + hir::ExprKind::Closure(&rustc_hir::Closure { + def_id, + kind: hir::ClosureKind::Coroutine(_), + .. + }), + .. + } = tcx.hir().body(body).value + else { + bug!() + }; + + def_id.to_def_id() +} + fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { match tcx.hir_node_by_def_id(def_id) { Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => { diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c29d413184304..4860555de2056 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -344,11 +344,25 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { kind: hir::ExprKind::Closure(hir::Closure { kind, .. }), .. }) = node { + // See `ClosureArgsParts`, `CoroutineArgsParts`, and `CoroutineClosureArgsParts` + // for info on the usage of each of these fields. let dummy_args = match kind { ClosureKind::Closure => &["", "", ""][..], - ClosureKind::Coroutine(_) => { - &["", "", "", "", ""][..] - } + ClosureKind::Coroutine(_) => &[ + "", + "", + "", + "", + "", + "", + ][..], + ClosureKind::CoroutineClosure(_) => &[ + "", + "", + "", + "", + "", + ][..], }; params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 97d792e49aeaa..3849c0893f471 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -254,7 +254,7 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou map: &mut named_variable_map, scope: &Scope::Root { opt_parent_item: None }, }; - match tcx.hir().owner(local_def_id) { + match tcx.hir_owner_node(local_def_id) { hir::OwnerNode::Item(item) => visitor.visit_item(item), hir::OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), hir::OwnerNode::TraitItem(item) => { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 3674a760cbf9d..20a7663f86441 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -9,6 +9,8 @@ use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, Ty use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; +use crate::errors::TypeofReservedKeywordUsed; + use super::bad_placeholder; use super::ItemCtxt; pub use opaque::test_opaque_hidden_types; @@ -39,8 +41,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { { return tcx.types.usize; } - Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => { - return tcx.typeck(def_id).node_type(e.hir_id); + Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => { + let ty = tcx.typeck(def_id).node_type(e.hir_id); + let ty = tcx.fold_regions(ty, |r, _| { + if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r } + }); + let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) { + (ty, Some((span, Applicability::MachineApplicable))) + } else { + (ty, None) + }; + tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); + return ty; } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) @@ -509,6 +521,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder bug!("unexpected non-type Node::GenericParam: {:?}", x), }, + Node::ArrayLenInfer(_) => tcx.types.usize, + x => { bug!("unexpected sort of node in type_of(): {:?}", x); } @@ -590,7 +604,6 @@ fn infer_placeholder_type<'a>( // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. // We are typeck and have the real type, so remove that and suggest the actual type. - // FIXME(eddyb) this looks like it should be functionality on `Diagnostic`. if let Ok(suggestions) = &mut err.suggestions { suggestions.clear(); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index e5871276d6414..bec53693d6c94 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -166,17 +166,6 @@ pub struct LifetimesOrBoundsMismatchOnTrait { pub ident: Ident, } -#[derive(Diagnostic)] -#[diag(hir_analysis_async_trait_impl_should_be_async)] -pub struct AsyncTraitImplShouldBeAsync { - #[primary_span] - // #[label] - pub span: Span, - #[label(hir_analysis_trait_item_label)] - pub trait_item_span: Option, - pub method_name: Symbol, -} - #[derive(Diagnostic)] #[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] pub struct DropImplOnWrongItem { @@ -1511,3 +1500,37 @@ pub struct NotSupportedDelegation<'a> { #[label] pub callee_span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_method_should_return_future)] +pub struct MethodShouldReturnFuture { + #[primary_span] + pub span: Span, + pub method_name: Symbol, + #[note] + pub trait_item_span: Option, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_unused_generic_parameter)] +pub(crate) struct UnusedGenericParameter { + #[primary_span] + #[label] + pub span: Span, + pub param_name: Ident, + pub param_def_kind: &'static str, + #[subdiagnostic] + pub help: UnusedGenericParameterHelp, + #[help(hir_analysis_const_param_help)] + pub const_param_help: Option<()>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnusedGenericParameterHelp { + #[help(hir_analysis_unused_generic_parameter_adt_help)] + Adt { param_name: Ident, phantom_data: String }, + #[help(hir_analysis_unused_generic_parameter_adt_no_phantom_data_help)] + AdtNoPhantomData { param_name: Ident }, + #[help(hir_analysis_unused_generic_parameter_ty_alias_help)] + TyAlias { param_name: Ident }, +} diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 454cb97ac148b..883d416ecd187 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -55,7 +55,9 @@ This API is completely unstable and subject to change. */ +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] @@ -169,11 +171,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.sess.time("coherence_checking", || { // Check impls constrain their parameters - let mut res = + let res = tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); for &trait_def_id in tcx.all_local_trait_impls(()).keys() { - res = res.and(tcx.ensure().coherent_trait(trait_def_id)); + let _ = tcx.ensure().coherent_trait(trait_def_id); } // these queries are executed for side-effects (error reporting): res.and(tcx.ensure().crate_inherent_impls(())) @@ -209,7 +211,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.ensure().check_unused_traits(()); - if let Some(reported) = tcx.dcx().has_errors() { Err(reported) } else { Ok(()) } + Ok(()) } /// A quasi-deprecated helper used in rustdoc and clippy to get diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 501915d2e7e53..3b1ee2975fd97 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -771,8 +771,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ); if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id) - && let Some(parent_node) = self.tcx.opt_hir_node(parent_node) - && let hir::Node::Expr(expr) = parent_node + && let hir::Node::Expr(expr) = self.tcx.hir_node(parent_node) { match &expr.kind { hir::ExprKind::Path(qpath) => self diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index f09594cbbc667..580cdb4a3a209 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -235,8 +235,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // leaf type -- noop } - ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) => { - bug!("Unexpected closure type in variance computation"); + ty::FnDef(..) | ty::Coroutine(..) | ty::Closure(..) | ty::CoroutineClosure(..) => { + bug!("Unexpected coroutine/closure type in variance computation"); } ty::Ref(region, ty, mutbl) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9d0c5cb0f32b0..b90fa03a3dc01 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2,8 +2,6 @@ //! the definitions in this file have equivalents in `rustc_ast_pretty`. #![recursion_limit = "256"] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_ast as ast; use rustc_ast::util::parser::{self, AssocOp, Fixity}; @@ -23,7 +21,7 @@ use std::cell::Cell; use std::vec; pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String { - to_string(&map, |s| s.print_node(map.find(hir_id).unwrap())) + to_string(&map, |s| s.print_node(map.hir_node(hir_id))) } pub enum AnnNode<'a> { @@ -117,6 +115,13 @@ impl<'a> State<'a> { Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), + Node::WhereBoundPredicate(pred) => { + self.print_formal_generic_params(pred.bound_generic_params); + self.print_type(pred.bounded_ty); + self.print_bounds(":", pred.bounds); + } + Node::ArrayLenInfer(_) => self.word("_"), + Node::Err(_) => self.word("/*ERROR*/"), } } } diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 4fd9391acc368..220da19a29dc8 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -96,9 +96,6 @@ hir_typeck_lossy_provenance_ptr2int = hir_typeck_method_call_on_unknown_raw_pointee = cannot call a method on a raw pointer with an unknown pointee type -hir_typeck_missing_fn_lang_items = failed to find an overloaded call trait for closure call - .help = make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}` hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method -> @@ -108,8 +105,6 @@ hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for { hir_typeck_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide -hir_typeck_op_trait_generic_params = `{$method_name}` must not have any generic parameters - hir_typeck_option_result_asref = use `{$def_path}::as_ref` to convert `{$expected_ty}` to `{$expr_ty}` hir_typeck_option_result_cloned = use `{$def_path}::cloned` to clone the value inside the `{$def_path}` hir_typeck_option_result_copied = use `{$def_path}::copied` to copy the value inside the `{$def_path}` diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index cf1f232229d51..7ea0469deddee 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,7 +1,11 @@ use crate::coercion::{AsCoercionSite, CoerceMany}; use crate::{Diverges, Expectation, FnCtxt, Needs}; -use rustc_errors::Diagnostic; -use rustc_hir::{self as hir, ExprKind}; +use rustc_errors::{Applicability, Diagnostic}; +use rustc_hir::{ + self as hir, + def::{CtorOf, DefKind, Res}, + ExprKind, PatKind, +}; use rustc_hir_pretty::ty_to_string; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; @@ -273,7 +277,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns `true` if there was an error forcing the coercion to the `()` type. pub(super) fn if_fallback_coercion( &self, - span: Span, + if_span: Span, + cond_expr: &'tcx hir::Expr<'tcx>, then_expr: &'tcx hir::Expr<'tcx>, coercion: &mut CoerceMany<'tcx, '_, T>, ) -> bool @@ -283,29 +288,106 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If this `if` expr is the parent's function return expr, // the cause of the type coercion is the return type, point at it. (#25228) let hir_id = self.tcx.hir().parent_id(self.tcx.hir().parent_id(then_expr.hir_id)); - let ret_reason = self.maybe_get_coercion_reason(hir_id, span); - let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse); + let ret_reason = self.maybe_get_coercion_reason(hir_id, if_span); + let cause = self.cause(if_span, ObligationCauseCode::IfExpressionWithNoElse); let mut error = false; coercion.coerce_forced_unit( self, &cause, - |err| { - if let Some((span, msg)) = &ret_reason { - err.span_label(*span, msg.clone()); - } else if let ExprKind::Block(block, _) = &then_expr.kind - && let Some(expr) = &block.expr - { - err.span_label(expr.span, "found here"); - } - err.note("`if` expressions without `else` evaluate to `()`"); - err.help("consider adding an `else` block that evaluates to the expected type"); - error = true; - }, + |err| self.explain_if_expr(err, ret_reason, if_span, cond_expr, then_expr, &mut error), false, ); error } + /// Explain why `if` expressions without `else` evaluate to `()` and detect likely irrefutable + /// `if let PAT = EXPR {}` expressions that could be turned into `let PAT = EXPR;`. + fn explain_if_expr( + &self, + err: &mut Diagnostic, + ret_reason: Option<(Span, String)>, + if_span: Span, + cond_expr: &'tcx hir::Expr<'tcx>, + then_expr: &'tcx hir::Expr<'tcx>, + error: &mut bool, + ) { + if let Some((if_span, msg)) = ret_reason { + err.span_label(if_span, msg.clone()); + } else if let ExprKind::Block(block, _) = then_expr.kind + && let Some(expr) = block.expr + { + err.span_label(expr.span, "found here"); + } + err.note("`if` expressions without `else` evaluate to `()`"); + err.help("consider adding an `else` block that evaluates to the expected type"); + *error = true; + if let ExprKind::Let(hir::Let { span, pat, init, .. }) = cond_expr.kind + && let ExprKind::Block(block, _) = then_expr.kind + // Refutability checks occur on the MIR, so we approximate it here by checking + // if we have an enum with a single variant or a struct in the pattern. + && let PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..) = pat.kind + && let hir::QPath::Resolved(_, path) = qpath + { + match path.res { + Res::Def(DefKind::Ctor(CtorOf::Struct, _), _) => { + // Structs are always irrefutable. Their fields might not be, but we + // don't check for that here, it's only an approximation. + } + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) + if self + .tcx + .adt_def(self.tcx.parent(self.tcx.parent(def_id))) + .variants() + .len() + == 1 => + { + // There's only a single variant in the `enum`, so we can suggest the + // irrefutable `let` instead of `if let`. + } + _ => return, + } + + let mut sugg = vec![ + // Remove the `if` + (if_span.until(*span), String::new()), + ]; + match (block.stmts, block.expr) { + ([first, ..], Some(expr)) => { + let padding = self + .tcx + .sess + .source_map() + .indentation_before(first.span) + .unwrap_or_else(|| String::new()); + sugg.extend([ + (init.span.between(first.span), format!(";\n{padding}")), + (expr.span.shrink_to_hi().with_hi(block.span.hi()), String::new()), + ]); + } + ([], Some(expr)) => { + let padding = self + .tcx + .sess + .source_map() + .indentation_before(expr.span) + .unwrap_or_else(|| String::new()); + sugg.extend([ + (init.span.between(expr.span), format!(";\n{padding}")), + (expr.span.shrink_to_hi().with_hi(block.span.hi()), String::new()), + ]); + } + // If there's no value in the body, then the `if` expression would already + // be of type `()`, so checking for those cases is unnecessary. + (_, None) => return, + } + err.multipart_suggestion( + "consider using an irrefutable `let` binding instead", + sugg, + Applicability::MaybeIncorrect, + ); + } + } + pub fn maybe_get_coercion_reason( &self, hir_id: hir::HirId, diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 9dc365526d467..1cd4b4cc4fc62 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -41,7 +41,7 @@ pub fn check_legal_trait_for_method_call( receiver: Option, expr_span: Span, trait_id: DefId, -) { +) -> Result<(), ErrorGuaranteed> { if tcx.lang_items().drop_trait() == Some(trait_id) { let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) { errors::ExplicitDestructorCallSugg::Snippet { @@ -51,8 +51,9 @@ pub fn check_legal_trait_for_method_call( } else { errors::ExplicitDestructorCallSugg::Empty(span) }; - tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg }); + return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg })); } + tcx.coherent_trait(trait_id) } #[derive(Debug)] @@ -77,6 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_expr, Expectation::NoExpectation, arg_exprs, + Some(call_expr), ), _ => self.check_expr(callee_expr), }; @@ -140,33 +142,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Some(CallStep::Builtin(adjusted_ty)); } - ty::Closure(def_id, args) => { + // Check whether this is a call to a closure where we + // haven't yet decided on whether the closure is fn vs + // fnmut vs fnonce. If so, we have to defer further processing. + ty::Closure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { let def_id = def_id.expect_local(); + let closure_sig = args.as_closure().sig(); + let closure_sig = self.instantiate_binder_with_fresh_vars( + call_expr.span, + infer::FnCall, + closure_sig, + ); + let adjustments = self.adjust_steps(autoderef); + self.record_deferred_call_resolution( + def_id, + DeferredCallResolution { + call_expr, + callee_expr, + closure_ty: adjusted_ty, + adjustments, + fn_sig: closure_sig, + }, + ); + return Some(CallStep::DeferredClosure(def_id, closure_sig)); + } - // Check whether this is a call to a closure where we - // haven't yet decided on whether the closure is fn vs - // fnmut vs fnonce. If so, we have to defer further processing. - if self.closure_kind(args).is_none() { - let closure_sig = args.as_closure().sig(); - let closure_sig = self.instantiate_binder_with_fresh_vars( - call_expr.span, - infer::FnCall, - closure_sig, - ); - let adjustments = self.adjust_steps(autoderef); - self.record_deferred_call_resolution( - def_id, - DeferredCallResolution { - call_expr, - callee_expr, - adjusted_ty, - adjustments, - fn_sig: closure_sig, - closure_args: args, - }, - ); - return Some(CallStep::DeferredClosure(def_id, closure_sig)); - } + // When calling a `CoroutineClosure` that is local to the body, we will + // not know what its `closure_kind` is yet. Instead, just fill in the + // signature with an infer var for the `tupled_upvars_ty` of the coroutine, + // and record a deferred call resolution which will constrain that var + // as part of `AsyncFn*` trait confirmation. + ty::CoroutineClosure(def_id, args) if self.closure_kind(adjusted_ty).is_none() => { + let def_id = def_id.expect_local(); + let closure_args = args.as_coroutine_closure(); + let coroutine_closure_sig = self.instantiate_binder_with_fresh_vars( + call_expr.span, + infer::FnCall, + closure_args.coroutine_closure_sig(), + ); + let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::TypeInference, + span: callee_expr.span, + }); + let call_sig = self.tcx.mk_fn_sig( + [coroutine_closure_sig.tupled_inputs_ty], + coroutine_closure_sig.to_coroutine( + self.tcx, + closure_args.parent_args(), + // Inherit the kind ty of the closure, since we're calling this + // coroutine with the most relaxed `AsyncFn*` trait that we can. + // We don't necessarily need to do this here, but it saves us + // computing one more infer var that will get constrained later. + closure_args.kind_ty(), + self.tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ), + coroutine_closure_sig.c_variadic, + coroutine_closure_sig.unsafety, + coroutine_closure_sig.abi, + ); + let adjustments = self.adjust_steps(autoderef); + self.record_deferred_call_resolution( + def_id, + DeferredCallResolution { + call_expr, + callee_expr, + closure_ty: adjusted_ty, + adjustments, + fn_sig: call_sig, + }, + ); + return Some(CallStep::DeferredClosure(def_id, call_sig)); } // Hack: we know that there are traits implementing Fn for &F @@ -253,28 +299,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { adjusted_ty, opt_input_type.as_ref().map(slice::from_ref), ) { - // Check for `self` receiver on the method, otherwise we can't use this as a `Fn*` trait. - if !self.tcx.associated_item(ok.value.def_id).fn_has_self_parameter { - self.dcx().span_delayed_bug( - call_expr.span, - "input to overloaded call fn is not a self receiver", - ); - return None; - } - let method = self.register_infer_ok_obligations(ok); let mut autoref = None; if borrow { // Check for &self vs &mut self in the method signature. Since this is either // the Fn or FnMut trait, it should be one of those. let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else { - // The `fn`/`fn_mut` lang item is ill-formed, which should have - // caused an error elsewhere. - self.dcx().span_delayed_bug( - call_expr.span, - "input to call/call_mut is not a ref", - ); - return None; + bug!("Expected `FnMut`/`Fn` to take receiver by-ref/by-mut") }; // For initial two-phase borrow @@ -900,10 +931,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub struct DeferredCallResolution<'tcx> { call_expr: &'tcx hir::Expr<'tcx>, callee_expr: &'tcx hir::Expr<'tcx>, - adjusted_ty: Ty<'tcx>, + closure_ty: Ty<'tcx>, adjustments: Vec>, fn_sig: ty::FnSig<'tcx>, - closure_args: GenericArgsRef<'tcx>, } impl<'a, 'tcx> DeferredCallResolution<'tcx> { @@ -912,10 +942,10 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { // we should not be invoked until the closure kind has been // determined by upvar inference - assert!(fcx.closure_kind(self.closure_args).is_some()); + assert!(fcx.closure_kind(self.closure_ty).is_some()); // We may now know enough to figure out fn vs fnmut etc. - match fcx.try_overloaded_call_traits(self.call_expr, self.adjusted_ty, None) { + match fcx.try_overloaded_call_traits(self.call_expr, self.closure_ty, None) { Some((autoref, method_callee)) => { // One problem is that when we get here, we are going // to have a newly instantiated function signature @@ -948,9 +978,11 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> { ); } None => { - // This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once` - // lang items are not defined (issue #86238). - fcx.dcx().emit_err(errors::MissingFnLangItems { span: self.call_expr.span }); + span_bug!( + self.call_expr.span, + "Expected to find a suitable `Fn`/`FnMut`/`FnOnce` implementation for `{}`", + self.closure_ty + ) } } } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index a0ac839f3dd2c..f21de1609cb7f 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -133,6 +133,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Adt(..) | ty::Never @@ -447,13 +448,35 @@ impl<'a, 'tcx> CastCheck<'tcx> { ); } } - let msg = "an `as` expression can only be used to convert between primitive \ - types or to coerce to a specific trait object"; + + let (msg, note) = if let ty::Adt(adt, _) = self.expr_ty.kind() + && adt.is_enum() + && self.cast_ty.is_numeric() + { + ( + "an `as` expression can be used to convert enum types to numeric \ + types only if the enum type is unit-only or field-less", + Some( + "see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information", + ), + ) + } else { + ( + "an `as` expression can only be used to convert between primitive \ + types or to coerce to a specific trait object", + None, + ) + }; + if label { err.span_label(self.span, msg); } else { err.note(msg); } + + if let Some(note) = note { + err.note(note); + } } else { err.span_label(self.span, "invalid cast"); } diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index ec63954df3461..aab78465f8c85 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -152,26 +152,22 @@ pub(super) fn check_fn<'a, 'tcx>( } fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>) { + let span = tcx.def_span(fn_id); + let DefKind::Fn = tcx.def_kind(fn_id) else { - let span = tcx.def_span(fn_id); tcx.dcx().span_err(span, "should be a function"); return; }; let generic_counts = tcx.generics_of(fn_id).own_counts(); if generic_counts.types != 0 { - let span = tcx.def_span(fn_id); tcx.dcx().span_err(span, "should have no type parameters"); } if generic_counts.consts != 0 { - let span = tcx.def_span(fn_id); tcx.dcx().span_err(span, "should have no const parameters"); } - let Some(panic_info_did) = tcx.lang_items().panic_info() else { - tcx.dcx().err("language item required, but not found: `panic_info`"); - return; - }; + let panic_info_did = tcx.require_lang_item(hir::LangItem::PanicInfo, Some(span)); // build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` let panic_info_ty = tcx.type_of(panic_info_did).instantiate( @@ -203,11 +199,7 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> let _ = check_function_signature( tcx, - ObligationCause::new( - tcx.def_span(fn_id), - fn_id, - ObligationCauseCode::LangFunctionType(sym::panic_impl), - ), + ObligationCause::new(span, fn_id, ObligationCauseCode::LangFunctionType(sym::panic_impl)), fn_id.into(), expected_sig, ); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index f51cc97b45deb..a985fa201d071 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => (None, None), }; - let ClosureSignatures { bound_sig, liberated_sig } = + let ClosureSignatures { bound_sig, mut liberated_sig } = self.sig_of_closure(expr_def_id, closure.fn_decl, closure.kind, expected_sig); debug!(?bound_sig, ?liberated_sig); @@ -125,7 +125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) | hir::CoroutineKind::Coroutine(_) => { let yield_ty = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, + kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, }); self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType); @@ -137,7 +137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // not a problem. hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => { let yield_ty = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::TypeInference, + kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, }); self.require_type_is_sized(yield_ty, expr_span, traits::SizedYieldType); @@ -166,8 +166,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); let interior = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::MiscVariable, - span: body.value.span, + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, }); self.deferred_coroutine_interiors.borrow_mut().push(( expr_def_id, @@ -175,10 +175,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { interior, )); + // Coroutines that come from coroutine closures have not yet determined + // their kind ty, so make a fresh infer var which will be constrained + // later during upvar analysis. Regular coroutines always have the kind + // ty of `().` + let kind_ty = match kind { + hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) => self + .next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }), + _ => tcx.types.unit, + }; + let coroutine_args = ty::CoroutineArgs::new( tcx, ty::CoroutineArgsParts { parent_args, + kind_ty, resume_ty, yield_ty, return_ty: liberated_sig.output(), @@ -192,6 +206,94 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(CoroutineTypes { resume_ty, yield_ty }), ) } + hir::ClosureKind::CoroutineClosure(kind) => { + // async closures always return the type ascribed after the `->` (if present), + // and yield `()`. + let (bound_return_ty, bound_yield_ty) = match kind { + hir::CoroutineDesugaring::Async => { + (bound_sig.skip_binder().output(), tcx.types.unit) + } + hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen => { + todo!("`gen` and `async gen` closures not supported yet") + } + }; + // Compute all of the variables that will be used to populate the coroutine. + let resume_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let interior = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let closure_kind_ty = self.next_ty_var(TypeVariableOrigin { + // FIXME(eddyb) distinguish closure kind inference variables from the rest. + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let coroutine_captures_by_ref_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + let closure_args = ty::CoroutineClosureArgs::new( + tcx, + ty::CoroutineClosureArgsParts { + parent_args, + closure_kind_ty, + signature_parts_ty: Ty::new_fn_ptr( + tcx, + bound_sig.map_bound(|sig| { + tcx.mk_fn_sig( + [ + resume_ty, + Ty::new_tup_from_iter(tcx, sig.inputs().iter().copied()), + ], + Ty::new_tup(tcx, &[bound_yield_ty, bound_return_ty]), + sig.c_variadic, + sig.unsafety, + sig.abi, + ) + }), + ), + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + coroutine_witness_ty: interior, + }, + ); + + let coroutine_upvars_ty = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::ClosureSynthetic, + span: expr_span, + }); + + // We need to turn the liberated signature that we got from HIR, which + // looks something like `|Args...| -> T`, into a signature that is suitable + // for type checking the inner body of the closure, which always returns a + // coroutine. To do so, we use the `CoroutineClosureSignature` to compute + // the coroutine type, filling in the tupled_upvars_ty and kind_ty with infer + // vars which will get constrained during upvar analysis. + let coroutine_output_ty = tcx.liberate_late_bound_regions( + expr_def_id.to_def_id(), + closure_args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine( + tcx, + parent_args, + closure_kind_ty, + tcx.coroutine_for_closure(expr_def_id), + coroutine_upvars_ty, + ) + }), + ); + liberated_sig = tcx.mk_fn_sig( + liberated_sig.inputs().iter().copied(), + coroutine_output_ty, + liberated_sig.c_variadic, + liberated_sig.unsafety, + liberated_sig.abi, + ); + + (Ty::new_coroutine_closure(tcx, expr_def_id.to_def_id(), closure_args.args), None) + } }; check_fn( @@ -690,7 +792,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _, )) | hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) - | hir::ClosureKind::Closure => astconv.ty_infer(None, decl.output.span()), + | hir::ClosureKind::Closure + | hir::ClosureKind::CoroutineClosure(_) => { + astconv.ty_infer(None, decl.output.span()) + } }, }; diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ca636ebcade04..2beabc0835db1 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1715,8 +1715,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let ret_msg = "return a value for the case when the loop has zero elements to iterate on"; let ret_ty_msg = "otherwise consider changing the return type to account for that possibility"; - if let Some(node) = tcx.opt_hir_node(item.into()) - && let Some(body_id) = node.body_id() + let node = tcx.hir_node(item.into()); + if let Some(body_id) = node.body_id() && let Some(sig) = node.fn_sig() && let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind && !ty.is_never() diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index b6dfc34d3ac19..d8974251de040 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -561,11 +561,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut parent; 'outer: loop { // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement. - let Some( - hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) - | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) - | hir::Node::Expr(&ref p), - ) = self.tcx.opt_hir_node(parent_id) + let (hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) + | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) + | hir::Node::Expr(&ref p)) = self.tcx.hir_node(parent_id) else { break; }; @@ -578,20 +576,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut direct = false; loop { // Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to. - let parent = match self.tcx.opt_hir_node(parent_id) { - Some(hir::Node::Expr(&ref parent)) => { + let parent = match self.tcx.hir_node(parent_id) { + hir::Node::Expr(&ref parent) => { parent_id = self.tcx.hir().parent_id(parent.hir_id); parent } - Some(hir::Node::Stmt(hir::Stmt { + hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Semi(&ref parent) | hir::StmtKind::Expr(&ref parent), .. - })) => { + }) => { parent_id = self.tcx.hir().parent_id(*hir_id); parent } - Some(hir::Node::Block(_)) => { + hir::Node::Block(_) => { parent_id = self.tcx.hir().parent_id(parent_id); parent } @@ -680,17 +678,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: Option>, ) { let parent = self.tcx.hir().parent_id(expr.hir_id); - match (self.tcx.opt_hir_node(parent), error) { - (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) + match (self.tcx.hir_node(parent), error) { + (hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. }), _) if init.hir_id == expr.hir_id => { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); } ( - Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Assign(lhs, rhs, _), .. - })), + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }), Some(TypeError::Sorts(ExpectedFound { expected, .. })), ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => { // We ignore closures explicitly because we already point at them elsewhere. @@ -725,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) => { - if let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) { + if let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) { primary_span = pat.span; secondary_span = pat.span; match self.tcx.hir().find_parent(pat.hir_id) { @@ -774,9 +770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } ( - Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Binary(_, lhs, rhs), .. - })), + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(_, lhs, rhs), .. }), Some(TypeError::Sorts(ExpectedFound { expected, .. })), ) if rhs.hir_id == expr.hir_id && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected) => @@ -797,8 +791,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else { return; }; - let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. })) = - self.tcx.opt_hir_node(parent) + let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) = + self.tcx.hir_node(parent) else { return; }; @@ -1022,13 +1016,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Local(bind_hir_id), .. }, )) = expr.kind { - let bind = self.tcx.opt_hir_node(*bind_hir_id); - let parent = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*bind_hir_id)); - if let Some(hir::Node::Pat(hir::Pat { - kind: hir::PatKind::Binding(_, _hir_id, _, _), - .. - })) = bind - && let Some(hir::Node::Pat(hir::Pat { default_binding_modes: false, .. })) = parent + let bind = self.tcx.hir_node(*bind_hir_id); + let parent = self.tcx.hir_node(self.tcx.hir().parent_id(*bind_hir_id)); + if let hir::Node::Pat(hir::Pat { + kind: hir::PatKind::Binding(_, _hir_id, _, _), .. + }) = bind + && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent { return true; } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 0695af15b16f8..10e12d01b1fe6 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, - MultiSpan, SubdiagnosticMessage, + MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -83,14 +83,6 @@ pub struct MethodCallOnUnknownRawPointee { pub span: Span, } -#[derive(Diagnostic)] -#[diag(hir_typeck_missing_fn_lang_items)] -#[help] -pub struct MissingFnLangItems { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)] pub struct FunctionalRecordUpdateOnNonStruct { @@ -193,14 +185,6 @@ pub struct AddMissingParenthesesInRange { pub right: Span, } -#[derive(Diagnostic)] -#[diag(hir_typeck_op_trait_generic_params)] -pub struct OpMethodGenericParams { - #[primary_span] - pub span: Span, - pub method_name: String, -} - pub struct TypeMismatchFruTypo { /// Span of the LHS of the range pub expr_span: Span, @@ -211,10 +195,7 @@ pub struct TypeMismatchFruTypo { } impl AddToDiagnostic for TypeMismatchFruTypo { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up @@ -389,10 +370,7 @@ pub struct RemoveSemiForCoerce { } impl AddToDiagnostic for RemoveSemiForCoerce { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); @@ -563,14 +541,8 @@ pub enum CastUnknownPointerSub { From(Span), } -impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn( - &mut Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { +impl AddToDiagnostic for CastUnknownPointerSub { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { match self { CastUnknownPointerSub::To(span) => { let msg = f(diag, crate::fluent_generated::hir_typeck_label_to); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d00ae4db300be..292b85eb97f7f 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, ) -> Ty<'tcx> { - self.check_expr_with_expectation_and_args(expr, expected, &[]) + self.check_expr_with_expectation_and_args(expr, expected, &[], None) } /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a @@ -187,6 +187,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, expected: Expectation<'tcx>, args: &'tcx [hir::Expr<'tcx>], + call: Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { if self.tcx().sess.verbose_internals() { // make this code only run with -Zverbose-internals because it is probably slow @@ -233,7 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = ensure_sufficient_stack(|| match &expr.kind { hir::ExprKind::Path( qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)), - ) => self.check_expr_path(qpath, expr, args), + ) => self.check_expr_path(qpath, expr, args, call), _ => self.check_expr_kind(expr, expected), }); let ty = self.resolve_vars_if_possible(ty); @@ -300,7 +301,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Path(QPath::LangItem(lang_item, _)) => { self.check_lang_item_path(lang_item, expr) } - ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), + ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[], None), ExprKind::InlineAsm(asm) => { // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars). self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id)); @@ -514,6 +515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &'tcx hir::QPath<'tcx>, expr: &'tcx hir::Expr<'tcx>, args: &'tcx [hir::Expr<'tcx>], + call: Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { let tcx = self.tcx; let (res, opt_ty, segs) = @@ -530,7 +532,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value"); Ty::new_error(tcx, e) } - _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, + _ => { + self.instantiate_value_path( + segs, + opt_ty, + res, + call.map_or(expr.span, |e| e.span), + expr.span, + expr.hir_id, + ) + .0 + } }; if let ty::FnDef(did, _) = *ty.kind() { @@ -585,7 +597,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::FnCall, fn_sig.output(), ); - self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); + self.require_type_is_sized_deferred( + output, + call.map_or(expr.span, |e| e.span), + traits::SizedCallReturnType, + ); } // We always require that the type provided as the value for @@ -984,7 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( lhs.span.shrink_to_hi(), "you might have meant to write a semicolon here", - ";".to_string(), + ";", Applicability::MachineApplicable, ); return true; @@ -1001,7 +1017,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { then: impl FnOnce(&hir::Expr<'_>), ) { let mut parent = self.tcx.hir().parent_id(original_expr_id); - while let Some(node) = self.tcx.opt_hir_node(parent) { + loop { + let node = self.tcx.hir_node(parent); match node { hir::Node::Expr(hir::Expr { kind: @@ -1102,7 +1119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We won't diverge unless both branches do (or the condition does). self.diverges.set(cond_diverges | then_diverges & else_diverges); } else { - self.if_fallback_coercion(sp, then_expr, &mut coerce); + self.if_fallback_coercion(sp, cond_expr, then_expr, &mut coerce); // If the condition is false we can't diverge. self.diverges.set(cond_diverges); @@ -1455,8 +1472,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let hir::TyKind::Array(_, length) = ty.peel_refs().kind && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length - && let Some(span) = self.tcx.hir().opt_span(hir_id) { + let span = self.tcx.hir().span(hir_id); match self.dcx().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) { Some(mut err) => { err.span_suggestion( @@ -1950,6 +1967,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let len = remaining_fields.len(); + #[allow(rustc::potential_query_instability)] let mut displayable_field_names: Vec<&str> = remaining_fields.keys().map(|ident| ident.as_str()).collect(); // sorting &str primitives here, sort_unstable is ok diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index e99489ee3c03c..36c3eef82fccb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -521,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// We must not attempt to select obligations after this method has run, or risk query cycle /// ICE. #[instrument(level = "debug", skip(self))] - pub(in super::super) fn resolve_coroutine_interiors(&self, def_id: DefId) { + pub(in super::super) fn resolve_coroutine_interiors(&self) { // Try selecting all obligations that are not blocked on inference variables. // Once we start unifying coroutine witnesses, trying to select obligations on them will // trigger query cycle ICEs, as doing so requires MIR. @@ -1073,6 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty: Option>, res: Res, span: Span, + path_span: Span, hir_id: hir::HirId, ) -> (Ty<'tcx>, Res) { let tcx = self.tcx; @@ -1104,13 +1105,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let container_id = assoc_item.container_id(tcx); debug!(?def_id, ?container, ?container_id); match container { - ty::TraitContainer => callee::check_legal_trait_for_method_call( - tcx, - span, - None, - span, - container_id, - ), + ty::TraitContainer => { + if let Err(e) = callee::check_legal_trait_for_method_call( + tcx, + path_span, + None, + span, + container_id, + ) { + self.set_tainted_by_errors(e); + } + } ty::ImplContainer => { if segments.len() == 1 { // `::assoc` will end up here, and so @@ -1174,14 +1179,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // parameter internally, but we don't allow users to specify the // parameter's value explicitly, so we have to do some error- // checking here. - let arg_count = check_generic_arg_count_for_call( - tcx, - span, - def_id, - generics, - seg, - IsMethodCall::No, - ); + let arg_count = + check_generic_arg_count_for_call(tcx, def_id, generics, seg, IsMethodCall::No); if let ExplicitLateBound::Yes = arg_count.explicit_late_bound { explicit_late_bound = ExplicitLateBound::Yes; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 2494feee1ff1d..35b3f27d79127 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -426,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|vars| self.resolve_vars_if_possible(vars)), ); - self.report_arg_errors( + self.set_tainted_by_errors(self.report_arg_errors( compatibility_diagonal, formal_and_expected_inputs, provided_args, @@ -435,7 +435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_def_id, call_span, call_expr, - ); + )); } } @@ -449,7 +449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn_def_id: Option, call_span: Span, call_expr: &'tcx hir::Expr<'tcx>, - ) { + ) -> ErrorGuaranteed { // Next, let's construct the error let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind { hir::ExprKind::Call( @@ -488,10 +488,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let tcx = self.tcx; - // FIXME: taint after emitting errors and pass through an `ErrorGuaranteed` - self.set_tainted_by_errors( - tcx.dcx().span_delayed_bug(call_span, "no errors reported for args"), - ); // Get the argument span in the context of the call span so that // suggestions and labels are (more) correct when an arg is a @@ -698,8 +694,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(mismatch_idx), is_method, ); - err.emit(); - return; + return err.emit(); } } } @@ -723,11 +718,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if cfg!(debug_assertions) { span_bug!(error_span, "expected errors from argument matrix"); } else { - tcx.dcx().emit_err(errors::ArgMismatchIndeterminate { span: error_span }); + return tcx.dcx().emit_err(errors::ArgMismatchIndeterminate { span: error_span }); } - return; } + let mut reported = None; errors.retain(|error| { let Error::Invalid(provided_idx, expected_idx, Compatibility::Incompatible(Some(e))) = error @@ -738,16 +733,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) { - self.err_ctxt().report_and_explain_type_error(trace, *e).emit(); + reported = Some(self.err_ctxt().report_and_explain_type_error(trace, *e).emit()); return false; } true }); // We're done if we found errors, but we already emitted them. - if errors.is_empty() { - return; + if let Some(reported) = reported { + assert!(errors.is_empty()); + return reported; } + assert!(!errors.is_empty()); // Okay, now that we've emitted the special errors separately, we // are only left missing/extra/swapped and mismatched arguments, both @@ -804,8 +801,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(expected_idx.as_usize()), is_method, ); - err.emit(); - return; + return err.emit(); } let mut err = if formal_and_expected_inputs.len() == provided_args.len() { @@ -1253,7 +1249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - err.emit(); + err.emit() } fn suggest_ptr_null_mut( @@ -2064,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let node = self .tcx .opt_local_def_id_to_hir_id(self.tcx.hir().get_parent_item(call_expr.hir_id)) - .and_then(|hir_id| self.tcx.opt_hir_node(hir_id)); + .map(|hir_id| self.tcx.hir_node(hir_id)); match node { Some(hir::Node::Item(item)) => call_finder.visit_item(item), Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 449de631f5a20..ad4546c09b546 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -45,14 +45,6 @@ pub struct FnCtxt<'a, 'tcx> { /// eventually). pub(super) param_env: ty::ParamEnv<'tcx>, - /// Number of errors that had been reported when we started - /// checking this function. On exit, if we find that *more* errors - /// have been reported, we will skip regionck and other work that - /// expects the types within the function to be consistent. - // FIXME(matthewjasper) This should not exist, and it's not correct - // if type checking is run in parallel. - err_count_on_creation: usize, - /// If `Some`, this stores coercion information for returned /// expressions. If `None`, this is in a context where return is /// inappropriate, such as a const expression. @@ -126,7 +118,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { FnCtxt { body_id, param_env, - err_count_on_creation: inh.tcx.dcx().err_count(), ret_coercion: None, ret_coercion_span: Cell::new(None), coroutine_types: None, @@ -195,10 +186,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }), } } - - pub fn errors_reported_since_creation(&self) -> bool { - self.dcx().err_count() > self.err_count_on_creation - } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 95c1139e43e44..ed0bdb9bdaa0d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -261,6 +261,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.kind && let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) && self.can_coerce(recv_ty, expected) + && let name = method.name.as_str() + && (name.starts_with("to_") || name.starts_with("as_") || name == "into") { let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) { expr.span.with_lo(recv_span.hi()) @@ -680,8 +682,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is and we were expecting a Box, ergo Pin>, we // can suggest Box::pin. let parent = self.tcx.hir().parent_id(expr.hir_id); - let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = - self.tcx.opt_hir_node(parent) + let Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. }) = + self.tcx.hir_node(parent) else { return false; }; @@ -906,9 +908,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::Param(expected_ty_as_param) = expected.kind() else { return }; - let fn_node = self.tcx.opt_hir_node(fn_id); + let fn_node = self.tcx.hir_node(fn_id); - let Some(hir::Node::Item(hir::Item { + let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn( hir::FnSig { @@ -919,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _body_id, ), .. - })) = fn_node + }) = fn_node else { return; }; @@ -1051,9 +1053,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let ty = self.normalize(expr.span, ty); if self.can_coerce(found, ty) { - if let Some(node) = self.tcx.opt_hir_node(fn_id) - && let Some(owner_node) = node.as_owner() - && let Some(span) = expr.span.find_ancestor_inside(owner_node.span()) + if let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner() + && let Some(span) = expr.span.find_ancestor_inside(*owner_node.span()) { err.multipart_suggestion( "you might have meant to return this value", @@ -1682,15 +1683,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { segments: [_], res: crate::Res::Local(binding), .. }, )) => { - let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.opt_hir_node(*binding) - else { - return expr; - }; - let Some(parent) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) else { + let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding) else { return expr; }; - match parent { + match self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id)) { // foo.clone() hir::Node::Local(hir::Local { init: Some(init), .. }) => { self.note_type_is_not_clone_inner_expr(init) @@ -1701,8 +1698,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: hir::PatKind::Tuple(pats, ..), .. }) => { - let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) = - self.tcx.opt_hir_node(self.tcx.hir().parent_id(*pat_hir_id)) + let hir::Node::Local(hir::Local { init: Some(init), .. }) = + self.tcx.hir_node(self.tcx.hir().parent_id(*pat_hir_id)) else { return expr; }; @@ -1734,10 +1731,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr_kind && let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } = call_expr_path - && let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = - self.tcx.opt_hir_node(*binding) - && let Some(closure) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) - && let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure + && let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding) + && let hir::Node::Local(hir::Local { init: Some(init), .. }) = + self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id)) && let Expr { kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }), .. @@ -1977,20 +1973,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unroll desugaring, to make sure this works for `for` loops etc. loop { parent = self.tcx.hir().parent_id(id); - if let Some(parent_span) = self.tcx.hir().opt_span(parent) { - if parent_span.find_ancestor_inside(expr.span).is_some() { - // The parent node is part of the same span, so is the result of the - // same expansion/desugaring and not the 'real' parent node. - id = parent; - continue; - } + let parent_span = self.tcx.hir().span(parent); + if parent_span.find_ancestor_inside(expr.span).is_some() { + // The parent node is part of the same span, so is the result of the + // same expansion/desugaring and not the 'real' parent node. + id = parent; + continue; } break; } - if let Some(hir::Node::Block(&hir::Block { - span: block_span, expr: Some(e), .. - })) = self.tcx.opt_hir_node(parent) + if let hir::Node::Block(&hir::Block { span: block_span, expr: Some(e), .. }) = + self.tcx.hir_node(parent) { if e.hir_id == id { if let Some(span) = expr.span.find_ancestor_inside(block_span) { @@ -2218,30 +2212,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let local_parent = self.tcx.hir().parent_id(local_id); - let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = - self.tcx.opt_hir_node(local_parent) + let Node::Param(hir::Param { hir_id: param_hir_id, .. }) = self.tcx.hir_node(local_parent) else { return None; }; let param_parent = self.tcx.hir().parent_id(*param_hir_id); - let Some(Node::Expr(hir::Expr { + let Node::Expr(hir::Expr { hir_id: expr_hir_id, kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }), .. - })) = self.tcx.opt_hir_node(param_parent) + }) = self.tcx.hir_node(param_parent) else { return None; }; let expr_parent = self.tcx.hir().parent_id(*expr_hir_id); - let hir = self.tcx.opt_hir_node(expr_parent); + let hir = self.tcx.hir_node(expr_parent); let closure_params_len = closure_fn_decl.inputs.len(); let ( - Some(Node::Expr(hir::Expr { + Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(method_path, receiver, ..), .. - })), + }), 1, ) = (hir, closure_params_len) else { @@ -2672,10 +2665,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool { if let hir::ExprKind::If(..) = expr.kind { let parent_id = self.tcx.hir().parent_id(expr.hir_id); - if let Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::If(_, _, Some(else_expr)), - .. - })) = self.tcx.opt_hir_node(parent_id) + if let Node::Expr(hir::Expr { + kind: hir::ExprKind::If(_, _, Some(else_expr)), .. + }) = self.tcx.hir_node(parent_id) { return else_expr.hir_id == expr.hir_id; } @@ -3065,7 +3057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; let parent = self.tcx.hir().parent_id(expr.hir_id); - if let Some(hir::Node::ExprField(_)) = self.tcx.opt_hir_node(parent) { + if let hir::Node::ExprField(_) = self.tcx.hir_node(parent) { // Ignore `Foo { field: a..Default::default() }` return; } @@ -3144,7 +3136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::def::Res::Local(hir_id) = path.res else { return; }; - let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else { + let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else { return; }; let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) = diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 36aa949668ff3..315dc4330ad32 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(try_blocks)] @@ -286,7 +288,7 @@ fn typeck_with_fallback<'tcx>( debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations()); // This must be the last thing before `report_ambiguity_errors`. - fcx.resolve_coroutine_interiors(def_id.to_def_id()); + fcx.resolve_coroutine_interiors(); debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations()); @@ -444,15 +446,6 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! { diag.emit() } -/// `expected` here is the expected number of explicit generic arguments on the trait. -fn has_expected_num_generic_args(tcx: TyCtxt<'_>, trait_did: DefId, expected: usize) -> bool { - let generics = tcx.generics_of(trait_did); - generics.count() - == expected - + if generics.has_self { 1 } else { 0 } - + if generics.host_effect_index.is_some() { 1 } else { 0 } -} - pub fn provide(providers: &mut Providers) { method::provide(providers); *providers = Providers { diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 1ce0240f7b830..f9297550c573c 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -436,7 +436,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { pub(crate) fn cat_rvalue( &self, hir_id: hir::HirId, - span: Span, + // FIXME: remove + _span: Span, expr_ty: Ty<'tcx>, ) -> PlaceWithHirId<'tcx> { PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new()) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 6f18cc51b11c1..3a44c6c241041 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -356,7 +356,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let arg_count_correct = check_generic_arg_count_for_call( self.tcx, - self.span, pick.item.def_id, generics, seg, @@ -630,13 +629,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) { // Disallow calls to the method `drop` defined in the `Drop` trait. if let Some(trait_def_id) = pick.item.trait_container(self.tcx) { - callee::check_legal_trait_for_method_call( + if let Err(e) = callee::check_legal_trait_for_method_call( self.tcx, self.span, Some(self.self_expr.span), self.call_expr.span, trait_def_id, - ) + ) { + self.set_tainted_by_errors(e); + } } } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index af172b59a1467..804d6ff2cb577 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -10,7 +10,6 @@ mod suggest; pub use self::suggest::SelfSource; pub use self::MethodError::*; -use crate::errors::OpMethodGenericParams; use crate::FnCtxt; use rustc_errors::{Applicability, Diagnostic, SubdiagnosticMessage}; use rustc_hir as hir; @@ -385,26 +384,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // type parameters or early-bound regions. let tcx = self.tcx; let Some(method_item) = self.associated_value(trait_def_id, m_name) else { - tcx.dcx().span_delayed_bug( - obligation.cause.span, - "operator trait does not have corresponding operator method", - ); - return None; + bug!("expected associated item for operator trait") }; - if method_item.kind != ty::AssocKind::Fn { - self.dcx().span_delayed_bug(tcx.def_span(method_item.def_id), "not a method"); - return None; - } - let def_id = method_item.def_id; - let generics = tcx.generics_of(def_id); - - if generics.params.len() != 0 { - tcx.dcx().emit_fatal(OpMethodGenericParams { - span: tcx.def_span(method_item.def_id), - method_name: m_name.to_string(), - }); + if method_item.kind != ty::AssocKind::Fn { + span_bug!(tcx.def_span(def_id), "expected `{m_name}` to be an associated function"); } debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 6c9501e93fa11..81b8239351547 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -57,6 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match ty.kind() { // Not all of these (e.g., unsafe fns) implement `FnOnce`, // so we look for these beforehand. + // FIXME(async_closures): These don't impl `FnOnce` by default. ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true, // If it's not a simple function, look for things which implement `FnOnce`. _ => { @@ -229,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind && let hir::def::Res::Local(hir_id) = path.res - && let Some(hir::Node::Pat(b)) = self.tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(b) = self.tcx.hir_node(hir_id) && let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id) && let Some(node) = self.tcx.hir().find_parent(p.hir_id) && let Some(decl) = node.fn_decl() @@ -540,6 +541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_spans: SortedMap> = Default::default(); let mut restrict_type_params = false; + let mut suggested_derive = false; let mut unsatisfied_bounds = false; if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { let msg = "consider using `len` instead"; @@ -554,6 +556,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement" )); } + } else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) { + // We special case the situation where we are looking for `_` in + // `::method` because otherwise the machinery will look for blanket + // implementations that have unsatisfied trait bounds to suggest, leading us to claim + // things like "we're looking for a trait with method `cmp`, both `Iterator` and `Ord` + // have one, in order to implement `Ord` you need to restrict `TypeParam: FnPtr` so + // that `impl Ord for T` can apply", which is not what we want. We have a type + // parameter, we want to directly say "`Ord::cmp` and `Iterator::cmp` exist, restrict + // `TypeParam: Ord` or `TypeParam: Iterator`"". That is done further down when calling + // `self.suggest_traits_to_import`, so we ignore the `unsatisfied_predicates` + // suggestions. } else if !unsatisfied_predicates.is_empty() { let mut type_params = FxIndexMap::default(); @@ -916,20 +929,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .enumerate() .collect::>(); - for ((span, add_where_or_comma), obligations) in type_params.into_iter() { - restrict_type_params = true; - // #74886: Sort here so that the output is always the same. - let obligations = obligations.into_sorted_stable_ord(); - err.span_suggestion_verbose( - span, - format!( - "consider restricting the type parameter{s} to satisfy the \ - trait bound{s}", - s = pluralize!(obligations.len()) - ), - format!("{} {}", add_where_or_comma, obligations.join(", ")), - Applicability::MaybeIncorrect, - ); + if !matches!(rcvr_ty.peel_refs().kind(), ty::Param(_)) { + for ((span, add_where_or_comma), obligations) in type_params.into_iter() { + restrict_type_params = true; + // #74886: Sort here so that the output is always the same. + let obligations = obligations.into_sorted_stable_ord(); + err.span_suggestion_verbose( + span, + format!( + "consider restricting the type parameter{s} to satisfy the trait \ + bound{s}", + s = pluralize!(obligations.len()) + ), + format!("{} {}", add_where_or_comma, obligations.join(", ")), + Applicability::MaybeIncorrect, + ); + } } bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically. @@ -977,7 +992,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the following trait bounds were not satisfied:\n{bound_list}" )); } - self.suggest_derive(&mut err, unsatisfied_predicates); + suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates); unsatisfied_bounds = true; } @@ -1116,9 +1131,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name.span, format!( "you might have meant to use `{}`", - inherent_method.name.as_str() + inherent_method.name ), - inherent_method.name.as_str(), + inherent_method.name, Applicability::MaybeIncorrect, ); break 'outer; @@ -1200,7 +1215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params { + if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive { } else { self.suggest_traits_to_import( &mut err, @@ -1210,7 +1225,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args.map(|args| args.len() + 1), source, no_match_data.out_of_scope_traits.clone(), - unsatisfied_predicates, static_candidates, unsatisfied_bounds, expected.only_has_type(self), @@ -1325,7 +1339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); - return Some(err); + Some(err) } fn note_candidates_on_method_error( @@ -2003,7 +2017,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { visitor.visit_body(body); let parent = self.tcx.hir().parent_id(seg1.hir_id); - if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent) + if let Node::Expr(call_expr) = self.tcx.hir_node(parent) && let Some(expr) = visitor.result && let Some(self_ty) = self.node_ty_opt(expr.hir_id) { @@ -2019,7 +2033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diag.span_suggestion_verbose( sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':').unwrap(), "you may have meant to call an instance method", - ".".to_string(), + ".", Applicability::MaybeIncorrect, ); } @@ -2470,7 +2484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Option>, Option>, )], - ) { + ) -> bool { let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates); derives.sort(); derives.dedup(); @@ -2495,6 +2509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } + !derives_grouped.is_empty() } fn note_derefed_ty_has_method( @@ -2697,11 +2712,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inputs_len: Option, source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec, - unsatisfied_predicates: &[( - ty::Predicate<'tcx>, - Option>, - Option>, - )], static_candidates: &[CandidateSource], unsatisfied_bounds: bool, return_type: Option>, @@ -2918,19 +2928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). - unsatisfied_predicates.iter().all(|(p, _, _)| { - match p.kind().skip_binder() { - // Hide traits if they are present in predicates as they can be fixed without - // having to implement them. - ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => { - t.def_id() == info.def_id - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => { - p.projection_ty.def_id == info.def_id - } - _ => false, - } - }) && (type_is_local || info.def_id.is_local()) + (type_is_local || info.def_id.is_local()) && !self.tcx.trait_is_auto(info.def_id) && self .associated_value(info.def_id, item_name) @@ -3253,7 +3251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let parent = self.tcx.hir().parent_id(expr.hir_id); - if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent) + if let Node::Expr(call_expr) = self.tcx.hir_node(parent) && let hir::ExprKind::MethodCall( hir::PathSegment { ident: method_name, .. }, self_expr, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index bbe6d9e967044..9ce6189856194 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -1,7 +1,7 @@ //! Code related to processing overloaded binary and unary operators. use super::method::MethodCallee; -use super::{has_expected_num_generic_args, FnCtxt}; +use super::FnCtxt; use crate::Expectation; use rustc_ast as ast; use rustc_data_structures::packed::Pu128; @@ -887,25 +887,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty, op, opname, trait_did ); - // Catches cases like #83893, where a lang item is declared with the - // wrong number of generic arguments. Should have yielded an error - // elsewhere by now, but we have to catch it here so that we do not - // index `other_tys` out of bounds (if the lang item has too many - // generic arguments, `other_tys` is too short). - if !has_expected_num_generic_args( - self.tcx, - trait_did, - match op { - // Binary ops have a generic right-hand side, unary ops don't - Op::Binary(..) => 1, - Op::Unary(..) => 0, - }, - ) { - self.dcx() - .span_delayed_bug(span, "operator didn't have the right number of generic args"); - return Err(vec![]); - } - let opname = Ident::with_dummy_span(opname); let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip(); let input_types = opt_rhs_ty.as_slice(); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index a611d0eda8574..fcf4b59e93fcd 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -576,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if (lhs, rhs).references_error() { err.downgrade_to_delayed_bug(); } - if self.tcx.sess.teach(err.get_code().unwrap()) { + if self.tcx.sess.teach(err.code.unwrap()) { err.note( "In a match expression, only numbers and characters can be matched \ against a range. This is because the compiler checks that the range \ @@ -847,7 +847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { type_str ); err.span_label(span, format!("type `{type_str}` cannot be dereferenced")); - if self.tcx.sess.teach(err.get_code().unwrap()) { + if self.tcx.sess.teach(err.code.unwrap()) { err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ); } return Err(err.emit()); @@ -923,7 +923,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type-check the path. let (pat_ty, pat_res) = - self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id); + self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id); if let Some(err) = self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty) { @@ -1078,7 +1078,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type-check the path. let (pat_ty, res) = - self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id); + self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id); if !pat_ty.is_fn() { let e = report_unexpected_res(res); return Ty::new_error(tcx, e); @@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if tcx.sess.teach(err.get_code().unwrap()) { + if tcx.sess.teach(err.code.unwrap()) { err.note( "This error indicates that a struct pattern attempted to \ extract a nonexistent field from a struct. Struct fields \ diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index d626176377283..1eaaf30043b44 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -1,5 +1,5 @@ use crate::method::MethodCallee; -use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp}; +use crate::{FnCtxt, PlaceOp}; use rustc_ast as ast; use rustc_errors::Applicability; use rustc_hir as hir; @@ -209,20 +209,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - // If the lang item was declared incorrectly, stop here so that we don't - // run into an ICE (#83893). The error is reported where the lang item is - // declared. - if !has_expected_num_generic_args( - self.tcx, - imm_tr, - match op { - PlaceOp::Deref => 0, - PlaceOp::Index => 1, - }, - ) { - return None; - } - self.lookup_method_in_trait( self.misc(span), Ident::with_dummy_span(imm_op), @@ -249,20 +235,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - // If the lang item was declared incorrectly, stop here so that we don't - // run into an ICE (#83893). The error is reported where the lang item is - // declared. - if !has_expected_num_generic_args( - self.tcx, - mut_tr, - match op { - PlaceOp::Deref => 0, - PlaceOp::Index => 1, - }, - ) { - return None; - } - self.lookup_method_in_trait( self.misc(span), Ident::with_dummy_span(mut_op), diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index b9b3ed53dae8f..34ce0ab1f8b98 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -73,9 +73,7 @@ pub fn resolve_rvalue_scopes<'a, 'tcx>( debug!("start resolving rvalue scopes, def_id={def_id:?}"); debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates); for (&hir_id, candidate) in &scope_tree.rvalue_candidates { - let Some(Node::Expr(expr)) = tcx.opt_hir_node(hir_id) else { - bug!("hir node does not exist") - }; + let Node::Expr(expr) = tcx.hir_node(hir_id) else { bug!("hir node does not exist") }; record_rvalue_scope(&mut rvalue_scopes, expr, candidate); } rvalue_scopes diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 82c5e566f161c..211109b59417a 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -170,9 +170,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { // Extract the type of the closure. let ty = self.node_ty(closure_hir_id); - let (closure_def_id, args) = match *ty.kind() { - ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args)), - ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args)), + let (closure_def_id, args, infer_kind) = match *ty.kind() { + ty::Closure(def_id, args) => { + (def_id, UpvarArgs::Closure(args), self.closure_kind(ty).is_none()) + } + ty::CoroutineClosure(def_id, args) => { + (def_id, UpvarArgs::CoroutineClosure(args), self.closure_kind(ty).is_none()) + } + ty::Coroutine(def_id, args) => (def_id, UpvarArgs::Coroutine(args), false), ty::Error(_) => { // #51714: skip analysis when we have already encountered type errors return; @@ -188,18 +193,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let closure_def_id = closure_def_id.expect_local(); - let infer_kind = if let UpvarArgs::Closure(closure_args) = args { - self.closure_kind(closure_args).is_none().then_some(closure_args) - } else { - None - }; - assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id); let mut delegate = InferBorrowKind { closure_def_id, capture_information: Default::default(), fake_reads: Default::default(), }; + + // As noted in `lower_coroutine_body_with_moved_arguments`, we default the capture mode + // to `ByRef` for the `async {}` block internal to async fns/closure. This means + // that we would *not* be moving all of the parameters into the async block by default. + // + // We force all of these arguments to be captured by move before we do expr use analysis. + // + // FIXME(async_closures): This could be cleaned up. It's a bit janky that we're just + // moving all of the `LocalSource::AsyncFn` locals here. + if let Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Fn | hir::CoroutineSource::Closure, + )) = self.tcx.coroutine_kind(closure_def_id) + { + let hir::ExprKind::Block(block, _) = body.value.kind else { + bug!(); + }; + for stmt in block.stmts { + let hir::StmtKind::Local(hir::Local { + init: Some(init), + source: hir::LocalSource::AsyncFn, + pat, + .. + }) = stmt.kind + else { + bug!(); + }; + let hir::PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), _, _, _) = + pat.kind + else { + // Complex pattern, skip the non-upvar local. + continue; + }; + let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = init.kind else { + bug!(); + }; + let hir::def::Res::Local(local_id) = path.res else { + bug!(); + }; + let place = self.place_for_root_variable(closure_def_id, local_id); + delegate.capture_information.push(( + place, + ty::CaptureInfo { + capture_kind_expr_id: Some(init.hir_id), + path_expr_id: Some(init.hir_id), + capture_kind: UpvarCapture::ByValue, + }, + )); + } + } + euv::ExprUseVisitor::new( &mut delegate, &self.infcx, @@ -257,10 +307,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let before_feature_tys = self.final_upvar_tys(closure_def_id); - if let Some(closure_args) = infer_kind { + if infer_kind { // Unify the (as yet unbound) type variable in the closure // args with the kind we inferred. - let closure_kind_ty = closure_args.as_closure().kind_ty(); + let closure_kind_ty = match args { + UpvarArgs::Closure(args) => args.as_closure().kind_ty(), + UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().kind_ty(), + UpvarArgs::Coroutine(_) => unreachable!("coroutines don't have an inferred kind"), + }; self.demand_eqtype( span, Ty::from_closure_kind(self.tcx, closure_kind), @@ -282,6 +336,84 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + // For coroutine-closures, we additionally must compute the + // `coroutine_captures_by_ref_ty` type, which is used to generate the by-ref + // version of the coroutine-closure's output coroutine. + if let UpvarArgs::CoroutineClosure(args) = args { + let closure_env_region: ty::Region<'_> = ty::Region::new_bound( + self.tcx, + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(0), + kind: ty::BoundRegionKind::BrEnv, + }, + ); + let tupled_upvars_ty_for_borrow = Ty::new_tup_from_iter( + self.tcx, + self.typeck_results + .borrow() + .closure_min_captures_flattened( + self.tcx.coroutine_for_closure(closure_def_id).expect_local(), + ) + // Skip the captures that are just moving the closure's args + // into the coroutine. These are always by move, and we append + // those later in the `CoroutineClosureSignature` helper functions. + .skip( + args.as_coroutine_closure() + .coroutine_closure_sig() + .skip_binder() + .tupled_inputs_ty + .tuple_fields() + .len(), + ) + .map(|captured_place| { + let upvar_ty = captured_place.place.ty(); + let capture = captured_place.info.capture_kind; + // Not all upvars are captured by ref, so use + // `apply_capture_kind_on_capture_ty` to ensure that we + // compute the right captured type. + apply_capture_kind_on_capture_ty( + self.tcx, + upvar_ty, + capture, + Some(closure_env_region), + ) + }), + ); + let coroutine_captures_by_ref_ty = Ty::new_fn_ptr( + self.tcx, + ty::Binder::bind_with_vars( + self.tcx.mk_fn_sig( + [], + tupled_upvars_ty_for_borrow, + false, + hir::Unsafety::Normal, + rustc_target::spec::abi::Abi::Rust, + ), + self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region( + ty::BoundRegionKind::BrEnv, + )]), + ), + ); + self.demand_eqtype( + span, + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + coroutine_captures_by_ref_ty, + ); + + // Additionally, we can now constrain the coroutine's kind type. + let ty::Coroutine(_, coroutine_args) = + *self.typeck_results.borrow().expr_ty(body.value).kind() + else { + bug!(); + }; + self.demand_eqtype( + span, + coroutine_args.as_coroutine().kind_ty(), + Ty::from_closure_kind(self.tcx, closure_kind), + ); + } + self.log_closure_min_capture_info(closure_def_id, span); // Now that we've analyzed the closure, we know how each @@ -551,7 +683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Go through each entry in the current list of min_captures - // - if ancestor is found, update it's capture kind to account for current place's + // - if ancestor is found, update its capture kind to account for current place's // capture information. // // - if descendant is found, remove it from the list, and update the current place's @@ -840,9 +972,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) { if s.starts_with('$') { // Looks like a macro fragment. Try to find the real block. - if let Some(hir::Node::Expr(&hir::Expr { + if let hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Block(block, ..), .. - })) = self.tcx.opt_hir_node(body_id.hir_id) { + }) = self.tcx.hir_node(body_id.hir_id) { // If the body is a block (with `{..}`), we use the span of that block. // E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`. // Since we know it's a block, we know we can insert the `let _ = ..` without diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 3430a5fb00dc9..94f6c06157efe 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -753,10 +753,14 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { } fn report_error(&self, p: impl Into>) -> ErrorGuaranteed { - match self.fcx.dcx().has_errors() { - Some(e) => e, - None => self - .fcx + if let Some(guar) = self.fcx.dcx().has_errors() { + guar + } else if self.fcx.dcx().stashed_err_count() > 0 { + // Without this case we sometimes get uninteresting and extraneous + // "type annotations needed" errors. + self.fcx.dcx().delayed_bug("error in Resolver") + } else { + self.fcx .err_ctxt() .emit_inference_failure_err( self.fcx.tcx.hir().body_owner_def_id(self.body.id()), @@ -765,7 +769,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { E0282, false, ) - .emit(), + .emit() } } diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 6f909a0cc9db4..aa6f184a2d7d1 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -131,7 +131,7 @@ impl<'tcx> IfThisChanged<'tcx> { None => DepNode::from_def_path_hash( self.tcx, def_path_hash, - dep_kinds::hir_owner_nodes, + dep_kinds::opt_hir_owner_nodes, ), Some(n) => { match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 82f02b7d47aac..0729986f32fdf 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -5,8 +5,6 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 842cc9fae9b4d..14cc8c260e218 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -57,8 +57,8 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ - // hir_owner_nodes should be computed for all nodes - label_strs::hir_owner_nodes, + // opt_hir_owner_nodes should be computed for all nodes + label_strs::opt_hir_owner_nodes, ]; /// `impl` implementation of struct/trait diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 854841206b89b..6fcb3a024ab6f 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![cfg_attr( feature = "nightly", feature(extend_one, min_specialization, new_uninit, step_trait, test) diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs index 72567b43a5f84..532cac5791e06 100644 --- a/compiler/rustc_index_macros/src/lib.rs +++ b/compiler/rustc_index_macros/src/lib.rs @@ -31,17 +31,17 @@ mod newtype; /// - `#[max = 0xFFFF_FFFD]`: specifies the max value, which allows niche /// optimizations. The default max value is 0xFFFF_FF00. /// - `#[gate_rustc_only]`: makes parts of the generated code nightly-only. -/// -/// `SpecOptionPartialEq` is specialized by this macro, so using it requires enabling -/// `#![feature(min_specialization)]` for the crate. #[proc_macro] #[cfg_attr( feature = "nightly", - allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq) + allow_internal_unstable( + step_trait, + rustc_attrs, + trusted_step, + spec_option_partial_eq, + min_specialization + ) )] -// FIXME: Remove the above comment about `min_specialization` once bootstrap is bumped, -// and the corresponding one on SpecOptionPartialEq -#[cfg_attr(all(feature = "nightly", not(bootstrap)), allow_internal_unstable(min_specialization))] pub fn newtype_index(input: TokenStream) -> TokenStream { newtype::newtype(input) } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 0a128218c9229..8bfc05d6a96db 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,7 +1,7 @@ use hir::GenericParamKind; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, - DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, + DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp, }; use rustc_hir as hir; use rustc_hir::FnRetTy; @@ -225,10 +225,7 @@ pub enum RegionOriginNote<'a> { } impl AddToDiagnostic for RegionOriginNote<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut label_or_note = |span, msg: DiagnosticMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); @@ -289,10 +286,7 @@ pub enum LifetimeMismatchLabels { } impl AddToDiagnostic for LifetimeMismatchLabels { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { diag.span_label(param_span, fluent::infer_declared_different); @@ -336,10 +330,7 @@ pub struct AddLifetimeParamsSuggestion<'a> { } impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut mk_suggestion = || { let ( hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. }, @@ -437,10 +428,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { } impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, _: F) { self.unmet_requirements .push_span_label(self.binding_span, fluent::infer_msl_introduces_static); diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req); @@ -755,10 +743,7 @@ pub struct ConsiderBorrowingParamHelp { } impl AddToDiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required @@ -799,10 +784,7 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label); multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement); @@ -845,10 +827,7 @@ pub struct ReqIntroducedLocations { } impl AddToDiagnostic for ReqIntroducedLocations { - fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, f: F) { for sp in self.spans { self.span.push_span_label(sp, fluent::infer_ril_introduced_here); } @@ -867,10 +846,7 @@ pub struct MoreTargeted { } impl AddToDiagnostic for MoreTargeted { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _f: F) { diag.code(E0772); diag.primary_message(fluent::infer_more_targeted); diag.arg("ident", self.ident); @@ -1289,10 +1265,7 @@ pub struct SuggestTuplePatternMany { } impl AddToDiagnostic for SuggestTuplePatternMany { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { diag.arg("path", self.path); let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into()); diag.multipart_suggestions( diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 331e3633e908d..a59a4df77296d 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -1,6 +1,6 @@ use crate::fluent_generated as fluent; use crate::infer::error_reporting::nice_region_error::find_anon_type; -use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage}; +use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessageOp}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{symbol::kw, Span}; @@ -160,10 +160,7 @@ impl RegionExplanation<'_> { } impl AddToDiagnostic for RegionExplanation<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) { diag.arg("pref_kind", self.prefix); diag.arg("suff_kind", self.suffix); diag.arg("desc_kind", self.desc.kind); diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 0f1af81d9f04c..859593e119457 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -87,6 +87,7 @@ impl<'tcx> InferCtxt<'tcx> { reported_signature_mismatch: self.reported_signature_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), err_count_on_creation: self.err_count_on_creation, + stashed_err_count_on_creation: self.stashed_err_count_on_creation, universe: self.universe.clone(), intercrate, next_trait_solver: self.next_trait_solver, diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index e4b37f05b778f..156a4f7101763 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -414,6 +414,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Bool @@ -480,7 +481,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } ty::ConstKind::Infer(InferConst::EffectVar(vid)) => { match self.infcx.unwrap().probe_effect_var(vid) { - Some(value) => return self.fold_const(value.as_const(self.tcx)), + Some(value) => return self.fold_const(value), None => { return self.canonicalize_const_var( CanonicalVarInfo { kind: CanonicalVarKind::Effect }, diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 386fdb09ba5d5..1f68a5a9c6179 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -24,6 +24,7 @@ use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind}; use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind}; use rustc_index::IndexVec; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, List, Ty, TyCtxt}; @@ -152,7 +153,12 @@ impl<'tcx> InferCtxt<'tcx> { ) .into(), CanonicalVarKind::Effect => { - let vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; + let vid = self + .inner + .borrow_mut() + .effect_unification_table() + .new_key(EffectVarValue::Unknown) + .vid; ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool) .into() } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index db01b5bd70719..dd9ed80ca7242 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -71,6 +71,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError}; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; +use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{ self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -518,6 +519,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); } + + RegionResolutionError::CannotNormalize(clause, origin) => { + let clause: ty::Clause<'tcx> = + clause.map_bound(ty::ClauseKind::TypeOutlives).to_predicate(self.tcx); + self.tcx + .dcx() + .struct_span_err(origin.span(), format!("cannot normalize `{clause}`")) + .emit(); + } } } } @@ -559,7 +569,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { RegionResolutionError::GenericBoundFailure(..) => true, RegionResolutionError::ConcreteFailure(..) | RegionResolutionError::SubSupConflict(..) - | RegionResolutionError::UpperBoundUniverseConflict(..) => false, + | RegionResolutionError::UpperBoundUniverseConflict(..) + | RegionResolutionError::CannotNormalize(..) => false, }; let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { @@ -574,6 +585,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), + RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(), }); errors } @@ -2170,8 +2182,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let Some(tykind) = tykind && let hir::TyKind::Array(_, length) = tykind && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length - && let Some(span) = self.tcx.hir().opt_span(*hir_id) { + let span = self.tcx.hir().span(*hir_id); Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found }) } else { None @@ -2546,7 +2558,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { add_lt_suggs, new_lt: &new_lt, }; - match self.tcx.hir().expect_owner(lifetime_scope) { + match self.tcx.expect_hir_owner_node(lifetime_scope) { hir::OwnerNode::Item(i) => visitor.visit_item(i), hir::OwnerNode::ForeignItem(i) => visitor.visit_foreign_item(i), hir::OwnerNode::ImplItem(i) => visitor.visit_impl_item(i), @@ -2830,7 +2842,11 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { // say, also take a look at the error code, maybe we can // tailor to that. _ => match terr { - TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => Error0644, + TypeError::CyclicTy(ty) + if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() => + { + Error0644 + } TypeError::IntrinsicCast => Error0308, _ => Error0308, }, @@ -2877,7 +2893,9 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { // say, also take a look at the error code, maybe we can // tailor to that. _ => match terr { - TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_coroutine() => { + TypeError::CyclicTy(ty) + if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() => + { ObligationCauseFailureCode::ClosureSelfref { span } } TypeError::IntrinsicCast => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 7287fc26053fe..c637ab31cd214 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -883,7 +883,10 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { GenericArgKind::Type(ty) => { if matches!( ty.kind(), - ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::Coroutine(..) + ty::Alias(ty::Opaque, ..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) ) { // Opaque types can't be named by the user right now. // diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index a7d1c2ca66695..c8fd4e3a69286 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -443,7 +443,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if let hir::OwnerNode::Item(Item { kind: ItemKind::Impl(hir::Impl { self_ty, .. }), .. - }) = tcx.hir().owner(impl_did) + }) = tcx.hir_owner_node(impl_did) { Some((impl_item.ident, self_ty)) } else { diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 0e7c641e0e0b8..f884ca83073df 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -195,7 +195,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } diag.help("type parameters must be constrained to match other types"); - if tcx.sess.teach(diag.get_code().unwrap()) { + if tcx.sess.teach(diag.code.unwrap()) { diag.help( "given a type parameter `T` and a method `foo`: ``` @@ -228,7 +228,10 @@ impl Trait for X { #traits-as-parameters", ); } - (ty::Param(p), ty::Closure(..) | ty::Coroutine(..)) => { + ( + ty::Param(p), + ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..), + ) => { let generics = tcx.generics_of(body_owner_def_id); if let Some(param) = generics.opt_type_param(p, tcx) { let p_span = tcx.def_span(param.def_id); @@ -497,7 +500,7 @@ impl Trait for X { } CyclicTy(ty) => { // Watch out for various cases of cyclic types and try to explain. - if ty.is_closure() || ty.is_coroutine() { + if ty.is_closure() || ty.is_coroutine() || ty.is_coroutine_closure() { diag.note( "closures cannot capture themselves or take themselves as argument;\n\ this error may be the result of a recent compiler bug-fix,\n\ @@ -678,7 +681,7 @@ impl Trait for X { https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", ); } - if tcx.sess.teach(diag.get_code().unwrap()) { + if tcx.sess.teach(diag.code.unwrap()) { diag.help( "given an associated type `T` and a method `foo`: ``` diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index d256994d8d1fd..2d5fa1b5c7001 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -151,13 +151,8 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { - let opt_ct = self - .infcx - .inner - .borrow_mut() - .effect_unification_table() - .probe_value(v) - .map(|effect| effect.as_const(self.infcx.tcx)); + let opt_ct = + self.infcx.inner.borrow_mut().effect_unification_table().probe_value(v).known(); self.freshen_const( opt_ct, ty::InferConst::EffectVar(v), diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 0562c6ccfcf75..6137506d4a994 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -98,6 +98,8 @@ pub enum RegionResolutionError<'tcx> { SubregionOrigin<'tcx>, // cause of the constraint Region<'tcx>, // the placeholder `'b` ), + + CannotNormalize(ty::PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>), } impl<'tcx> RegionResolutionError<'tcx> { @@ -106,7 +108,8 @@ impl<'tcx> RegionResolutionError<'tcx> { RegionResolutionError::ConcreteFailure(origin, _, _) | RegionResolutionError::GenericBoundFailure(origin, _, _) | RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _) - | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin, + | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) + | RegionResolutionError::CannotNormalize(_, origin) => origin, } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1eab8575fc0c4..78ef70398e5ed 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -8,6 +8,7 @@ pub use self::ValuePairs::*; pub use relate::combine::ObligationEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::undo_log::UndoLogs; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use self::opaque_types::OpaqueTypeStorage; @@ -25,8 +26,8 @@ use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxt, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; +use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; -use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -278,7 +279,8 @@ pub struct InferCtxt<'tcx> { /// The set of predicates on which errors have been reported, to /// avoid reporting the same error twice. - pub reported_trait_errors: RefCell>>>, + pub reported_trait_errors: + RefCell>, ErrorGuaranteed)>>, pub reported_signature_mismatch: RefCell)>>, @@ -304,6 +306,12 @@ pub struct InferCtxt<'tcx> { // FIXME(matthewjasper) Merge into `tainted_by_errors` err_count_on_creation: usize, + /// Track how many errors were stashed when this infcx is created. + /// Used for the same purpose as `err_count_on_creation`, even + /// though it's weaker because the count can go up and down. + // FIXME(matthewjasper) Merge into `tainted_by_errors` + stashed_err_count_on_creation: usize, + /// What is the innermost universe we have created? Starts out as /// `UniverseIndex::root()` but grows from there as we enter /// universal quantifiers. @@ -709,6 +717,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), err_count_on_creation: tcx.dcx().err_count(), + stashed_err_count_on_creation: tcx.dcx().stashed_err_count(), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, next_trait_solver, @@ -817,7 +826,7 @@ impl<'tcx> InferCtxt<'tcx> { (0..table.len()) .map(|i| ty::EffectVid::from_usize(i)) - .filter(|&vid| table.probe_value(vid).is_none()) + .filter(|&vid| table.probe_value(vid).is_unknown()) .map(|v| { ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool) }) @@ -861,7 +870,7 @@ impl<'tcx> InferCtxt<'tcx> { } #[instrument(skip(self, snapshot), level = "debug")] - fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) { + fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) { let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; self.universe.set(universe); @@ -893,7 +902,7 @@ impl<'tcx> InferCtxt<'tcx> { self.commit_from(snapshot); } Err(_) => { - self.rollback_to("commit_if_ok -- error", snapshot); + self.rollback_to(snapshot); } } r @@ -907,7 +916,7 @@ impl<'tcx> InferCtxt<'tcx> { { let snapshot = self.start_snapshot(); let r = f(&snapshot); - self.rollback_to("probe", snapshot); + self.rollback_to(snapshot); r } @@ -1030,10 +1039,9 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - let ty::SubtypePredicate { a_is_expected, a, b } = - self.instantiate_binder_with_placeholders(predicate); - - Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) + self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { + Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) + }) } pub fn region_outlives_predicate( @@ -1041,10 +1049,12 @@ impl<'tcx> InferCtxt<'tcx> { cause: &traits::ObligationCause<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) { - let ty::OutlivesPredicate(r_a, r_b) = self.instantiate_binder_with_placeholders(predicate); - let origin = - SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { + let origin = SubregionOrigin::from_obligation_cause(cause, || { + RelateRegionParamBound(cause.span) + }); + self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + }) } /// Number of type variables created so far. @@ -1235,7 +1245,8 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn var_for_effect(&self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { - let effect_vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; + let effect_vid = + self.inner.borrow_mut().effect_unification_table().new_key(EffectVarValue::Unknown).vid; let ty = self .tcx .type_of(param.def_id) @@ -1258,26 +1269,24 @@ impl<'tcx> InferCtxt<'tcx> { /// inference variables, regionck errors). #[must_use = "this method does not have any side effects"] pub fn tainted_by_errors(&self) -> Option { - debug!( - "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ - tainted_by_errors={})", - self.dcx().err_count(), - self.err_count_on_creation, - self.tainted_by_errors.get().is_some() - ); - - if let Some(e) = self.tainted_by_errors.get() { - return Some(e); - } - - if self.dcx().err_count() > self.err_count_on_creation { - // errors reported since this infcx was made - let e = self.dcx().has_errors().unwrap(); - self.set_tainted_by_errors(e); - return Some(e); + if let Some(guar) = self.tainted_by_errors.get() { + Some(guar) + } else if self.dcx().err_count() > self.err_count_on_creation { + // Errors reported since this infcx was made. + let guar = self.dcx().has_errors().unwrap(); + self.set_tainted_by_errors(guar); + Some(guar) + } else if self.dcx().stashed_err_count() > self.stashed_err_count_on_creation { + // Errors stashed since this infcx was made. Not entirely reliable + // because the count of stashed errors can go down. But without + // this case we get a moderate number of uninteresting and + // extraneous "type annotations needed" errors. + let guar = self.dcx().delayed_bug("tainted_by_errors: stashed bug awaiting emission"); + self.set_tainted_by_errors(guar); + Some(guar) + } else { + None } - - None } /// Set the "tainted by errors" flag to true. We call this when we @@ -1415,8 +1424,8 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn probe_effect_var(&self, vid: EffectVid) -> Option> { - self.inner.borrow_mut().effect_unification_table().probe_value(vid) + pub fn probe_effect_var(&self, vid: EffectVid) -> Option> { + self.inner.borrow_mut().effect_unification_table().probe_value(vid).known() } /// Attempts to resolve all type/region/const variables in @@ -1452,7 +1461,7 @@ impl<'tcx> InferCtxt<'tcx> { // Use this method if you'd like to find some substitution of the binder's // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`] // that corresponds to your use case, consider whether or not you should - // use [`InferCtxt::instantiate_binder_with_placeholders`] instead. + // use [`InferCtxt::enter_forall`] instead. pub fn instantiate_binder_with_fresh_vars( &self, span: Span, @@ -1537,9 +1546,13 @@ impl<'tcx> InferCtxt<'tcx> { /// Obtains the latest type of the given closure; this may be a /// closure in the current function, in which case its /// `ClosureKind` may not yet be known. - pub fn closure_kind(&self, closure_args: GenericArgsRef<'tcx>) -> Option { - let closure_kind_ty = closure_args.as_closure().kind_ty(); - let closure_kind_ty = self.shallow_resolve(closure_kind_ty); + pub fn closure_kind(&self, closure_ty: Ty<'tcx>) -> Option { + let unresolved_kind_ty = match *closure_ty.kind() { + ty::Closure(_, args) => args.as_closure().kind_ty(), + ty::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(), + _ => bug!("unexpected type {closure_ty}"), + }; + let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty); closure_kind_ty.to_opt_closure_kind() } @@ -1892,7 +1905,8 @@ impl<'a, 'tcx> TypeFolder> for ShallowResolver<'a, 'tcx> { .borrow_mut() .effect_unification_table() .probe_value(vid) - .map_or(ct, |val| val.as_const(self.infcx.tcx)), + .known() + .unwrap_or(ct), _ => ct, } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index db46b39ce25fc..46c4f80cb0cb7 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -327,7 +327,6 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn register_member_constraints( &self, - param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, concrete_ty: Ty<'tcx>, span: Span, @@ -456,6 +455,17 @@ where args.as_closure().sig_as_fn_ptr_ty().visit_with(self); } + ty::CoroutineClosure(_, args) => { + // Skip lifetime parameters of the enclosing item(s) + + for upvar in args.as_coroutine_closure().upvar_tys() { + upvar.visit_with(self); + } + + // FIXME(async_closures): Is this the right signature to visit here? + args.as_coroutine_closure().signature_parts_ty().visit_with(self); + } + ty::Coroutine(_, args) => { // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. @@ -676,7 +686,7 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi let res = hir_id == scope; trace!( "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", - tcx.opt_hir_node(hir_id), + tcx.hir_node(hir_id), tcx.hir_node(opaque_hir_id), res ); diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index fc3d8375873b0..7dd1ec3254220 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -103,6 +103,11 @@ fn compute_components<'tcx>( compute_components(tcx, tupled_ty, out, visited); } + ty::CoroutineClosure(_, args) => { + let tupled_ty = args.as_coroutine_closure().tupled_upvars_ty(); + compute_components(tcx, tupled_ty, out, visited); + } + ty::Coroutine(_, args) => { // Same as the closure case let tupled_ty = args.as_coroutine().tupled_upvars_ty(); diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 6379f84aa252f..a4f9316b5020f 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -1,10 +1,10 @@ //! Various code related to computing outlives relations. use self::env::OutlivesEnvironment; use super::region_constraints::RegionConstraintData; -use super::{InferCtxt, RegionResolutionError}; +use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; -use rustc_middle::traits::query::OutlivesBound; +use rustc_middle::traits::query::{NoSolution, OutlivesBound}; use rustc_middle::ty; pub mod components; @@ -41,12 +41,25 @@ impl<'tcx> InferCtxt<'tcx> { /// result. After this, no more unification operations should be /// done -- or the compiler will panic -- but it is legal to use /// `resolve_vars_if_possible` as well as `fully_resolve`. + /// + /// If you are in a crate that has access to `rustc_trait_selection`, + /// then it's probably better to use `resolve_regions`, + /// which knows how to normalize registered region obligations. #[must_use] - pub fn resolve_regions( + pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, + deeply_normalize_ty: impl Fn( + ty::PolyTypeOutlivesPredicate<'tcx>, + SubregionOrigin<'tcx>, + ) -> Result, NoSolution>, ) -> Vec> { - self.process_registered_region_obligations(outlives_env); + match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) { + Ok(()) => {} + Err((clause, origin)) => { + return vec![RegionResolutionError::CannotNormalize(clause, origin)]; + } + }; let (var_infos, data) = { let mut inner = self.inner.borrow_mut(); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index d7a3bfcbc41b6..7208f17fb340f 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,10 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::GenericArgKind; +use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate}; +use rustc_span::DUMMY_SP; use smallvec::smallvec; use super::env::OutlivesEnvironment; @@ -123,26 +125,73 @@ impl<'tcx> InferCtxt<'tcx> { /// flow of the inferencer. The key point is that it is /// invoked after all type-inference variables have been bound -- /// right before lexical region resolution. - #[instrument(level = "debug", skip(self, outlives_env))] - pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) { + #[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))] + pub fn process_registered_region_obligations( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + mut deeply_normalize_ty: impl FnMut( + PolyTypeOutlivesPredicate<'tcx>, + SubregionOrigin<'tcx>, + ) + -> Result, NoSolution>, + ) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); - let my_region_obligations = self.take_registered_region_obligations(); + let normalized_caller_bounds: Vec<_> = outlives_env + .param_env + .caller_bounds() + .iter() + .filter_map(|clause| { + let outlives = clause.as_type_outlives_clause()?; + Some( + deeply_normalize_ty( + outlives, + SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP), + ) + // FIXME(-Znext-solver): How do we accurately report an error span here :( + .map_err(|NoSolution| { + (outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)) + }), + ) + }) + .try_collect()?; - for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - debug!(?sup_type, ?sub_region, ?origin); - let sup_type = self.resolve_vars_if_possible(sup_type); + // Must loop since the process of normalizing may itself register region obligations. + for iteration in 0.. { + let my_region_obligations = self.take_registered_region_obligations(); + if my_region_obligations.is_empty() { + break; + } - let outlives = &mut TypeOutlives::new( - self, - self.tcx, - outlives_env.region_bound_pairs(), - None, - outlives_env.param_env, - ); - let category = origin.to_constraint_category(); - outlives.type_must_outlive(origin, sup_type, sub_region, category); + if !self.tcx.recursion_limit().value_within_limit(iteration) { + bug!( + "FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}" + ); + } + + for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { + let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region)); + let ty::OutlivesPredicate(sup_type, sub_region) = + deeply_normalize_ty(outlives, origin.clone()) + .map_err(|NoSolution| (outlives, origin.clone()))? + .no_bound_vars() + .expect("started with no bound vars, should end with no bound vars"); + + debug!(?sup_type, ?sub_region, ?origin); + + let outlives = &mut TypeOutlives::new( + self, + self.tcx, + outlives_env.region_bound_pairs(), + None, + &normalized_caller_bounds, + ); + let category = origin.to_constraint_category(); + outlives.type_must_outlive(origin, sup_type, sub_region, category); + } } + + Ok(()) } } @@ -190,7 +239,7 @@ where tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], ) -> Self { Self { delegate, @@ -199,7 +248,7 @@ where tcx, region_bound_pairs, implicit_region_bound, - param_env, + caller_bounds, ), } } diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 7a85268492b43..5d2f51c689b95 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -23,7 +23,7 @@ pub struct VerifyBoundCx<'cx, 'tcx> { /// Outside of borrowck the only way to prove `T: '?0` is by /// setting `'?0` to `'empty`. implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], } impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { @@ -31,9 +31,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { tcx: TyCtxt<'tcx>, region_bound_pairs: &'cx RegionBoundPairs<'tcx>, implicit_region_bound: Option>, - param_env: ty::ParamEnv<'tcx>, + caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>], ) -> Self { - Self { tcx, region_bound_pairs, implicit_region_bound, param_env } + Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds } } #[instrument(level = "debug", skip(self))] @@ -219,8 +219,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // To start, collect bounds from user environment. Note that // parameter environments are already elaborated, so we don't // have to worry about that. - let c_b = self.param_env.caller_bounds(); - let param_bounds = self.collect_outlives_from_clause_list(erased_ty, c_b.into_iter()); + let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| { + super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) + }); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -307,22 +308,4 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { .filter_map(|p| p.no_bound_vars()) .map(|OutlivesPredicate(_, r)| r) } - - /// Searches through a predicate list for a predicate `T: 'a`. - /// - /// Careful: does not elaborate predicates, and just uses `==` - /// when comparing `ty` for equality, so `ty` must be something - /// that does not involve inference variables and where you - /// otherwise want a precise match. - fn collect_outlives_from_clause_list( - &self, - erased_ty: Ty<'tcx>, - clauses: impl Iterator>, - ) -> impl Iterator, ty::Region<'tcx>>>> - { - let tcx = self.tcx; - clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| { - super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty) - }) - } } diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 1c120646f1f90..7edfbf02a6829 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -202,11 +202,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::ConstKind::Infer(InferConst::EffectVar(a_vid)), ty::ConstKind::Infer(InferConst::EffectVar(b_vid)), ) => { - self.inner - .borrow_mut() - .effect_unification_table() - .unify_var_var(a_vid, b_vid) - .map_err(|a| effect_unification_error(self.tcx, relation.a_is_expected(), a))?; + self.inner.borrow_mut().effect_unification_table().union(a_vid, b_vid); return Ok(a); } @@ -225,27 +221,19 @@ impl<'tcx> InferCtxt<'tcx> { } (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { - return self.unify_const_variable(vid, b, relation.param_env()); + return self.unify_const_variable(vid, b); } (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { - return self.unify_const_variable(vid, a, relation.param_env()); + return self.unify_const_variable(vid, a); } (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { - return self.unify_effect_variable( - relation.a_is_expected(), - vid, - EffectVarValue::Const(b), - ); + return Ok(self.unify_effect_variable(vid, b)); } (_, ty::ConstKind::Infer(InferConst::EffectVar(vid))) => { - return self.unify_effect_variable( - !relation.a_is_expected(), - vid, - EffectVarValue::Const(a), - ); + return Ok(self.unify_effect_variable(vid, a)); } (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) @@ -310,7 +298,6 @@ impl<'tcx> InferCtxt<'tcx> { &self, target_vid: ty::ConstVid, ct: ty::Const<'tcx>, - param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { ConstVariableValue::Known { value } => { @@ -366,18 +353,12 @@ impl<'tcx> InferCtxt<'tcx> { Ok(Ty::new_float(self.tcx, val)) } - fn unify_effect_variable( - &self, - vid_is_expected: bool, - vid: ty::EffectVid, - val: EffectVarValue<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> { + fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> { self.inner .borrow_mut() .effect_unification_table() - .unify_var_value(vid, Some(val)) - .map_err(|e| effect_unification_error(self.tcx, vid_is_expected, e))?; - Ok(val.as_const(self.tcx)) + .union_value(vid, EffectVarValue::Known(val)); + val } } @@ -579,11 +560,3 @@ fn float_unification_error<'tcx>( let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) } - -fn effect_unification_error<'tcx>( - _tcx: TyCtxt<'tcx>, - _a_is_expected: bool, - (_a, _b): (EffectVarValue<'tcx>, EffectVarValue<'tcx>), -) -> TypeError<'tcx> { - bug!("unexpected effect unification error") -} diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 440df8c8936f9..90be80f67b4d0 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -38,24 +38,25 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. Note that this automatically creates // a new universe if needed. - let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup); + self.infcx.enter_forall(sup, |sup_prime| { + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other preexisting region variables -- can name + // the placeholders. + let sub_prime = + self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); + debug!("a_prime={:?}", sub_prime); + debug!("b_prime={:?}", sup_prime); - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other preexisting region variables -- can name - // the placeholders. - let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); - - debug!("a_prime={:?}", sub_prime); - debug!("b_prime={:?}", sup_prime); - - // Compare types now that bound regions have been replaced. - let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?; - - debug!("OK result={result:?}"); - // NOTE: returning the result here would be dangerous as it contains - // placeholders which **must not** be named afterwards. - Ok(()) + // Compare types now that bound regions have been replaced. + let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime); + if result.is_ok() { + debug!("OK result={result:?}"); + } + // NOTE: returning the result here would be dangerous as it contains + // placeholders which **must not** be named afterwards. + result.map(|_| ()) + }) } } @@ -68,9 +69,11 @@ impl<'tcx> InferCtxt<'tcx> { /// This is the first step of checking subtyping when higher-ranked things are involved. /// For more details visit the relevant sections of the [rustc dev guide]. /// + /// `fn enter_forall` should be preferred over this method. + /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[instrument(level = "debug", skip(self), ret)] - pub fn instantiate_binder_with_placeholders(&self, binder: ty::Binder<'tcx, T>) -> T + pub fn enter_forall_and_leak_universe(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable> + Copy, { @@ -106,6 +109,31 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(binder, delegate) } + /// Replaces all bound variables (lifetimes, types, and constants) bound by + /// `binder` with placeholder variables in a new universe and then calls the + /// closure `f` with the instantiated value. The new placeholders can only be + /// named by inference variables created inside of the closure `f` or afterwards. + /// + /// This is the first step of checking subtyping when higher-ranked things are involved. + /// For more details visit the relevant sections of the [rustc dev guide]. + /// + /// This method should be preferred over `fn enter_forall_and_leak_universe`. + /// + /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + #[instrument(level = "debug", skip(self, f))] + pub fn enter_forall(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U + where + T: TypeFoldable> + Copy, + { + // FIXME: currently we do nothing to prevent placeholders with the new universe being + // used after exiting `f`. For example region subtyping can result in outlives constraints + // that name placeholders created in this function. Nested goals from type relations can + // also contain placeholders created by this function. + let value = self.enter_forall_and_leak_universe(forall); + debug!("?value"); + f(value) + } + /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that /// universe. diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index 8b80646a386c8..5e2d2af9b8587 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -261,52 +261,55 @@ where Ok(a) } - #[instrument(skip(self), level = "debug")] - fn instantiate_binder_with_placeholders(&mut self, binder: ty::Binder<'tcx, T>) -> T + fn enter_forall( + &mut self, + binder: ty::Binder<'tcx, T>, + f: impl FnOnce(&mut Self, T) -> U, + ) -> U where T: ty::TypeFoldable> + Copy, { - if let Some(inner) = binder.no_bound_vars() { - return inner; - } - - let mut next_region = { - let nll_delegate = &mut self.delegate; - let mut lazy_universe = None; + let value = if let Some(inner) = binder.no_bound_vars() { + inner + } else { + let mut next_region = { + let nll_delegate = &mut self.delegate; + let mut lazy_universe = None; + + move |br: ty::BoundRegion| { + // The first time this closure is called, create a + // new universe for the placeholders we will make + // from here out. + let universe = lazy_universe.unwrap_or_else(|| { + let universe = nll_delegate.create_next_universe(); + lazy_universe = Some(universe); + universe + }); + + let placeholder = ty::PlaceholderRegion { universe, bound: br }; + debug!(?placeholder); + let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); + debug!(?placeholder_reg); + + placeholder_reg + } + }; - move |br: ty::BoundRegion| { - // The first time this closure is called, create a - // new universe for the placeholders we will make - // from here out. - let universe = lazy_universe.unwrap_or_else(|| { - let universe = nll_delegate.create_next_universe(); - lazy_universe = Some(universe); - universe - }); - - let placeholder = ty::PlaceholderRegion { universe, bound: br }; - debug!(?placeholder); - let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); - debug!(?placeholder_reg); - - placeholder_reg - } - }; + let delegate = FnMutDelegate { + regions: &mut next_region, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; - let delegate = FnMutDelegate { - regions: &mut next_region, - types: &mut |_bound_ty: ty::BoundTy| { - unreachable!("we only replace regions in nll_relate, not types") - }, - consts: &mut |_bound_var: ty::BoundVar, _ty| { - unreachable!("we only replace regions in nll_relate, not consts") - }, + self.infcx.tcx.replace_bound_vars_uncached(binder, delegate) }; - let replaced = self.infcx.tcx.replace_bound_vars_uncached(binder, delegate); - debug!(?replaced); - - replaced + debug!(?value); + f(self, value) } #[instrument(skip(self), level = "debug")] @@ -630,10 +633,10 @@ where // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! - let b_replaced = self.instantiate_binder_with_placeholders(b); - let a_replaced = self.instantiate_binder_with_existentials(a); - - self.relate(a_replaced, b_replaced)?; + self.enter_forall(b, |this, b| { + let a = this.instantiate_binder_with_existentials(a); + this.relate(a, b) + })?; self.ambient_variance = variance; } @@ -650,10 +653,10 @@ where let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); - let a_replaced = self.instantiate_binder_with_placeholders(a); - let b_replaced = self.instantiate_binder_with_existentials(b); - - self.relate(a_replaced, b_replaced)?; + self.enter_forall(a, |this, a| { + let b = this.instantiate_binder_with_existentials(b); + this.relate(a, b) + })?; self.ambient_variance = variance; } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 959b09031277c..d5999331dfab6 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -237,14 +237,13 @@ impl<'tcx> TypeFolder> for EagerResolver<'_, 'tcx> { } ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool); - match self.infcx.probe_effect_var(vid) { - Some(c) => c.as_const(self.infcx.tcx), - None => ty::Const::new_infer( + self.infcx.probe_effect_var(vid).unwrap_or_else(|| { + ty::Const::new_infer( self.infcx.tcx, ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)), self.infcx.tcx.types.bool, - ), - } + ) + }) } _ => { if c.has_infer() { diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 9e3de1825ed37..622cdf0c7b895 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -16,11 +16,14 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(extend_one)] #![feature(let_chains)] #![feature(if_let_guard)] +#![feature(iterator_try_collect)] #![feature(min_specialization)] #![feature(try_blocks)] #![recursion_limit = "512"] // For rustdoc diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index eabc1b953af1c..ed551658d91a9 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::Map; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; @@ -62,7 +61,7 @@ pub fn report_object_safety_error<'tcx>( err.span_label(span, format!("`{trait_str}` cannot be made into an object")); if let Some(hir_id) = hir_id - && let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id) + && let hir::Node::Ty(ty) = tcx.hir_node(hir_id) && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind { let mut hir_id = hir_id; diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 5ca8809099675..8a4705e0056e1 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -45,20 +45,19 @@ pub struct Compiler { pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { cfgs.into_iter() .map(|s| { - let sess = ParseSess::with_silent_emitter(Some(format!( + let sess = ParseSess::with_silent_emitter(format!( "this error occurred on the command line: `--cfg={s}`" - ))); + )); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { ($reason: expr) => { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - dcx.struct_fatal(format!( + dcx.fatal(format!( concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s - )) - .emit(); + )); }; } @@ -108,20 +107,19 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() }; for s in specs { - let sess = ParseSess::with_silent_emitter(Some(format!( + let sess = ParseSess::with_silent_emitter(format!( "this error occurred on the command line: `--check-cfg={s}`" - ))); + )); let filename = FileName::cfg_spec_source_code(&s); macro_rules! error { ($reason:expr) => { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - dcx.struct_fatal(format!( + dcx.fatal(format!( concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s )) - .emit() }; } diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 69414a1379515..7d69e49b209f5 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -4,8 +4,6 @@ #![feature(let_chains)] #![feature(thread_spawn_unchecked)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 9795640412069..50b2bf7da153e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -778,6 +778,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // kindck is gone now). -nmatsakis if let Some(reported) = sess.dcx().has_errors() { return Err(reported); + } else if sess.dcx().stashed_err_count() > 0 { + // Without this case we sometimes get delayed bug ICEs and I don't + // understand why. -nnethercote + return Err(sess.dcx().delayed_bug("some stashed error is waiting for use")); } sess.time("misc_checking_3", || { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2d4963a8b901a..bfc4fc07d4cc7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -749,6 +749,7 @@ fn test_unstable_options_tracking_hash() { tracked!(debug_macros, true); tracked!(default_hidden_visibility, Some(true)); tracked!(dep_info_omit_d_target, true); + tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); tracked!(emit_thin_lto, false); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index f6c9289b529c7..ca84e930c2439 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -18,8 +18,7 @@ //! lexeme types. //! //! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] + // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 07f127414dbc0..f10d3d4a68a76 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -72,7 +72,7 @@ use crate::nonstandard_style::{method_context, MethodLateContext}; use std::fmt::Write; -// hardwired lints from librustc_middle +// hardwired lints from rustc_lint_defs pub use rustc_session::lint::builtin::*; declare_lint! { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 04201a38c35ea..1c480ec8f53b1 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -326,11 +326,9 @@ impl LintStore { /// True if this symbol represents a lint group name. pub fn is_lint_group(&self, lint_name: Symbol) -> bool { - debug!( - "is_lint_group(lint_name={:?}, lint_groups={:?})", - lint_name, - self.lint_groups.keys().collect::>() - ); + #[allow(rustc::potential_query_instability)] + let lint_groups = self.lint_groups.keys().collect::>(); + debug!("is_lint_group(lint_name={:?}, lint_groups={:?})", lint_name, lint_groups); let lint_name_str = lint_name.as_str(); self.lint_groups.contains_key(lint_name_str) || { let warnings_name_str = crate::WARNINGS.name_lower(); @@ -374,8 +372,12 @@ impl LintStore { None => { // 1. The tool is currently running, so this lint really doesn't exist. // FIXME: should this handle tools that never register a lint, like rustfmt? - debug!("lints={:?}", self.by_name.keys().collect::>()); + #[allow(rustc::potential_query_instability)] + let lints = self.by_name.keys().collect::>(); + debug!("lints={:?}", lints); let tool_prefix = format!("{tool_name}::"); + + #[allow(rustc::potential_query_instability)] return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) { self.no_lint_suggestion(&complete_name, tool_name.as_str()) } else { diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 312874db3f54e..0fa61c5d87e77 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -185,8 +185,26 @@ pub(super) fn builtin( db.note("see the asm section of Rust By Example for more information"); } BuiltinLintDiagnostics::UnexpectedCfgName((name, name_span), value) => { + #[allow(rustc::potential_query_instability)] let possibilities: Vec = sess.parse_sess.check_config.expecteds.keys().copied().collect(); + + let mut names_possibilities: Vec<_> = if value.is_none() { + // We later sort and display all the possibilities, so the order here does not matter. + #[allow(rustc::potential_query_instability)] + sess.parse_sess + .check_config + .expecteds + .iter() + .filter_map(|(k, v)| match v { + ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k), + _ => None, + }) + .collect() + } else { + Vec::new() + }; + let is_from_cargo = std::env::var_os("CARGO").is_some(); let mut is_feature_cfg = name == sym::feature; @@ -261,17 +279,30 @@ pub(super) fn builtin( } is_feature_cfg |= best_match == sym::feature; - } else if !possibilities.is_empty() { - let mut possibilities = - possibilities.iter().map(Symbol::as_str).collect::>(); - possibilities.sort(); - let possibilities = possibilities.join("`, `"); + } else { + if !names_possibilities.is_empty() && names_possibilities.len() <= 3 { + names_possibilities.sort(); + for cfg_name in names_possibilities.iter() { + db.span_suggestion( + name_span, + "found config with similar value", + format!("{cfg_name} = \"{name}\""), + Applicability::MaybeIncorrect, + ); + } + } + if !possibilities.is_empty() { + let mut possibilities = + possibilities.iter().map(Symbol::as_str).collect::>(); + possibilities.sort(); + let possibilities = possibilities.join("`, `"); - // The list of expected names can be long (even by default) and - // so the diagnostic produced can take a lot of space. To avoid - // cloging the user output we only want to print that diagnostic - // once. - db.help_once(format!("expected names are: `{possibilities}`")); + // The list of expected names can be long (even by default) and + // so the diagnostic produced can take a lot of space. To avoid + // cloging the user output we only want to print that diagnostic + // once. + db.help_once(format!("expected names are: `{possibilities}`")); + } } let inst = if let Some((value, _value_span)) = value { diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 3bd0c1b803199..21d4b6fa65b5b 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,5 @@ use crate::fluent_generated as fluent; -use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; +use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; @@ -24,10 +24,7 @@ pub enum OverruledAttributeSub { } impl AddToDiagnostic for OverruledAttributeSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index eb2490a47d09d..516df14c8943a 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -345,7 +345,7 @@ declare_tool_lint! { /// /// More details on translatable diagnostics can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html). pub rustc::UNTRANSLATABLE_DIAGNOSTIC, - Allow, + Deny, "prevent creation of diagnostics which cannot be translated", report_in_external_macro: true } @@ -357,7 +357,7 @@ declare_tool_lint! { /// /// More details on diagnostics implementations can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html). pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL, - Allow, + Deny, "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls", report_in_external_macro: true } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index caa015565914d..d3d7698e7f927 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -364,14 +364,11 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( // Note: `passes` is often empty. In that case, it's faster to run // `builtin_lints` directly rather than bundling it up into the // `RuntimeCombinedLateLintPass`. - let mut passes: Vec<_> = unerased_lint_store(tcx.sess) - .late_module_passes - .iter() - .map(|mk_pass| (mk_pass)(tcx)) - .collect(); - if passes.is_empty() { + let late_module_passes = &unerased_lint_store(tcx.sess).late_module_passes; + if late_module_passes.is_empty() { late_lint_mod_inner(tcx, module_def_id, context, builtin_lints); } else { + let mut passes: Vec<_> = late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); passes.push(Box::new(builtin_lints)); let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] }; late_lint_mod_inner(tcx, module_def_id, context, pass); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index d37f0c151714d..40fb12b21070b 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -181,7 +181,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe // Otherwise, we need to visit the attributes in source code order, so we fetch HIR and do // a standard visit. // FIXME(#102522) Just iterate on attrs once that iteration order matches HIR's. - _ => match tcx.hir().owner(owner) { + _ => match tcx.hir_owner_node(owner) { hir::OwnerNode::Item(item) => levels.visit_item(item), hir::OwnerNode::ForeignItem(item) => levels.visit_foreign_item(item), hir::OwnerNode::TraitItem(item) => levels.visit_trait_item(item), diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 1d9ce10bcaf38..5c2a422a2b7c0 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -34,11 +34,9 @@ #![feature(if_let_guard)] #![feature(iter_order_by)] #![feature(let_chains)] -#![cfg_attr(not(bootstrap), feature(trait_upcasting))] +#![feature(trait_upcasting)] #![feature(min_specialization)] #![feature(rustc_attrs)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] @@ -516,6 +514,15 @@ fn register_builtins(store: &mut LintStore) { "converted into hard error, see PR #118649 \ for more information", ); + store.register_removed( + "illegal_floating_point_literal_pattern", + "no longer a warning, float patterns behave the same as `==`", + ); + store.register_removed( + "nontrivial_structural_match", + "no longer needed, see RFC #3535 \ + for more information", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index f916deb4a46d1..42d9760f8aa14 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,12 +1,13 @@ -#![allow(rustc::untranslatable_diagnostic)] #![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use std::num::NonZeroU32; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, - DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle, + DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessageOp, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -268,10 +269,7 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { } impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { // Access to associates types should use `::Assoc`, which does not need a // bound. Let's see if this type does that. @@ -323,10 +321,7 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.multipart_suggestion( fluent::lint_suggestion, self.suggestions, @@ -443,10 +438,7 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -497,10 +489,7 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut expected_str = DiagnosticStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagnosticStyledString::new(); @@ -766,10 +755,7 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -783,10 +769,7 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( @@ -934,10 +917,7 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; if can_suggest_binding { @@ -1217,10 +1197,7 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, fluent::lint_label); @@ -1413,10 +1390,7 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { OverflowingBinHexSign::Positive => { diag.note(fluent::lint_positive_note); diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index bed5d3c80c046..cf825be7a55ea 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -77,101 +77,104 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { - let predicate = infcx.instantiate_binder_with_placeholders(pred.kind()); - let ty::ClauseKind::Projection(proj) = predicate else { - continue; - }; - // Only check types, since those are the only things that may - // have opaques in them anyways. - let Some(proj_term) = proj.term.ty() else { continue }; + infcx.enter_forall(pred.kind(), |predicate| { + let ty::ClauseKind::Projection(proj) = predicate else { + return; + }; + // Only check types, since those are the only things that may + // have opaques in them anyways. + let Some(proj_term) = proj.term.ty() else { return }; - // HACK: `impl Trait` from an RPIT is "ok"... - if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() - && cx.tcx.parent(opaque_ty.def_id) == def_id - && matches!( - opaque.origin, - hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) - ) - { - continue; - } + // HACK: `impl Trait` from an RPIT is "ok"... + if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() + && cx.tcx.parent(opaque_ty.def_id) == def_id + && matches!( + opaque.origin, + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) + ) + { + return; + } - // HACK: `async fn() -> Self` in traits is "ok"... - // This is not really that great, but it's similar to why the `-> Self` - // return type is well-formed in traits even when `Self` isn't sized. - if let ty::Param(param_ty) = *proj_term.kind() - && param_ty.name == kw::SelfUpper - && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_)) - && opaque.in_trait - { - continue; - } + // HACK: `async fn() -> Self` in traits is "ok"... + // This is not really that great, but it's similar to why the `-> Self` + // return type is well-formed in traits even when `Self` isn't sized. + if let ty::Param(param_ty) = *proj_term.kind() + && param_ty.name == kw::SelfUpper + && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_)) + && opaque.in_trait + { + return; + } - let proj_ty = - Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); - // For every instance of the projection type in the bounds, - // replace them with the term we're assigning to the associated - // type in our opaque type. - let proj_replacer = &mut BottomUpFolder { - tcx: cx.tcx, - ty_op: |ty| if ty == proj_ty { proj_term } else { ty }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }; - // For example, in `impl Trait`, for all of the bounds on `Assoc`, - // e.g. `type Assoc: OtherTrait`, replace `::Assoc: OtherTrait` - // with `impl Send: OtherTrait`. - for (assoc_pred, assoc_pred_span) in cx - .tcx - .explicit_item_bounds(proj.projection_ty.def_id) - .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) - { - let assoc_pred = assoc_pred.fold_with(proj_replacer); - let Ok(assoc_pred) = traits::fully_normalize( - infcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - ) else { - continue; + let proj_ty = + Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); + // For every instance of the projection type in the bounds, + // replace them with the term we're assigning to the associated + // type in our opaque type. + let proj_replacer = &mut BottomUpFolder { + tcx: cx.tcx, + ty_op: |ty| if ty == proj_ty { proj_term } else { ty }, + lt_op: |lt| lt, + ct_op: |ct| ct, }; - // If that predicate doesn't hold modulo regions (but passed during type-check), - // then we must've taken advantage of the hack in `project_and_unify_types` where - // we replace opaques with inference vars. Emit a warning! - if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( - cx.tcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - )) { - // If it's a trait bound and an opaque that doesn't satisfy it, - // then we can emit a suggestion to add the bound. - let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { - ( - ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), - ty::ClauseKind::Trait(trait_pred), - ) => Some(AddBound { - suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), - trait_ref: trait_pred.print_modifiers_and_trait_path(), - }), - _ => None, + // For example, in `impl Trait`, for all of the bounds on `Assoc`, + // e.g. `type Assoc: OtherTrait`, replace `::Assoc: OtherTrait` + // with `impl Send: OtherTrait`. + for (assoc_pred, assoc_pred_span) in cx + .tcx + .explicit_item_bounds(proj.projection_ty.def_id) + .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) + { + let assoc_pred = assoc_pred.fold_with(proj_replacer); + let Ok(assoc_pred) = traits::fully_normalize( + infcx, + traits::ObligationCause::dummy(), + cx.param_env, + assoc_pred, + ) else { + continue; }; - cx.emit_span_lint( - OPAQUE_HIDDEN_INFERRED_BOUND, - pred_span, - OpaqueHiddenInferredBoundLint { - ty: Ty::new_opaque( - cx.tcx, - def_id, - ty::GenericArgs::identity_for_item(cx.tcx, def_id), - ), - proj_ty: proj_term, - assoc_pred_span, - add_bound, - }, - ); + + // If that predicate doesn't hold modulo regions (but passed during type-check), + // then we must've taken advantage of the hack in `project_and_unify_types` where + // we replace opaques with inference vars. Emit a warning! + if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( + cx.tcx, + traits::ObligationCause::dummy(), + cx.param_env, + assoc_pred, + )) { + // If it's a trait bound and an opaque that doesn't satisfy it, + // then we can emit a suggestion to add the bound. + let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { + ( + ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), + ty::ClauseKind::Trait(trait_pred), + ) => Some(AddBound { + suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), + trait_ref: trait_pred.print_modifiers_and_trait_path(), + }), + _ => None, + }; + + cx.emit_span_lint( + OPAQUE_HIDDEN_INFERRED_BOUND, + pred_span, + OpaqueHiddenInferredBoundLint { + ty: Ty::new_opaque( + cx.tcx, + def_id, + ty::GenericArgs::identity_for_item(cx.tcx, def_id), + ), + proj_ty: proj_term, + assoc_pred_span, + add_bound, + }, + ); + } } - } + }); } } } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index e3d3150b36ef4..1205395b8908d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1435,6 +1435,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { | ty::Bound(..) | ty::Error(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Placeholder(..) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index ea3747dfac4b3..9f670893b270d 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -355,7 +355,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { Some(len) => is_ty_must_use(cx, ty, expr, span) .map(|inner| MustUsePath::Array(Box::new(inner), len)), }, - ty::Closure(..) => Some(MustUsePath::Closure(span)), + ty::Closure(..) | ty::CoroutineClosure(..) => Some(MustUsePath::Closure(span)), ty::Coroutine(def_id, ..) => { // async fn should be treated as "implementor of `Future`" let must_use = if cx.tcx.coroutine_is_async(def_id) { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e6d837ecd92bd..6a2a2c1e48e2a 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3,6 +3,9 @@ //! These are the built-in lints that are emitted direct in the main //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. +//! +//! When removing a lint, make sure to also add a call to `register_removed` in +//! compiler/rustc_lint/src/lib.rs. use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason}; use rustc_span::edition::Edition; @@ -45,7 +48,6 @@ declare_lint_pass! { FUZZY_PROVENANCE_CASTS, HIDDEN_GLOB_REEXPORTS, ILL_FORMED_ATTRIBUTE_INPUT, - ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, INCOMPLETE_INCLUDE, INDIRECT_STRUCTURAL_MATCH, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, @@ -67,7 +69,6 @@ declare_lint_pass! { MUST_NOT_SUSPEND, NAMED_ARGUMENTS_USED_POSITIONALLY, NON_EXHAUSTIVE_OMITTED_PATTERNS, - NONTRIVIAL_STRUCTURAL_MATCH, ORDER_DEPENDENT_TRAIT_OBJECTS, OVERLAPPING_RANGE_ENDPOINTS, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -1873,55 +1874,6 @@ declare_lint! { }; } -declare_lint! { - /// The `illegal_floating_point_literal_pattern` lint detects - /// floating-point literals used in patterns. - /// - /// ### Example - /// - /// ```rust - /// let x = 42.0; - /// - /// match x { - /// 5.0 => {} - /// _ => {} - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Previous versions of the compiler accepted floating-point literals in - /// patterns, but it was later determined this was a mistake. The - /// semantics of comparing floating-point values may not be clear in a - /// pattern when contrasted with "structural equality". Typically you can - /// work around this by using a [match guard], such as: - /// - /// ```rust - /// # let x = 42.0; - /// - /// match x { - /// y if y == 5.0 => {} - /// _ => {} - /// } - /// ``` - /// - /// This is a [future-incompatible] lint to transition this to a hard - /// error in the future. See [issue #41620] for more details. - /// - /// [issue #41620]: https://github.com/rust-lang/rust/issues/41620 - /// [match guard]: https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - Warn, - "floating-point literals cannot be used in patterns", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #41620 ", - }; -} - declare_lint! { /// The `unstable_name_collisions` lint detects that you have used a name /// that the standard library plans to add in the future. @@ -2330,8 +2282,8 @@ declare_lint! { Warn, "constant used in pattern contains value of non-structural-match type in a field or a variant", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #62411 ", + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #120362 ", }; } @@ -2386,47 +2338,8 @@ declare_lint! { Warn, "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #62411 ", - }; -} - -declare_lint! { - /// The `nontrivial_structural_match` lint detects constants that are used in patterns, - /// whose type is not structural-match and whose initializer body actually uses values - /// that are not structural-match. So `Option` is ok if the constant - /// is just `None`. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![deny(nontrivial_structural_match)] - /// - /// #[derive(Copy, Clone, Debug)] - /// struct NoDerive(u32); - /// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } - /// impl Eq for NoDerive { } - /// fn main() { - /// const INDEX: Option = [None, Some(NoDerive(10))][0]; - /// match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Previous versions of Rust accepted constants in patterns, even if those constants' types - /// did not have `PartialEq` derived. Thus the compiler falls back to runtime execution of - /// `PartialEq`, which can report that two constants are not equal even if they are - /// bit-equivalent. - pub NONTRIVIAL_STRUCTURAL_MATCH, - Warn, - "constant used in pattern of non-structural-match type and the constant's initializer \ - expression contains values of non-structural-match types", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #73448 ", + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #120362 ", }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index eed35326c4501..8b7e82d2113f8 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,6 +1,4 @@ #![feature(min_specialization)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 5bfffc5d9117b..6d578c97f3fe1 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -76,7 +76,6 @@ enum LLVMRustAttribute { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, - ReturnsTwice = 25, ReadNone = 26, SanitizeHWAddress = 28, WillReturn = 29, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 6114f7c867807..3b6bf03686b0d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -934,10 +934,8 @@ LLVMRustOptimize( } else { for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); - if (OptStage != LLVMRustOptStage::PreLinkThinLTO) { - for (const auto &C : OptimizerLastEPCallbacks) - PB.registerOptimizerLastEPCallback(C); - } + for (const auto &C : OptimizerLastEPCallbacks) + PB.registerOptimizerLastEPCallback(C); switch (OptStage) { case LLVMRustOptStage::PreLinkNoLTO: @@ -945,14 +943,7 @@ LLVMRustOptimize( break; case LLVMRustOptStage::PreLinkThinLTO: MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel); - // The ThinLTOPreLink pipeline already includes ThinLTOBuffer passes. However, callback - // passes may still run afterwards. This means we need to run the buffer passes again. - // FIXME: In LLVM 13, the ThinLTOPreLink pipeline also runs OptimizerLastEPCallbacks - // before the RequiredLTOPreLinkPasses, in which case we can remove these hacks. - if (OptimizerLastEPCallbacks.empty()) - NeedThinLTOBufferPasses = false; - for (const auto &C : OptimizerLastEPCallbacks) - C(MPM, OptLevel); + NeedThinLTOBufferPasses = false; break; case LLVMRustOptStage::PreLinkFatLTO: MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 0df7b7eed11f9..a2dfebec59441 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -250,8 +250,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::NonLazyBind; case OptimizeNone: return Attribute::OptimizeNone; - case ReturnsTwice: - return Attribute::ReturnsTwice; case ReadNone: return Attribute::ReadNone; case SanitizeHWAddress: diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index ca0aec71052d0..6a570c97c8888 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index e3464cb8a2df6..1a78f9f0f86e5 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -38,9 +38,6 @@ //! debugging, you can make changes inside those crates and quickly run main.rs //! to read the debug logs. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::env::{self, VarError}; use std::fmt::{self, Display}; use std::io::{self, IsTerminal}; diff --git a/compiler/rustc_macros/build.rs b/compiler/rustc_macros/build.rs new file mode 100644 index 0000000000000..717f8a922457d --- /dev/null +++ b/compiler/rustc_macros/build.rs @@ -0,0 +1,16 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-env-changed=RUSTC_BOOTSTRAP"); + if !std::env::var("RUSTC_BOOTSTRAP").is_ok() { + eprintln!( + "error: you are attempting to build the compiler without going through bootstrap" + ); + eprintln!( + "help: see https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html for how to build the compiler" + ); + eprintln!( + "help: if you know what you're doing, set the RUSTC_BOOTSTRAP environment variable to any value" + ); + panic!("wrong command used for building"); + } +} diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index c029b931e7dde..3a5f289559e6a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -89,10 +89,7 @@ impl SubdiagnosticDeriveBuilder { gen impl rustc_errors::AddToDiagnostic for @Self { fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F) where - __F: core::ops::Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage - ) -> rustc_errors::SubdiagnosticMessage, + __F: rustc_errors::SubdiagnosticMessageOp, { #implementation } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 9e85a59b5b92b..af65c908ee66b 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -6,8 +6,6 @@ #![feature(proc_macro_span)] #![feature(proc_macro_tracked_env)] #![allow(rustc::default_hash_types)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] use synstructure::decl_derive; diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index bb02a8a1e4743..c18f0e7b7b938 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -534,7 +534,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { ) -> Option { self.used_extern_options.insert(name); match self.maybe_resolve_crate(name, dep_kind, None) { - Ok(cnum) => Some(cnum), + Ok(cnum) => { + self.cstore.set_used_recursively(cnum); + Some(cnum) + } Err(err) => { let missing_core = self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); @@ -1067,6 +1070,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok() } + + pub fn unload_unused_crates(&mut self) { + for opt_cdata in &mut self.cstore.metas { + if let Some(cdata) = opt_cdata + && !cdata.used() + { + *opt_cdata = None; + } + } + } } fn global_allocator_spans(krate: &ast::Crate) -> Vec { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 471425e80174f..2e7130f356579 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -15,8 +15,6 @@ #![feature(try_blocks)] #![feature(never_type)] #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] extern crate proc_macro; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 20e3ae3ba9492..11cb1bb6d9e6e 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -106,6 +106,8 @@ pub(crate) struct CrateMetadata { private_dep: bool, /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. host_hash: Option, + /// The crate was used non-speculatively. + used: bool, /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext` /// and `ExpnId`). @@ -1811,6 +1813,7 @@ impl CrateMetadata { source: Lrc::new(source), private_dep, host_hash, + used: false, extern_crate: None, hygiene_context: Default::default(), def_key_cache: Default::default(), @@ -1860,6 +1863,10 @@ impl CrateMetadata { self.private_dep &= private_dep; } + pub(crate) fn used(&self) -> bool { + self.used + } + pub(crate) fn required_panic_strategy(&self) -> Option { self.root.required_panic_strategy } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0b352a02b64c7..7cd2f58779f84 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; use std::any::Any; +use std::mem; use super::{Decodable, DecodeContext, DecodeIterator}; @@ -576,12 +577,24 @@ impl CStore { self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess) } + pub fn set_used_recursively(&mut self, cnum: CrateNum) { + let cmeta = self.get_crate_data_mut(cnum); + if !cmeta.used { + cmeta.used = true; + let dependencies = mem::take(&mut cmeta.dependencies); + for &dep_cnum in &dependencies { + self.set_used_recursively(dep_cnum); + } + self.get_crate_data_mut(cnum).dependencies = dependencies; + } + } + pub(crate) fn update_extern_crate(&mut self, cnum: CrateNum, extern_crate: ExternCrate) { let cmeta = self.get_crate_data_mut(cnum); if cmeta.update_extern_crate(extern_crate) { // Propagate the extern crate info to dependencies if it was updated. let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - let dependencies = std::mem::take(&mut cmeta.dependencies); + let dependencies = mem::take(&mut cmeta.dependencies); for &dep_cnum in &dependencies { self.update_extern_crate(dep_cnum, extern_crate); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 542caf8622385..79aa9a547f7c6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -386,7 +386,7 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { } } -// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ @@ -398,7 +398,7 @@ macro_rules! record { }}; } -// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_array($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ @@ -1388,13 +1388,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if should_encode_fn_sig(def_kind) { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } - // FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]` - // do not have corresponding HIR nodes, so some queries usually making sense for - // anonymous constants will not work on them and panic. It's not clear whether it - // can cause any observable issues or not. - let anon_const_without_hir = def_kind == DefKind::AnonConst - && tcx.opt_hir_node(tcx.local_def_id_to_hir_id(local_id)).is_none(); - if should_encode_generics(def_kind) && !anon_const_without_hir { + if should_encode_generics(def_kind) { let g = tcx.generics_of(def_id); record!(self.tables.generics_of[def_id] <- g); record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id)); @@ -1408,7 +1402,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir { + if should_encode_type(tcx, local_id, def_kind) { record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); } if should_encode_constness(def_kind) { diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index e745913fabc37..c648b2bfe9b90 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -94,7 +94,7 @@ macro_rules! arena_types { // Note that this deliberately duplicates items in the `rustc_hir::arena`, // since we need to allocate this type on both the `rustc_hir` arena - // (during lowering) and the `librustc_middle` arena (for decoding MIR) + // (during lowering) and the `rustc_middle` arena (for decoding MIR) [decode] asm_template: rustc_ast::InlineAsmTemplatePiece, [decode] used_trait_imports: rustc_data_structures::unord::UnordSet, [decode] is_late_bound_map: rustc_data_structures::fx::FxIndexSet, diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 211da80020297..3ebbcd650302f 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -1,7 +1,6 @@ -use std::borrow::Cow; use std::fmt; -use rustc_errors::{codes::*, DiagnosticArgValue, DiagnosticMessage}; +use rustc_errors::{codes::*, DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage}; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -95,14 +94,14 @@ pub(super) struct ConstNotUsedTraitAlias { pub struct CustomSubdiagnostic<'a> { pub msg: fn() -> DiagnosticMessage, - pub add_args: Box, DiagnosticArgValue)) + 'a>, + pub add_args: Box, } impl<'a> CustomSubdiagnostic<'a> { pub fn label(x: fn() -> DiagnosticMessage) -> Self { Self::label_and_then(x, |_| {}) } - pub fn label_and_then, DiagnosticArgValue)) + 'a>( + pub fn label_and_then( msg: fn() -> DiagnosticMessage, f: F, ) -> Self { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 949b786e3a7d2..bf72aac10332e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -107,9 +107,8 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { fn next(&mut self) -> Option { if self.current_id.local_id.index() != 0 { self.current_id.local_id = ItemLocalId::new(0); - if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node)); - } + let node = self.map.tcx.hir_owner_node(self.current_id.owner); + return Some((self.current_id.owner, node)); } if self.current_id == CRATE_HIR_ID { return None; @@ -125,36 +124,48 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> { self.current_id = HirId::make_owner(parent_id.def_id); // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`. - if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) { - return Some((self.current_id.owner, node)); - } + let node = self.map.tcx.hir_owner_node(self.current_id.owner); + return Some((self.current_id.owner, node)); } } } impl<'tcx> TyCtxt<'tcx> { #[inline] - fn hir_owner(self, owner: OwnerId) -> Option> { - Some(self.hir_owner_nodes(owner).as_owner()?.node()) + fn expect_hir_owner_nodes(self, def_id: LocalDefId) -> &'tcx OwnerNodes<'tcx> { + self.opt_hir_owner_nodes(def_id) + .unwrap_or_else(|| span_bug!(self.def_span(def_id), "{def_id:?} is not an owner")) } - /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. - pub fn opt_hir_node(self, id: HirId) -> Option> { - let owner = self.hir_owner_nodes(id.owner).as_owner()?; - let node = owner.nodes[id.local_id].as_ref()?; - Some(node.node) + #[inline] + pub fn hir_owner_nodes(self, owner_id: OwnerId) -> &'tcx OwnerNodes<'tcx> { + self.expect_hir_owner_nodes(owner_id.def_id) + } + + #[inline] + fn opt_hir_owner_node(self, def_id: LocalDefId) -> Option> { + self.opt_hir_owner_nodes(def_id).map(|nodes| nodes.node()) + } + + #[inline] + pub fn expect_hir_owner_node(self, def_id: LocalDefId) -> OwnerNode<'tcx> { + self.expect_hir_owner_nodes(def_id).node() + } + + #[inline] + pub fn hir_owner_node(self, owner_id: OwnerId) -> OwnerNode<'tcx> { + self.hir_owner_nodes(owner_id).node() } /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. #[inline] pub fn opt_hir_node_by_def_id(self, id: LocalDefId) -> Option> { - self.opt_hir_node(self.opt_local_def_id_to_hir_id(id)?) + Some(self.hir_node(self.opt_local_def_id_to_hir_id(id)?)) } - /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found. - #[track_caller] + /// Retrieves the `hir::Node` corresponding to `id`. pub fn hir_node(self, id: HirId) -> Node<'tcx> { - self.opt_hir_node(id).unwrap_or_else(|| bug!("couldn't find HIR node for hir id {id:?}")) + self.hir_owner_nodes(id.owner).nodes[id.local_id].node } /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found. @@ -174,8 +185,8 @@ impl<'hir> Map<'hir> { #[inline] pub fn root_module(self) -> &'hir Mod<'hir> { - match self.tcx.hir_owner(CRATE_OWNER_ID) { - Some(OwnerNode::Crate(item)) => item, + match self.tcx.hir_owner_node(CRATE_OWNER_ID) { + OwnerNode::Crate(item) => item, _ => bug!(), } } @@ -211,10 +222,13 @@ impl<'hir> Map<'hir> { /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`]. pub fn opt_parent_id(self, id: HirId) -> Option { if id.local_id == ItemLocalId::from_u32(0) { + // FIXME: This function never returns `None` right now, and the parent chain end is + // determined by checking for `parent(id) == id`. This function should return `None` + // for the crate root instead. Some(self.tcx.hir_owner_parent(id.owner)) } else { - let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?; - let node = owner.nodes[id.local_id].as_ref()?; + let owner = self.tcx.hir_owner_nodes(id.owner); + let node = &owner.nodes[id.local_id]; let hir_id = HirId { owner: id.owner, local_id: node.parent }; // HIR indexing should have checked that. debug_assert_ne!(id.local_id, node.parent); @@ -233,58 +247,46 @@ impl<'hir> Map<'hir> { } pub fn find_parent(self, hir_id: HirId) -> Option> { - self.tcx.opt_hir_node(self.opt_parent_id(hir_id)?) + Some(self.tcx.hir_node(self.opt_parent_id(hir_id)?)) } pub fn get_if_local(self, id: DefId) -> Option> { - id.as_local().and_then(|id| self.tcx.opt_hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?)) + id.as_local() + .and_then(|id| Some(self.tcx.hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?))) } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { - let node = self.tcx.hir_owner(OwnerId { def_id: id })?; - node.generics() - } - - pub fn owner(self, id: OwnerId) -> OwnerNode<'hir> { - self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)) + self.tcx.opt_hir_owner_node(id)?.generics() } pub fn item(self, id: ItemId) -> &'hir Item<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_item() + self.tcx.hir_owner_node(id.owner_id).expect_item() } pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_trait_item() + self.tcx.hir_owner_node(id.owner_id).expect_trait_item() } pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_impl_item() + self.tcx.hir_owner_node(id.owner_id).expect_impl_item() } pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> { - self.tcx.hir_owner(id.owner_id).unwrap().expect_foreign_item() + self.tcx.hir_owner_node(id.owner_id).expect_foreign_item() } pub fn body(self, id: BodyId) -> &'hir Body<'hir> { - self.tcx.hir_owner_nodes(id.hir_id.owner).unwrap().bodies[&id.hir_id.local_id] + self.tcx.hir_owner_nodes(id.hir_id.owner).bodies[&id.hir_id.local_id] } #[track_caller] pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - if let Some(node) = self.tcx.opt_hir_node(hir_id) { - node.fn_decl() - } else { - bug!("no node for hir_id `{}`", hir_id) - } + self.tcx.hir_node(hir_id).fn_decl() } #[track_caller] pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - if let Some(node) = self.tcx.opt_hir_node(hir_id) { - node.fn_sig() - } else { - bug!("no node for hir_id `{}`", hir_id) - } + self.tcx.hir_node(hir_id).fn_sig() } #[track_caller] @@ -303,10 +305,7 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId { let parent = self.parent_id(hir_id); - assert!( - self.tcx.opt_hir_node(parent).is_some_and(|n| is_body_owner(n, hir_id)), - "{hir_id:?}" - ); + assert!(is_body_owner(self.tcx.hir_node(parent), hir_id), "{hir_id:?}"); parent } @@ -436,9 +435,9 @@ impl<'hir> Map<'hir> { pub fn get_module(self, module: LocalModDefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); - match self.tcx.hir_owner(hir_id.owner) { - Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. })) => (m, span, hir_id), - Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id), + match self.tcx.hir_owner_node(hir_id.owner) { + OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. }) => (m, span, hir_id), + OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), } } @@ -558,7 +557,7 @@ impl<'hir> Map<'hir> { /// until the crate root is reached. Prefer this over your own loop using `parent_id`. #[inline] pub fn parent_iter(self, current_id: HirId) -> impl Iterator)> { - self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.tcx.opt_hir_node(id)?))) + self.parent_id_iter(current_id).map(move |id| (id, self.tcx.hir_node(id))) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` @@ -610,7 +609,7 @@ impl<'hir> Map<'hir> { pub fn get_return_block(self, id: HirId) -> Option { let mut iter = self.parent_iter(id).peekable(); let mut ignore_tail = false; - if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.tcx.opt_hir_node(id) { + if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) { // When dealing with `return` statements, we don't care about climbing only tail // expressions. ignore_tail = true; @@ -726,8 +725,8 @@ impl<'hir> Map<'hir> { pub fn get_foreign_abi(self, hir_id: HirId) -> Abi { let parent = self.get_parent_item(hir_id); - if let Some(node) = self.tcx.hir_owner(parent) - && let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = node + if let OwnerNode::Item(Item { kind: ItemKind::ForeignMod { abi, .. }, .. }) = + self.tcx.hir_owner_node(parent) { return *abi; } @@ -737,50 +736,41 @@ impl<'hir> Map<'hir> { ) } - pub fn expect_owner(self, def_id: LocalDefId) -> OwnerNode<'hir> { - self.tcx - .hir_owner(OwnerId { def_id }) - .unwrap_or_else(|| bug!("expected owner for {:?}", def_id)) - } - pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> { - match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(OwnerNode::Item(item)) => item, + match self.tcx.expect_hir_owner_node(id) { + OwnerNode::Item(item) => item, _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> { - match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(OwnerNode::ImplItem(item)) => item, + match self.tcx.expect_hir_owner_node(id) { + OwnerNode::ImplItem(item) => item, _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> { - match self.tcx.hir_owner(OwnerId { def_id: id }) { - Some(OwnerNode::TraitItem(item)) => item, + match self.tcx.expect_hir_owner_node(id) { + OwnerNode::TraitItem(item) => item, _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } } pub fn get_fn_output(self, def_id: LocalDefId) -> Option<&'hir FnRetTy<'hir>> { - match self.tcx.hir_owner(OwnerId { def_id }) { - Some(node) => node.fn_decl().map(|fn_decl| &fn_decl.output), - _ => None, - } + Some(&self.tcx.opt_hir_owner_node(def_id)?.fn_decl()?.output) } pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> { - match self.tcx.opt_hir_node(id) { - Some(Node::Variant(variant)) => variant, + match self.tcx.hir_node(id) { + Node::Variant(variant) => variant, _ => bug!("expected variant, found {}", self.node_to_string(id)), } } pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> { - match self.tcx.hir_owner(id) { - Some(OwnerNode::ForeignItem(item)) => item, + match self.tcx.hir_owner_node(id) { + OwnerNode::ForeignItem(item) => item, _ => { bug!( "expected foreign item, found {}", @@ -791,18 +781,18 @@ impl<'hir> Map<'hir> { } pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> { - match self.tcx.opt_hir_node(id) { - Some(Node::Expr(expr)) => expr, + match self.tcx.hir_node(id) { + Node::Expr(expr) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)), } } #[inline] fn opt_ident(self, id: HirId) -> Option { - match self.tcx.opt_hir_node(id)? { + match self.tcx.hir_node(id) { Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), // A `Ctor` doesn't have an identifier itself, but its parent - // struct/variant does. Compare with `hir::Map::opt_span`. + // struct/variant does. Compare with `hir::Map::span`. Node::Ctor(..) => match self.find_parent(id)? { Node::Item(item) => Some(item.ident), Node::Variant(variant) => Some(variant.ident), @@ -840,11 +830,6 @@ impl<'hir> Map<'hir> { /// Gets the span of the definition of the specified HIR node. /// This is used by `tcx.def_span`. pub fn span(self, hir_id: HirId) -> Span { - self.opt_span(hir_id) - .unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id)) - } - - pub fn opt_span(self, hir_id: HirId) -> Option { fn until_within(outer: Span, end: Span) -> Span { if let Some(end) = end.find_ancestor_inside(outer) { outer.with_hi(end.hi()) @@ -868,7 +853,7 @@ impl<'hir> Map<'hir> { } } - let span = match self.tcx.opt_hir_node(hir_id)? { + let span = match self.tcx.hir_node(hir_id) { // Function-like. Node::Item(Item { kind: ItemKind::Fn(sig, ..), span: outer_span, .. }) | Node::TraitItem(TraitItem { @@ -940,7 +925,7 @@ impl<'hir> Map<'hir> { ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()), _ => named_span(item.span, item.ident, None), }, - Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)), + Node::Ctor(_) => return self.span(self.parent_id(hir_id)), Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl_span, .. }), span, @@ -952,7 +937,7 @@ impl<'hir> Map<'hir> { _ => self.span_with_body(hir_id), }; debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt()); - Some(span) + span } /// Like `hir.span()`, but includes the body of items @@ -989,6 +974,9 @@ impl<'hir> Map<'hir> { Node::Infer(i) => i.span, Node::Local(local) => local.span, Node::Crate(item) => item.spans.inner_span, + Node::WhereBoundPredicate(pred) => pred.span, + Node::ArrayLenInfer(inf) => inf.span, + Node::Err(span) => *span, } } @@ -1052,8 +1040,8 @@ impl<'hir> Map<'hir> { } impl<'hir> intravisit::Map<'hir> for Map<'hir> { - fn find(&self, hir_id: HirId) -> Option> { - self.tcx.opt_hir_node(hir_id) + fn hir_node(&self, hir_id: HirId) -> Node<'hir> { + self.tcx.hir_node(hir_id) } fn body(&self, id: BodyId) -> &'hir Body<'hir> { @@ -1170,8 +1158,8 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default(); let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str()); - match map.tcx.opt_hir_node(id) { - Some(Node::Item(item)) => { + match map.tcx.hir_node(id) { + Node::Item(item) => { let item_str = match item.kind { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "use", @@ -1199,10 +1187,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { }; format!("{id} ({item_str} {})", path_str(item.owner_id.def_id)) } - Some(Node::ForeignItem(item)) => { + Node::ForeignItem(item) => { format!("{id} (foreign item {})", path_str(item.owner_id.def_id)) } - Some(Node::ImplItem(ii)) => { + Node::ImplItem(ii) => { let kind = match ii.kind { ImplItemKind::Const(..) => "assoc const", ImplItemKind::Fn(..) => "method", @@ -1210,7 +1198,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { }; format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id)) } - Some(Node::TraitItem(ti)) => { + Node::TraitItem(ti) => { let kind = match ti.kind { TraitItemKind::Const(..) => "assoc constant", TraitItemKind::Fn(..) => "trait method", @@ -1219,38 +1207,40 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id)) } - Some(Node::Variant(variant)) => { + Node::Variant(variant) => { format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id)) } - Some(Node::Field(field)) => { + Node::Field(field) => { format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id)) } - Some(Node::AnonConst(_)) => node_str("const"), - Some(Node::ConstBlock(_)) => node_str("const"), - Some(Node::Expr(_)) => node_str("expr"), - Some(Node::ExprField(_)) => node_str("expr field"), - Some(Node::Stmt(_)) => node_str("stmt"), - Some(Node::PathSegment(_)) => node_str("path segment"), - Some(Node::Ty(_)) => node_str("type"), - Some(Node::TypeBinding(_)) => node_str("type binding"), - Some(Node::TraitRef(_)) => node_str("trait ref"), - Some(Node::Pat(_)) => node_str("pat"), - Some(Node::PatField(_)) => node_str("pattern field"), - Some(Node::Param(_)) => node_str("param"), - Some(Node::Arm(_)) => node_str("arm"), - Some(Node::Block(_)) => node_str("block"), - Some(Node::Infer(_)) => node_str("infer"), - Some(Node::Local(_)) => node_str("local"), - Some(Node::Ctor(ctor)) => format!( + Node::AnonConst(_) => node_str("const"), + Node::ConstBlock(_) => node_str("const"), + Node::Expr(_) => node_str("expr"), + Node::ExprField(_) => node_str("expr field"), + Node::Stmt(_) => node_str("stmt"), + Node::PathSegment(_) => node_str("path segment"), + Node::Ty(_) => node_str("type"), + Node::TypeBinding(_) => node_str("type binding"), + Node::TraitRef(_) => node_str("trait ref"), + Node::Pat(_) => node_str("pat"), + Node::PatField(_) => node_str("pattern field"), + Node::Param(_) => node_str("param"), + Node::Arm(_) => node_str("arm"), + Node::Block(_) => node_str("block"), + Node::Infer(_) => node_str("infer"), + Node::Local(_) => node_str("local"), + Node::Ctor(ctor) => format!( "{id} (ctor {})", ctor.ctor_def_id().map_or("".into(), |def_id| path_str(def_id)), ), - Some(Node::Lifetime(_)) => node_str("lifetime"), - Some(Node::GenericParam(param)) => { + Node::Lifetime(_) => node_str("lifetime"), + Node::GenericParam(param) => { format!("{id} (generic_param {})", path_str(param.def_id)) } - Some(Node::Crate(..)) => String::from("(root_crate)"), - None => format!("{id} (unknown node)"), + Node::Crate(..) => String::from("(root_crate)"), + Node::WhereBoundPredicate(_) => node_str("where bound predicate"), + Node::ArrayLenInfer(_) => node_str("array len infer"), + Node::Err(_) => node_str("error"), } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 2d4d5deaefa93..f66cd2370e3ee 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -12,7 +12,7 @@ use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; -use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, ExpnId}; /// Gather the LocalDefId for each item-like within a module, including items contained within /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. @@ -127,21 +127,15 @@ pub fn provide(providers: &mut Providers) { providers.hir_crate_items = map::hir_crate_items; providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; - providers.opt_local_def_id_to_hir_id = |tcx, id| { - let owner = tcx.hir_crate(()).owners[id].map(|_| ()); - Some(match owner { - MaybeOwner::Owner(_) => HirId::make_owner(id), - MaybeOwner::Phantom => bug!("No HirId for {:?}", id), + providers.opt_local_def_id_to_hir_id = |tcx, def_id| { + Some(match tcx.hir_crate(()).owners[def_id] { + MaybeOwner::Owner(_) => HirId::make_owner(def_id), MaybeOwner::NonOwner(hir_id) => hir_id, + MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id), }) }; - providers.hir_owner_nodes = |tcx, id| { - if let Some(i) = tcx.hir_crate(()).owners.get(id.def_id) { - i.map(|i| &i.nodes) - } else { - MaybeOwner::Phantom - } - }; + providers.opt_hir_owner_nodes = + |tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { // Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash. tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| { @@ -154,10 +148,7 @@ pub fn provide(providers: &mut Providers) { providers.hir_attrs = |tcx, id| { tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) }; - providers.def_span = |tcx, def_id| { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP) - }; + providers.def_span = |tcx, def_id| tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); providers.def_ident_span = |tcx, def_id| { let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir().opt_ident_span(hir_id) diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index c35799ef47f2b..63c0ebd5f6b79 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -194,33 +194,37 @@ impl<'tcx> UnifyValue for ConstVariableValue<'tcx> { /// values for the effect inference variable #[derive(Clone, Copy, Debug)] pub enum EffectVarValue<'tcx> { - /// The host effect is on, enabling access to syscalls, filesystem access, etc. - Host, - /// The host effect is off. Execution is restricted to const operations only. - NoHost, - Const(ty::Const<'tcx>), + Unknown, + Known(ty::Const<'tcx>), } impl<'tcx> EffectVarValue<'tcx> { - pub fn as_const(self, tcx: TyCtxt<'tcx>) -> ty::Const<'tcx> { + pub fn known(self) -> Option> { match self { - EffectVarValue::Host => tcx.consts.true_, - EffectVarValue::NoHost => tcx.consts.false_, - EffectVarValue::Const(c) => c, + EffectVarValue::Unknown => None, + EffectVarValue::Known(value) => Some(value), + } + } + + pub fn is_unknown(self) -> bool { + match self { + EffectVarValue::Unknown => true, + EffectVarValue::Known(_) => false, } } } impl<'tcx> UnifyValue for EffectVarValue<'tcx> { - type Error = (EffectVarValue<'tcx>, EffectVarValue<'tcx>); + type Error = NoError; fn unify_values(value1: &Self, value2: &Self) -> Result { - match (value1, value2) { - (EffectVarValue::Host, EffectVarValue::Host) => Ok(EffectVarValue::Host), - (EffectVarValue::NoHost, EffectVarValue::NoHost) => Ok(EffectVarValue::NoHost), - (EffectVarValue::NoHost | EffectVarValue::Host, _) - | (_, EffectVarValue::NoHost | EffectVarValue::Host) => Err((*value1, *value2)), - (EffectVarValue::Const(_), EffectVarValue::Const(_)) => { - bug!("equating two const variables, both of which have known values") + match (*value1, *value2) { + (EffectVarValue::Unknown, EffectVarValue::Unknown) => Ok(EffectVarValue::Unknown), + (EffectVarValue::Unknown, EffectVarValue::Known(val)) + | (EffectVarValue::Known(val), EffectVarValue::Unknown) => { + Ok(EffectVarValue::Known(val)) + } + (EffectVarValue::Known(_), EffectVarValue::Known(_)) => { + bug!("equating known inference variables: {value1:?} {value2:?}") } } } @@ -229,7 +233,7 @@ impl<'tcx> UnifyValue for EffectVarValue<'tcx> { #[derive(PartialEq, Copy, Clone, Debug)] pub struct EffectVidKey<'tcx> { pub vid: ty::EffectVid, - pub phantom: PhantomData>, + pub phantom: PhantomData>, } impl<'tcx> From for EffectVidKey<'tcx> { @@ -239,7 +243,7 @@ impl<'tcx> From for EffectVidKey<'tcx> { } impl<'tcx> UnifyKey for EffectVidKey<'tcx> { - type Value = Option>; + type Value = EffectVarValue<'tcx>; #[inline] fn index(&self) -> u32 { self.vid.as_u32() diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index ddfb2ece39f10..2aaece1060a1f 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,6 +30,7 @@ #![feature(assert_matches)] #![feature(box_patterns)] #![feature(core_intrinsics)] +#![feature(const_type_name)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(coroutines)] @@ -48,7 +49,7 @@ #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(control_flow_enum)] -#![cfg_attr(not(bootstrap), feature(trait_upcasting))] +#![feature(trait_upcasting)] #![feature(try_blocks)] #![feature(decl_macro)] #![feature(extract_if)] @@ -57,8 +58,10 @@ #![feature(const_option)] #![feature(ptr_alignment_type)] #![feature(macro_metavar_expr)] -#![allow(rustc::potential_query_instability)] #![allow(internal_features)] +#![allow(rustc::potential_query_instability)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #[macro_use] extern crate bitflags; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index e11c9371118cb..7d6d39a2a8a39 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -74,35 +74,32 @@ bitflags! { /// `#[used]`: indicates that LLVM can't eliminate this function (but the /// linker can!). const USED = 1 << 9; - /// `#[ffi_returns_twice]`, indicates that an extern function can return - /// multiple times - const FFI_RETURNS_TWICE = 1 << 10; /// `#[track_caller]`: allow access to the caller location - const TRACK_CALLER = 1 << 11; + const TRACK_CALLER = 1 << 10; /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function /// declaration. - const FFI_PURE = 1 << 12; + const FFI_PURE = 1 << 11; /// #[ffi_const]: applies clang's `const` attribute to a foreign function /// declaration. - const FFI_CONST = 1 << 13; + const FFI_CONST = 1 << 12; /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a /// function as an entry function from Non-Secure code. - const CMSE_NONSECURE_ENTRY = 1 << 14; + const CMSE_NONSECURE_ENTRY = 1 << 13; /// `#[coverage(off)]`: indicates that the function should be ignored by /// the MIR `InstrumentCoverage` pass and not added to the coverage map /// during codegen. - const NO_COVERAGE = 1 << 15; + const NO_COVERAGE = 1 << 14; /// `#[used(linker)]`: /// indicates that neither LLVM nor the linker will eliminate this function. - const USED_LINKER = 1 << 16; + const USED_LINKER = 1 << 15; /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory. - const DEALLOCATOR = 1 << 17; + const DEALLOCATOR = 1 << 16; /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory. - const REALLOCATOR = 1 << 18; + const REALLOCATOR = 1 << 17; /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory. - const ALLOCATOR_ZEROED = 1 << 19; + const ALLOCATOR_ZEROED = 1 << 18; /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function. - const NO_BUILTINS = 1 << 20; + const NO_BUILTINS = 1 << 19; } } rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags } diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index f92c72c8a588c..a4e193ba2c942 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -23,7 +23,7 @@ impl<'tcx> TyCtxt<'tcx> { }) } - /// Given a [`DefId`] of a [`Fn`], [`FnMut`] or [`FnOnce`] traits, + /// Given a [`DefId`] of one of the [`Fn`], [`FnMut`] or [`FnOnce`] traits, /// returns a corresponding [`ty::ClosureKind`]. /// For any other [`DefId`] return `None`. pub fn fn_trait_kind_from_def_id(self, id: DefId) -> Option { @@ -36,6 +36,19 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Given a [`DefId`] of one of the `AsyncFn`, `AsyncFnMut` or `AsyncFnOnce` traits, + /// returns a corresponding [`ty::ClosureKind`]. + /// For any other [`DefId`] return `None`. + pub fn async_fn_trait_kind_from_def_id(self, id: DefId) -> Option { + let items = self.lang_items(); + match Some(id) { + x if x == items.async_fn_trait() => Some(ty::ClosureKind::Fn), + x if x == items.async_fn_mut_trait() => Some(ty::ClosureKind::FnMut), + x if x == items.async_fn_once_trait() => Some(ty::ClosureKind::FnOnce), + _ => None, + } + } + /// Given a [`ty::ClosureKind`], get the [`DefId`] of its corresponding `Fn`-family /// trait, if it is defined. pub fn fn_trait_kind_to_def_id(self, kind: ty::ClosureKind) -> Option { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 95574aee499f2..0f69ab93452f7 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -5,7 +5,9 @@ use crate::mir::{ConstAlloc, ConstValue}; use crate::ty::{layout, tls, Ty, TyCtxt, ValTree}; use rustc_data_structures::sync::Lock; -use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; +use rustc_errors::{ + DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, +}; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; @@ -485,7 +487,7 @@ pub trait MachineStopType: Any + fmt::Debug + Send { fn diagnostic_message(&self) -> DiagnosticMessage; /// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to /// fluent for formatting the translated diagnostic message. - fn add_args(self: Box, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)); + fn add_args(self: Box, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)); } impl dyn MachineStopType { diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 5ecff04f3ae35..e937c17c8acec 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -418,8 +418,8 @@ impl<'tcx, Prov: Provenance> Scalar { #[inline] pub fn to_float(self) -> InterpResult<'tcx, F> { - // Going through `to_uint` to check size and truncation. - Ok(F::from_bits(self.to_uint(Size::from_bits(F::BITS))?)) + // Going through `to_bits` to check size and truncation. + Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?)) } #[inline] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 37c5bba46a7d8..e22d522862837 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -14,7 +14,9 @@ use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_data_structures::captures::Captures; -use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; +use rustc_errors::{ + DiagnosticArgName, DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, +}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind}; @@ -138,8 +140,12 @@ fn to_profiler_name(type_name: &'static str) -> &'static str { /// loop that goes over each available MIR and applies `run_pass`. pub trait MirPass<'tcx> { fn name(&self) -> &'static str { - let name = std::any::type_name::(); - if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name } + // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirLint` + const { + let name = std::any::type_name::(); + crate::util::common::c_name(name) + } } fn profiler_name(&self) -> &'static str { @@ -260,6 +266,25 @@ pub struct CoroutineInfo<'tcx> { /// Coroutine drop glue. This field is populated after the state transform pass. pub coroutine_drop: Option>, + /// The body of the coroutine, modified to take its upvars by move rather than by ref. + /// + /// This is used by coroutine-closures, which must return a different flavor of coroutine + /// when called using `AsyncFnOnce::call_once`. It is produced by the `ByMoveBody` pass which + /// is run right after building the initial MIR, and will only be populated for coroutines + /// which come out of the async closure desugaring. + /// + /// This body should be processed in lockstep with the containing body -- any optimization + /// passes, etc, should be applied to this body as well. This is done automatically if + /// using `run_passes`. + pub by_move_body: Option>, + + /// The body of the coroutine, modified to take its upvars by mutable ref rather than by + /// immutable ref. + /// + /// FIXME(async_closures): This is literally the same body as the parent body. Find a better + /// way to represent the by-mut signature (or cap the closure-kind of the coroutine). + pub by_mut_body: Option>, + /// The layout of a coroutine. This field is populated after the state transform pass. pub coroutine_layout: Option>, @@ -279,6 +304,8 @@ impl<'tcx> CoroutineInfo<'tcx> { coroutine_kind, yield_ty: Some(yield_ty), resume_ty: Some(resume_ty), + by_move_body: None, + by_mut_body: None, coroutine_drop: None, coroutine_layout: None, } @@ -589,6 +616,14 @@ impl<'tcx> Body<'tcx> { self.coroutine.as_ref().and_then(|coroutine| coroutine.coroutine_drop.as_ref()) } + pub fn coroutine_by_move_body(&self) -> Option<&Body<'tcx>> { + self.coroutine.as_ref()?.by_move_body.as_ref() + } + + pub fn coroutine_by_mut_body(&self) -> Option<&Body<'tcx>> { + self.coroutine.as_ref()?.by_mut_body.as_ref() + } + #[inline] pub fn coroutine_kind(&self) -> Option { self.coroutine.as_ref().map(|coroutine| coroutine.coroutine_kind) diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 91fdf0b312991..6937df7bb1897 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -402,6 +402,8 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 3b60eba2dfe0a..b601b465668e9 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -907,6 +907,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { NullOp::SizeOf => write!(fmt, "SizeOf({t})"), NullOp::AlignOf => write!(fmt, "AlignOf({t})"), NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"), + NullOp::DebugAssertions => write!(fmt, "cfg!(debug_assertions)"), } } ThreadLocalRef(did) => ty::tls::with(|tcx| { @@ -990,7 +991,8 @@ impl<'tcx> Debug for Rvalue<'tcx> { }) } - AggregateKind::Closure(def_id, args) => ty::tls::with(|tcx| { + AggregateKind::Closure(def_id, args) + | AggregateKind::CoroutineClosure(def_id, args) => ty::tls::with(|tcx| { let name = if tcx.sess.opts.unstable_opts.span_free_formats { let args = tcx.lift(args).unwrap(); format!("{{closure@{}}}", tcx.def_path_str_with_args(def_id, args),) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 98642adc19090..90b6df1dd1f5e 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -189,7 +189,7 @@ pub struct BorrowCheckResult<'tcx> { /// The result of the `mir_const_qualif` query. /// -/// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in +/// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each /// `Qualif`. #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)] @@ -197,7 +197,6 @@ pub struct ConstQualifs { pub has_mut_interior: bool, pub needs_drop: bool, pub needs_non_const_drop: bool, - pub custom_eq: bool, pub tainted_by_errors: Option, } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index a4b6c4f9c3f19..40af453f6ce6f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1350,6 +1350,7 @@ pub enum AggregateKind<'tcx> { Closure(DefId, GenericArgsRef<'tcx>), Coroutine(DefId, GenericArgsRef<'tcx>), + CoroutineClosure(DefId, GenericArgsRef<'tcx>), } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -1360,6 +1361,8 @@ pub enum NullOp<'tcx> { AlignOf, /// Returns the offset of a field OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but expanded in codegen + DebugAssertions, } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 5597609c7d796..5bc151de659c3 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -194,6 +194,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { tcx.types.usize } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => tcx.types.bool, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), AggregateKind::Tuple => { @@ -202,6 +203,9 @@ impl<'tcx> Rvalue<'tcx> { AggregateKind::Adt(did, _, args, _, _) => tcx.type_of(did).instantiate(tcx, args), AggregateKind::Closure(did, args) => Ty::new_closure(tcx, did, args), AggregateKind::Coroutine(did, args) => Ty::new_coroutine(tcx, did, args), + AggregateKind::CoroutineClosure(did, args) => { + Ty::new_coroutine_closure(tcx, did, args) + } }, Rvalue::ShallowInitBox(_, ty) => Ty::new_box(tcx, ty), Rvalue::CopyForDeref(ref place) => place.ty(local_decls, tcx).ty, diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 0fe33e441f430..91b7952bec5e8 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -292,7 +292,7 @@ impl AssertKind { } } - pub fn add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue)) + pub fn add_args(self, adder: &mut dyn FnMut(DiagnosticArgName, DiagnosticArgValue)) where O: fmt::Debug, { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 4696f54c89787..2c5ca82a4cd39 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -345,6 +345,8 @@ macro_rules! make_mir_visitor { ty::InstanceDef::Virtual(_def_id, _) | ty::InstanceDef::ThreadLocalShim(_def_id) | ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } | + ty::InstanceDef::ConstructCoroutineInClosureShim { coroutine_closure_def_id: _def_id, target_kind: _ } | + ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id, target_kind: _ } | ty::InstanceDef::DropGlue(_def_id, None) => {} ty::InstanceDef::FnPtrShim(_def_id, ty) | @@ -739,6 +741,12 @@ macro_rules! make_mir_visitor { ) => { self.visit_args(coroutine_args, location); } + AggregateKind::CoroutineClosure( + _, + coroutine_closure_args, + ) => { + self.visit_args(coroutine_closure_args, location); + } } for operand in operands { diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 1b01df6a18714..a272a51f32747 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -185,8 +185,8 @@ impl EraseType for Option>> { type Result = [u8; size_of::>>>()]; } -impl EraseType for rustc_hir::MaybeOwner<&'_ T> { - type Result = [u8; size_of::>()]; +impl EraseType for rustc_hir::MaybeOwner<'_> { + type Result = [u8; size_of::>()]; } impl EraseType for ty::EarlyBinder { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b383a6f5e52c8..938fba0ed0981 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -190,11 +190,11 @@ rustc_queries! { desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key) } } - /// Gives access to the HIR nodes and bodies inside the HIR owner `key`. + /// Gives access to the HIR nodes and bodies inside `key` if it's a HIR owner. /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_nodes(key: hir::OwnerId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { + query opt_hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key) } } @@ -755,6 +755,11 @@ rustc_queries! { separate_provide_extern } + query coroutine_for_closure(def_id: DefId) -> DefId { + desc { |_tcx| "Given a coroutine-closure def id, return the def id of the coroutine returned by it" } + separate_provide_extern + } + /// Gets a map with the variance of every item; use `variances_of` instead. query crate_variances(_: ()) -> &'tcx ty::CrateVariancesMap<'tcx> { arena_cache diff --git a/compiler/rustc_middle/src/tests.rs b/compiler/rustc_middle/src/tests.rs index 757e0bd3bfbf9..49960cc0bb2a2 100644 --- a/compiler/rustc_middle/src/tests.rs +++ b/compiler/rustc_middle/src/tests.rs @@ -1,7 +1,7 @@ use super::*; -// FIXME(#27438): right now the unit tests of librustc_middle don't refer to any actual -// functions generated in librustc_data_structures (all +// FIXME(#27438): right now the unit tests of rustc_middle don't refer to any actual +// functions generated in rustc_data_structures (all // references are through generic functions), but statics are // referenced from time to time. Due to this bug we won't // actually correctly link in the statics unless we also diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 0fed4ccc62a83..e1e5d68148fe8 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -1038,7 +1038,6 @@ impl<'tcx> PatRangeBoundary<'tcx> { a.partial_cmp(&b) } ty::Int(ity) => { - use rustc_middle::ty::layout::IntegerExt; let size = rustc_target::abi::Integer::from_int_ty(&tcx, *ity).size(); let a = size.sign_extend(a) as i128; let b = size.sign_extend(b) as i128; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 135680b934936..894acf3c2aa5f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -292,6 +292,8 @@ pub enum ObligationCauseCode<'tcx> { SizedArgumentType(Option), /// Return type must be `Sized`. SizedReturnType, + /// Return type of a call expression must be `Sized`. + SizedCallReturnType, /// Yield type must be `Sized`. SizedYieldType, /// Inline asm operand type must be `Sized`. diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 64f4af08e12ed..28eba133c76df 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -134,6 +134,15 @@ pub enum SelectionCandidate<'tcx> { is_const: bool, }, + /// Implementation of an `AsyncFn`-family trait by one of the anonymous types + /// generated for an `async ||` expression. + AsyncClosureCandidate, + + /// Implementation of the the `AsyncFnKindHelper` helper trait, which + /// is used internally to delay computation for async closures until after + /// upvar analysis is performed in HIR typeck. + AsyncFnKindHelperCandidate, + /// Implementation of a `Coroutine` trait by one of the anonymous types /// generated for a coroutine. CoroutineCandidate, diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index b4054f8ff5edd..fd5302dc75b13 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -1,46 +1,60 @@ use rustc_data_structures::fx::FxHashSet; -use crate::ty::{PolyTraitRef, TyCtxt}; +use crate::ty::{Clause, PolyTraitRef, ToPolyTraitRef, ToPredicate, TyCtxt}; -/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits. +/// Given a [`PolyTraitRef`], get the [`Clause`]s implied by the trait's definition. +/// /// This only exists in `rustc_middle` because the more powerful elaborator depends on /// `rustc_infer` for elaborating outlives bounds -- this should only be used for pretty /// printing. +pub fn super_predicates_for_pretty_printing<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: PolyTraitRef<'tcx>, +) -> impl Iterator> { + let clause = trait_ref.to_predicate(tcx); + Elaborator { tcx, visited: FxHashSet::from_iter([clause]), stack: vec![clause] } +} + +/// Like [`super_predicates_for_pretty_printing`], except it only returns traits and filters out +/// all other [`Clause`]s. pub fn supertraits_for_pretty_printing<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: PolyTraitRef<'tcx>, ) -> impl Iterator> { - Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] } + super_predicates_for_pretty_printing(tcx, trait_ref).filter_map(|clause| { + clause.as_trait_clause().map(|trait_clause| trait_clause.to_poly_trait_ref()) + }) } struct Elaborator<'tcx> { tcx: TyCtxt<'tcx>, - visited: FxHashSet>, - stack: Vec>, + visited: FxHashSet>, + stack: Vec>, } impl<'tcx> Elaborator<'tcx> { fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) { - let supertrait_refs = self - .tcx - .super_predicates_of(trait_ref.def_id()) - .predicates - .into_iter() - .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause()) - .map(|t| t.map_bound(|pred| pred.trait_ref)) - .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); - - self.stack.extend(supertrait_refs); + let super_predicates = + self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( + |&(pred, _)| { + let clause = pred.subst_supertrait(self.tcx, &trait_ref); + self.visited.insert(clause).then_some(clause) + }, + ); + + self.stack.extend(super_predicates); } } impl<'tcx> Iterator for Elaborator<'tcx> { - type Item = PolyTraitRef<'tcx>; + type Item = Clause<'tcx>; - fn next(&mut self) -> Option> { - if let Some(trait_ref) = self.stack.pop() { - self.elaborate(trait_ref); - Some(trait_ref) + fn next(&mut self) -> Option> { + if let Some(clause) = self.stack.pop() { + if let Some(trait_clause) = clause.as_trait_clause() { + self.elaborate(trait_clause.to_poly_trait_ref()); + } + Some(clause) } else { None } diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index a2794a100f14d..417f1932c6f90 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -55,7 +55,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> { fn regions( &mut self, a: ty::Region<'tcx>, - b: ty::Region<'tcx>, + _b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { Ok(a) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 6ec1dec97816c..a930c7e8ebf80 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -7,6 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; +use rustc_type_ir::ConstKind as IrConstKind; use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo}; mod int; @@ -19,7 +20,7 @@ use rustc_span::Span; use rustc_span::DUMMY_SP; pub use valtree::*; -use super::sty::ConstKind; +pub type ConstKind<'tcx> = IrConstKind>; /// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index f7c33960fdd83..515d564e81db7 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -249,11 +249,6 @@ impl ScalarInt { } } - #[inline] - pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result { - Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64) - } - /// Tries to convert the `ScalarInt` to an unsigned integer of the given size. /// Fails if the size of the `ScalarInt` is not equal to `size` and returns the /// `ScalarInt`s size in that case. @@ -262,24 +257,12 @@ impl ScalarInt { self.to_bits(size) } - // Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt` - // in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size` - // value of the `ScalarInt` in that case. - #[inline] - pub fn try_to_bool(self) -> Result { - match self.try_to_u8()? { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(self.size()), - } - } - // Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt` // in not equal to `Size { raw: 1 }` and returns the `size` value of the `ScalarInt` in // that case. #[inline] pub fn try_to_u8(self) -> Result { - self.to_bits(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u16`. Fails if the size of the `ScalarInt` @@ -287,7 +270,7 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u16(self) -> Result { - self.to_bits(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u32`. Fails if the `size` of the `ScalarInt` @@ -295,7 +278,7 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u32(self) -> Result { - self.to_bits(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u64`. Fails if the `size` of the `ScalarInt` @@ -303,7 +286,7 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u64(self) -> Result { - self.to_bits(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap()) + self.try_to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap()) } /// Tries to convert the `ScalarInt` to `u128`. Fails if the `size` of the `ScalarInt` @@ -311,7 +294,24 @@ impl ScalarInt { /// that case. #[inline] pub fn try_to_u128(self) -> Result { - self.to_bits(Size::from_bits(128)) + self.try_to_uint(Size::from_bits(128)) + } + + #[inline] + pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result { + self.try_to_uint(tcx.data_layout.pointer_size).map(|v| u64::try_from(v).unwrap()) + } + + // Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt` + // in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size` + // value of the `ScalarInt` in that case. + #[inline] + pub fn try_to_bool(self) -> Result { + match self.try_to_u8()? { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(self.size()), + } } /// Tries to convert the `ScalarInt` to a signed integer of the given size. @@ -357,6 +357,27 @@ impl ScalarInt { pub fn try_to_i128(self) -> Result { self.try_to_int(Size::from_bits(128)) } + + #[inline] + pub fn try_to_target_isize(&self, tcx: TyCtxt<'_>) -> Result { + self.try_to_int(tcx.data_layout.pointer_size).map(|v| i64::try_from(v).unwrap()) + } + + #[inline] + pub fn try_to_float(self) -> Result { + // Going through `to_uint` to check size and truncation. + Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?)) + } + + #[inline] + pub fn try_to_f32(self) -> Result { + self.try_to_float() + } + + #[inline] + pub fn try_to_f64(self) -> Result { + self.try_to_float() + } } macro_rules! from { @@ -399,11 +420,7 @@ impl TryFrom for bool { type Error = Size; #[inline] fn try_from(int: ScalarInt) -> Result { - int.to_bits(Size::from_bytes(1)).and_then(|u| match u { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(Size::from_bytes(1)), - }) + int.try_to_bool() } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0d53870a0baf0..b747f0a4fb646 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1193,7 +1193,7 @@ impl<'tcx> TyCtxt<'tcx> { let (suitable_region_binding_scope, bound_region) = loop { let def_id = match region.kind() { ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?, - ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(), + ty::ReEarlyParam(ebr) => ebr.def_id.as_local()?, _ => return None, // not a free region }; let scope = self.local_parent(def_id); @@ -1544,6 +1544,7 @@ impl<'tcx> TyCtxt<'tcx> { CoroutineWitness, Dynamic, Closure, + CoroutineClosure, Tuple, Bound, Param, diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 8678f388298c2..13cc5cbed443f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -98,6 +98,7 @@ impl<'tcx, T> IsSuggestable<'tcx> for T where T: TypeVisitable> + TypeFoldable>, { + #[tracing::instrument(level = "debug", skip(tcx))] fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool { self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue() } @@ -533,6 +534,9 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { match c.kind() { ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {} + // effect variables are always suggestable, because they are not visible + ConstKind::Infer(InferConst::EffectVar(_)) => {} + ConstKind::Infer(..) | ConstKind::Bound(..) | ConstKind::Placeholder(..) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 0e44878524bf0..80b763d1469e4 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -299,7 +299,7 @@ impl<'tcx> Ty<'tcx> { }, ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(..) => "trait object".into(), - ty::Closure(..) => "closure".into(), + ty::Closure(..) | ty::CoroutineClosure(..) => "closure".into(), ty::Coroutine(def_id, ..) => { format!("{:#}", tcx.coroutine_kind(def_id).unwrap()).into() } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index b71919adc58fa..adc153c4dfd2d 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -128,7 +128,9 @@ pub fn simplify_type<'tcx>( _ => Some(SimplifiedType::MarkerTraitObject), }, ty::Ref(_, _, mutbl) => Some(SimplifiedType::Ref(mutbl)), - ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(SimplifiedType::Closure(def_id)), + ty::FnDef(def_id, _) | ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _) => { + Some(SimplifiedType::Closure(def_id)) + } ty::Coroutine(def_id, _) => Some(SimplifiedType::Coroutine(def_id)), ty::CoroutineWitness(def_id, _) => Some(SimplifiedType::CoroutineWitness(def_id)), ty::Never => Some(SimplifiedType::Never), @@ -236,6 +238,7 @@ impl DeepRejectCtxt { | ty::Foreign(..) => debug_assert!(impl_ty.is_known_rigid()), ty::FnDef(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Placeholder(..) @@ -312,7 +315,7 @@ impl DeepRejectCtxt { }, // Impls cannot contain these types as these cannot be named directly. - ty::FnDef(..) | ty::Closure(..) | ty::Coroutine(..) => false, + ty::FnDef(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) => false, // Placeholder types don't unify with anything on their own ty::Placeholder(..) | ty::Bound(..) => false, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 0c1d10914146f..0f4b5fe228c96 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -136,6 +136,22 @@ impl FlagComputation { self.add_ty(args.tupled_upvars_ty()); } + &ty::CoroutineClosure(_, args) => { + let args = args.as_coroutine_closure(); + let should_remove_further_specializable = + !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); + self.add_args(args.parent_args()); + if should_remove_further_specializable { + self.flags -= TypeFlags::STILL_FURTHER_SPECIALIZABLE; + } + + self.add_ty(args.kind_ty()); + self.add_ty(args.signature_parts_ty()); + self.add_ty(args.tupled_upvars_ty()); + self.add_ty(args.coroutine_captures_by_ref_ty()); + self.add_ty(args.coroutine_witness_ty()); + } + &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); self.add_flags(TypeFlags::HAS_TY_BOUND); diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 69ad6810c6fe0..b9fff660a03b9 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -2,7 +2,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; -use crate::ty::sty::{ClosureArgs, CoroutineArgs, InlineConstArgs}; +use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs}; use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; @@ -288,6 +288,14 @@ impl<'tcx> GenericArgs<'tcx> { ClosureArgs { args: self } } + /// Interpret these generic args as the args of a coroutine-closure type. + /// Coroutine-closure args have a particular structure controlled by the + /// compiler that encodes information like the signature and closure kind; + /// see `ty::CoroutineClosureArgs` struct for more comments. + pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs<'tcx> { + CoroutineClosureArgs { args: self } + } + /// Interpret these generic args as the args of a coroutine type. /// Coroutine args have a particular structure controlled by the /// compiler that encodes information like the signature and coroutine kind; diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 293fdb026b685..8848d216f5b49 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -82,11 +82,33 @@ pub enum InstanceDef<'tcx> { /// details on that). Virtual(DefId, usize), - /// `<[FnMut closure] as FnOnce>::call_once`. + /// `<[FnMut/Fn closure] as FnOnce>::call_once`. /// /// The `DefId` is the ID of the `call_once` method in `FnOnce`. + /// + /// This generates a body that will just borrow the (owned) self type, + /// and dispatch to the `FnMut::call_mut` instance for the closure. ClosureOnceShim { call_once: DefId, track_caller: bool }, + /// `<[FnMut/Fn coroutine-closure] as FnOnce>::call_once` or + /// `<[Fn coroutine-closure] as FnMut>::call_mut`. + /// + /// The body generated here differs significantly from the `ClosureOnceShim`, + /// since we need to generate a distinct coroutine type that will move the + /// closure's upvars *out* of the closure. + ConstructCoroutineInClosureShim { + coroutine_closure_def_id: DefId, + target_kind: ty::ClosureKind, + }, + + /// `<[coroutine] as Future>::poll`, but for coroutines produced when `AsyncFnOnce` + /// is called on a coroutine-closure whose closure kind greater than `FnOnce`, or + /// similarly for `AsyncFnMut`. + /// + /// This will select the body that is produced by the `ByMoveBody` transform, and thus + /// take and use all of its upvars by-move rather than by-ref. + CoroutineKindShim { coroutine_def_id: DefId, target_kind: ty::ClosureKind }, + /// Compiler-generated accessor for thread locals which returns a reference to the thread local /// the `DefId` defines. This is used to export thread locals from dylibs on platforms lacking /// native support. @@ -168,6 +190,11 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::Intrinsic(def_id) | InstanceDef::ThreadLocalShim(def_id) | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ } + | ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id: def_id, + target_kind: _, + } + | ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id, target_kind: _ } | InstanceDef::DropGlue(def_id, _) | InstanceDef::CloneShim(def_id, _) | InstanceDef::FnPtrAddrShim(def_id, _) => def_id, @@ -187,6 +214,8 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => None, @@ -282,6 +311,8 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::DropGlue(_, Some(_)) => false, InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::Item(_) | InstanceDef::Intrinsic(..) @@ -319,6 +350,8 @@ fn fmt_instance( InstanceDef::Virtual(_, num) => write!(f, " - virtual#{num}"), InstanceDef::FnPtrShim(_, ty) => write!(f, " - shim({ty})"), InstanceDef::ClosureOnceShim { .. } => write!(f, " - shim"), + InstanceDef::ConstructCoroutineInClosureShim { .. } => write!(f, " - shim"), + InstanceDef::CoroutineKindShim { .. } => write!(f, " - shim"), InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"), @@ -610,7 +643,24 @@ impl<'tcx> Instance<'tcx> { }; if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) { - Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args }) + let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() + else { + bug!() + }; + + // If the closure's kind ty disagrees with the identity closure's kind ty, + // then this must be a coroutine generated by one of the `ConstructCoroutineInClosureShim`s. + if args.as_coroutine().kind_ty() == id_args.as_coroutine().kind_ty() { + Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args }) + } else { + Some(Instance { + def: ty::InstanceDef::CoroutineKindShim { + coroutine_def_id, + target_kind: args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(), + }, + args, + }) + } } else { // All other methods should be defaulted methods of the built-in trait. // This is important for `Iterator`'s combinators, but also useful for @@ -715,7 +765,14 @@ fn polymorphize<'tcx>( let def_id = instance.def_id(); let upvars_ty = match tcx.type_of(def_id).skip_binder().kind() { ty::Closure(..) => Some(args.as_closure().tupled_upvars_ty()), - ty::Coroutine(..) => Some(args.as_coroutine().tupled_upvars_ty()), + ty::Coroutine(..) => { + assert_eq!( + args.as_coroutine().kind_ty(), + tcx.types.unit, + "polymorphization does not support coroutines from async closures" + ); + Some(args.as_coroutine().tupled_upvars_ty()) + } _ => None, }; let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty()); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index f07a4ac29e961..8d8d06b7c0b7f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -906,6 +906,12 @@ where i, ), + ty::CoroutineClosure(_, args) => field_ty_or_layout( + TyAndLayout { ty: args.as_coroutine_closure().tupled_upvars_ty(), ..this }, + cx, + i, + ), + ty::Coroutine(def_id, args) => match this.variants { Variants::Single { index } => TyMaybeWithLayout::Ty( args.as_coroutine() @@ -1247,7 +1253,6 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: SpecAbi) -> PtxKernel | Msp430Interrupt | X86Interrupt - | AmdGpuKernel | EfiApi | AvrInterrupt | AvrNonBlockingInterrupt diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dabd50a32b95c..c9137f374a238 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -80,23 +80,35 @@ pub use self::closure::{ CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL, }; -pub use self::consts::{Const, ConstData, ConstInt, Expr, ScalarInt, UnevaluatedConst, ValTree}; +pub use self::consts::{ + Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree, +}; pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, }; pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; pub use self::parameterized::ParameterizedOverTcx; +pub use self::predicate::{ + Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialProjection, + ExistentialTraitRef, NormalizesTo, OutlivesPredicate, PolyCoercePredicate, + PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, + PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, + PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, + RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitPredicate, + TraitRef, TypeOutlivesPredicate, +}; +pub use self::region::{ + BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region, + RegionKind, RegionVid, +}; pub use self::rvalue_scopes::RvalueScopes; -pub use self::sty::BoundRegionKind::*; pub use self::sty::{ - AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, - BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind, - CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate, - ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs, - InlineConstArgsParts, LateParamRegion, ParamConst, ParamTy, PolyExistentialPredicate, - PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyTraitRef, PredicateKind, - Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo, + AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, + ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, + CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs, + InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, + VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -139,6 +151,8 @@ mod instance; mod list; mod opaque_types; mod parameterized; +mod predicate; +mod region; mod rvalue_scopes; mod structural_impls; #[allow(hidden_glob_reexports)] @@ -491,165 +505,6 @@ impl EarlyParamRegion { } } -/// A statement that can be proven by a trait solver. This includes things that may -/// show up in where clauses, such as trait predicates and projection predicates, -/// and also things that are emitted as part of type checking such as `ObjectSafe` -/// predicate which is emitted when a type is coerced to a trait object. -/// -/// Use this rather than `PredicateKind`, whenever possible. -#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] -#[rustc_pass_by_value] -pub struct Predicate<'tcx>( - Interned<'tcx, WithCachedTypeInfo>>>, -); - -impl<'tcx> Predicate<'tcx> { - /// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`. - #[inline] - pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> { - self.0.internee - } - - #[inline(always)] - pub fn flags(self) -> TypeFlags { - self.0.flags - } - - #[inline(always)] - pub fn outer_exclusive_binder(self) -> DebruijnIndex { - self.0.outer_exclusive_binder - } - - /// Flips the polarity of a Predicate. - /// - /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. - pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option> { - let kind = self - .kind() - .map_bound(|kind| match kind { - PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity, - })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { - trait_ref, - polarity: polarity.flip()?, - }))), - - _ => None, - }) - .transpose()?; - - Some(tcx.mk_predicate(kind)) - } - - #[instrument(level = "debug", skip(tcx), ret)] - pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { - match self.kind().skip_binder() { - ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { - tcx.trait_is_coinductive(data.def_id()) - } - ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true, - _ => false, - } - } - - /// Whether this projection can be soundly normalized. - /// - /// Wf predicates must not be normalized, as normalization - /// can remove required bounds which would cause us to - /// unsoundly accept some programs. See #91068. - #[inline] - pub fn allow_normalization(self) -> bool { - match self.kind().skip_binder() { - PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, - // `NormalizesTo` is only used in the new solver, so this shouldn't - // matter. Normalizing `term` would be 'wrong' however, as it changes whether - // `normalizes-to(::Assoc, ::Assoc)` holds. - PredicateKind::NormalizesTo(..) => false, - PredicateKind::Clause(ClauseKind::Trait(_)) - | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) - | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) - | PredicateKind::Clause(ClauseKind::Projection(_)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::AliasRelate(..) - | PredicateKind::ObjectSafe(_) - | PredicateKind::Subtype(_) - | PredicateKind::Coerce(_) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) - | PredicateKind::ConstEquate(_, _) - | PredicateKind::Ambiguous => true, - } - } -} - -impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { - rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) - } -} - -impl rustc_errors::IntoDiagnosticArg for Clause<'_> { - fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { - rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) - } -} - -/// A subset of predicates which can be assumed by the trait solver. They show up in -/// an item's where clauses, hence the name `Clause`, and may either be user-written -/// (such as traits) or may be inserted during lowering. -#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] -#[rustc_pass_by_value] -pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo>>>); - -impl<'tcx> Clause<'tcx> { - pub fn as_predicate(self) -> Predicate<'tcx> { - Predicate(self.0) - } - - pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> { - self.0.internee.map_bound(|kind| match kind { - PredicateKind::Clause(clause) => clause, - _ => unreachable!(), - }) - } - - pub fn as_trait_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() { - Some(clause.rebind(trait_clause)) - } else { - None - } - } - - pub fn as_projection_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() { - Some(clause.rebind(projection_clause)) - } else { - None - } - } - - pub fn as_type_outlives_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() { - Some(clause.rebind(o)) - } else { - None - } - } - - pub fn as_region_outlives_clause(self) -> Option>> { - let clause = self.kind(); - if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() { - Some(clause.rebind(o)) - } else { - None - } - } -} - /// The crate outlives map is computed during typeck and contains the /// outlives of every item in the local crate. You should not use it /// directly, because to do so will make your pass dependent on the @@ -664,189 +519,6 @@ pub struct CratePredicatesMap<'tcx> { pub predicates: DefIdMap<&'tcx [(Clause<'tcx>, Span)]>, } -impl<'tcx> Clause<'tcx> { - /// Performs a substitution suitable for going from a - /// poly-trait-ref to supertraits that must hold if that - /// poly-trait-ref holds. This is slightly different from a normal - /// substitution in terms of what happens with bound regions. See - /// lengthy comment below for details. - pub fn subst_supertrait( - self, - tcx: TyCtxt<'tcx>, - trait_ref: &ty::PolyTraitRef<'tcx>, - ) -> Clause<'tcx> { - // The interaction between HRTB and supertraits is not entirely - // obvious. Let me walk you (and myself) through an example. - // - // Let's start with an easy case. Consider two traits: - // - // trait Foo<'a>: Bar<'a,'a> { } - // trait Bar<'b,'c> { } - // - // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then - // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we - // knew that `Foo<'x>` (for any 'x) then we also know that - // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from - // normal substitution. - // - // In terms of why this is sound, the idea is that whenever there - // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` - // holds. So if there is an impl of `T:Foo<'a>` that applies to - // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all - // `'a`. - // - // Another example to be careful of is this: - // - // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } - // trait Bar1<'b,'c> { } - // - // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? - // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The - // reason is similar to the previous example: any impl of - // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So - // basically we would want to collapse the bound lifetimes from - // the input (`trait_ref`) and the supertraits. - // - // To achieve this in practice is fairly straightforward. Let's - // consider the more complicated scenario: - // - // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` - // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, - // where both `'x` and `'b` would have a DB index of 1. - // The substitution from the input trait-ref is therefore going to be - // `'a => 'x` (where `'x` has a DB index of 1). - // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an - // early-bound parameter and `'b` is a late-bound parameter with a - // DB index of 1. - // - If we replace `'a` with `'x` from the input, it too will have - // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` - // just as we wanted. - // - // There is only one catch. If we just apply the substitution `'a - // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will - // adjust the DB index because we substituting into a binder (it - // tries to be so smart...) resulting in `for<'x> for<'b> - // Bar1<'x,'b>` (we have no syntax for this, so use your - // imagination). Basically the 'x will have DB index of 2 and 'b - // will have DB index of 1. Not quite what we want. So we apply - // the substitution to the *contents* of the trait reference, - // rather than the trait reference itself (put another way, the - // substitution code expects equal binding levels in the values - // from the substitution and the value being substituted into, and - // this trick achieves that). - - // Working through the second example: - // trait_ref: for<'x> T: Foo1<'^0.0>; args: [T, '^0.0] - // predicate: for<'b> Self: Bar1<'a, '^0.0>; args: [Self, 'a, '^0.0] - // We want to end up with: - // for<'x, 'b> T: Bar1<'^0.0, '^0.1> - // To do this: - // 1) We must shift all bound vars in predicate by the length - // of trait ref's bound vars. So, we would end up with predicate like - // Self: Bar1<'a, '^0.1> - // 2) We can then apply the trait args to this, ending up with - // T: Bar1<'^0.0, '^0.1> - // 3) Finally, to create the final bound vars, we concatenate the bound - // vars of the trait ref with those of the predicate: - // ['x, 'b] - let bound_pred = self.kind(); - let pred_bound_vars = bound_pred.bound_vars(); - let trait_bound_vars = trait_ref.bound_vars(); - // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> - let shifted_pred = - tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); - // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> - let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args); - // 3) ['x] + ['b] -> ['x, 'b] - let bound_vars = - tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); - - // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? - tcx.reuse_or_mk_predicate( - self.as_predicate(), - ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars), - ) - .expect_clause() - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct TraitPredicate<'tcx> { - pub trait_ref: TraitRef<'tcx>, - - /// If polarity is Positive: we are proving that the trait is implemented. - /// - /// If polarity is Negative: we are proving that a negative impl of this trait - /// exists. (Note that coherence also checks whether negative impls of supertraits - /// exist via a series of predicates.) - /// - /// If polarity is Reserved: that's a bug. - pub polarity: ImplPolarity, -} - -pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; - -impl<'tcx> TraitPredicate<'tcx> { - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } - } - - pub fn def_id(self) -> DefId { - self.trait_ref.def_id - } - - pub fn self_ty(self) -> Ty<'tcx> { - self.trait_ref.self_ty() - } -} - -impl<'tcx> PolyTraitPredicate<'tcx> { - pub fn def_id(self) -> DefId { - // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().def_id() - } - - pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { - self.map_bound(|trait_ref| trait_ref.self_ty()) - } - - #[inline] - pub fn polarity(self) -> ImplPolarity { - self.skip_binder().polarity - } -} - -/// `A: B` -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct OutlivesPredicate(pub A, pub B); -pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; -pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; -pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; - -/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates -/// whether the `a` type is the type that we should label as "expected" when -/// presenting user diagnostics. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct SubtypePredicate<'tcx> { - pub a_is_expected: bool, - pub a: Ty<'tcx>, - pub b: Ty<'tcx>, -} -pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; - -/// Encodes that we have to coerce *from* the `a` type to the `b` type. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct CoercePredicate<'tcx> { - pub a: Ty<'tcx>, - pub b: Ty<'tcx>, -} -pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Term<'tcx> { ptr: NonNull<()>, @@ -1048,351 +720,6 @@ impl From for TermVid { } } -/// This kind of predicate has no *direct* correspondent in the -/// syntax, but it roughly corresponds to the syntactic forms: -/// -/// 1. `T: TraitRef<..., Item = Type>` -/// 2. `>::Item == Type` (NYI) -/// -/// In particular, form #1 is "desugared" to the combination of a -/// normal trait predicate (`T: TraitRef<...>`) and one of these -/// predicates. Form #2 is a broader form in that it also permits -/// equality between arbitrary types. Processing an instance of -/// Form #2 eventually yields one of these `ProjectionPredicate` -/// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ProjectionPredicate<'tcx> { - pub projection_ty: AliasTy<'tcx>, - pub term: Term<'tcx>, -} - -impl<'tcx> ProjectionPredicate<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.projection_ty.self_ty() - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { - Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - self.projection_ty.trait_def_id(tcx) - } - - pub fn def_id(self) -> DefId { - self.projection_ty.def_id - } -} - -pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; - -impl<'tcx> PolyProjectionPredicate<'tcx> { - /// Returns the `DefId` of the trait of the associated item being projected. - #[inline] - pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - self.skip_binder().projection_ty.trait_def_id(tcx) - } - - /// Get the [PolyTraitRef] required for this projection to be well formed. - /// Note that for generic associated types the predicates of the associated - /// type also need to be checked. - #[inline] - pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { - // Note: unlike with `TraitRef::to_poly_trait_ref()`, - // `self.0.trait_ref` is permitted to have escaping regions. - // This is because here `self` has a `Binder` and so does our - // return value, so we are preserving the number of binding - // levels. - self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) - } - - pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { - self.map_bound(|predicate| predicate.term) - } - - /// The `DefId` of the `TraitItem` for the associated type. - /// - /// Note that this is not the `DefId` of the `TraitRef` containing this - /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. - pub fn projection_def_id(&self) -> DefId { - // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().projection_ty.def_id - } -} - -/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be -/// proven by actually normalizing `alias`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct NormalizesTo<'tcx> { - pub alias: AliasTy<'tcx>, - pub term: Term<'tcx>, -} - -impl<'tcx> NormalizesTo<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.alias.self_ty() - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> { - Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - self.alias.trait_def_id(tcx) - } - - pub fn def_id(self) -> DefId { - self.alias.def_id - } -} - -pub trait ToPolyTraitRef<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; -} - -impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { - fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { - self.map_bound_ref(|trait_pred| trait_pred.trait_ref) - } -} - -pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; -} - -impl<'tcx, T> ToPredicate<'tcx, T> for T { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { - self - } -} - -impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self) - } -} - -impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause)) - } -} - -impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { - #[inline(always)] - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.as_predicate() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(self).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { - TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive } - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); - pred.to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); - pred.to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { - #[inline(always)] - fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| TraitPredicate { - trait_ref, - polarity: ty::ImplPolarity::Positive, - }) - } -} - -impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate, ty::Region<'tcx>> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(self))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx) - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - let p: Predicate<'tcx> = self.to_predicate(tcx); - p.expect_clause() - } -} - -impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - PredicateKind::NormalizesTo(self).to_predicate(tcx) - } -} - -impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_pred(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(ClauseKind::Projection(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::NormalizesTo(..) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::ObjectSafe(..) - | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, - } - } - - pub fn to_opt_poly_projection_pred(self) -> Option> { - let predicate = self.kind(); - match predicate.skip_binder() { - PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), - PredicateKind::Clause(ClauseKind::Trait(..)) - | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) - | PredicateKind::NormalizesTo(..) - | PredicateKind::AliasRelate(..) - | PredicateKind::Subtype(..) - | PredicateKind::Coerce(..) - | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) - | PredicateKind::Clause(ClauseKind::WellFormed(..)) - | PredicateKind::ObjectSafe(..) - | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) - | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) - | PredicateKind::ConstEquate(..) - | PredicateKind::Ambiguous => None, - } - } - - /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`. - pub fn as_clause(self) -> Option> { - match self.kind().skip_binder() { - PredicateKind::Clause(..) => Some(self.expect_clause()), - _ => None, - } - } - - /// Assert that the predicate is a clause. - pub fn expect_clause(self) -> Clause<'tcx> { - match self.kind().skip_binder() { - PredicateKind::Clause(..) => Clause(self.0), - _ => bug!("{self} is not a clause"), - } - } -} - /// Represents the bounds declared on a particular set of type /// parameters. Should eventually be generalized into a flag list of /// where-clauses. You can obtain an `InstantiatedPredicates` list from a @@ -2353,6 +1680,8 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::Virtual(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) | ty::InstanceDef::ThreadLocalShim(..) diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs new file mode 100644 index 0000000000000..7c5b49512ae50 --- /dev/null +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -0,0 +1,1062 @@ +use rustc_data_structures::captures::Captures; +use rustc_data_structures::intern::Interned; +use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; +use rustc_hir::def_id::DefId; +use rustc_hir::LangItem; +use rustc_span::Span; +use rustc_type_ir::ClauseKind as IrClauseKind; +use rustc_type_ir::PredicateKind as IrPredicateKind; +use std::cmp::Ordering; + +use crate::ty::visit::TypeVisitableExt; +use crate::ty::{ + self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArg, GenericArgs, + GenericArgsRef, ImplPolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo, +}; + +pub type ClauseKind<'tcx> = IrClauseKind>; +pub type PredicateKind<'tcx> = IrPredicateKind>; + +/// A statement that can be proven by a trait solver. This includes things that may +/// show up in where clauses, such as trait predicates and projection predicates, +/// and also things that are emitted as part of type checking such as `ObjectSafe` +/// predicate which is emitted when a type is coerced to a trait object. +/// +/// Use this rather than `PredicateKind`, whenever possible. +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Predicate<'tcx>( + pub(super) Interned<'tcx, WithCachedTypeInfo>>>, +); + +impl<'tcx> Predicate<'tcx> { + /// Gets the inner `ty::Binder<'tcx, PredicateKind<'tcx>>`. + #[inline] + pub fn kind(self) -> ty::Binder<'tcx, PredicateKind<'tcx>> { + self.0.internee + } + + #[inline(always)] + pub fn flags(self) -> TypeFlags { + self.0.flags + } + + #[inline(always)] + pub fn outer_exclusive_binder(self) -> DebruijnIndex { + self.0.outer_exclusive_binder + } + + /// Flips the polarity of a Predicate. + /// + /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. + pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option> { + let kind = self + .kind() + .map_bound(|kind| match kind { + PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity, + })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { + trait_ref, + polarity: polarity.flip()?, + }))), + + _ => None, + }) + .transpose()?; + + Some(tcx.mk_predicate(kind)) + } + + #[instrument(level = "debug", skip(tcx), ret)] + pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { + match self.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { + tcx.trait_is_coinductive(data.def_id()) + } + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true, + _ => false, + } + } + + /// Whether this projection can be soundly normalized. + /// + /// Wf predicates must not be normalized, as normalization + /// can remove required bounds which would cause us to + /// unsoundly accept some programs. See #91068. + #[inline] + pub fn allow_normalization(self) -> bool { + match self.kind().skip_binder() { + PredicateKind::Clause(ClauseKind::WellFormed(_)) => false, + // `NormalizesTo` is only used in the new solver, so this shouldn't + // matter. Normalizing `term` would be 'wrong' however, as it changes whether + // `normalizes-to(::Assoc, ::Assoc)` holds. + PredicateKind::NormalizesTo(..) => false, + PredicateKind::Clause(ClauseKind::Trait(_)) + | PredicateKind::Clause(ClauseKind::RegionOutlives(_)) + | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) + | PredicateKind::Clause(ClauseKind::Projection(_)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::AliasRelate(..) + | PredicateKind::ObjectSafe(_) + | PredicateKind::Subtype(_) + | PredicateKind::Coerce(_) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_)) + | PredicateKind::ConstEquate(_, _) + | PredicateKind::Ambiguous => true, + } + } +} + +impl rustc_errors::IntoDiagnosticArg for Predicate<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + +impl rustc_errors::IntoDiagnosticArg for Clause<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue { + rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string())) + } +} + +/// A subset of predicates which can be assumed by the trait solver. They show up in +/// an item's where clauses, hence the name `Clause`, and may either be user-written +/// (such as traits) or may be inserted during lowering. +#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Clause<'tcx>( + pub(super) Interned<'tcx, WithCachedTypeInfo>>>, +); + +impl<'tcx> Clause<'tcx> { + pub fn as_predicate(self) -> Predicate<'tcx> { + Predicate(self.0) + } + + pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> { + self.0.internee.map_bound(|kind| match kind { + PredicateKind::Clause(clause) => clause, + _ => unreachable!(), + }) + } + + pub fn as_trait_clause(self) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() { + Some(clause.rebind(trait_clause)) + } else { + None + } + } + + pub fn as_projection_clause(self) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() { + Some(clause.rebind(projection_clause)) + } else { + None + } + } + + pub fn as_type_outlives_clause(self) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } + + pub fn as_region_outlives_clause( + self, + ) -> Option>> { + let clause = self.kind(); + if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() { + Some(clause.rebind(o)) + } else { + None + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub enum ExistentialPredicate<'tcx> { + /// E.g., `Iterator`. + Trait(ExistentialTraitRef<'tcx>), + /// E.g., `Iterator::Item = T`. + Projection(ExistentialProjection<'tcx>), + /// E.g., `Send`. + AutoTrait(DefId), +} + +impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { + fn fmt>>( + this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + std::fmt::Debug::fmt(&this.data, f) + } +} + +impl<'tcx> ExistentialPredicate<'tcx> { + /// Compares via an ordering that will not change if modules are reordered or other changes are + /// made to the tree. In particular, this ordering is preserved across incremental compilations. + pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering { + use self::ExistentialPredicate::*; + match (*self, *other) { + (Trait(_), Trait(_)) => Ordering::Equal, + (Projection(ref a), Projection(ref b)) => { + tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id)) + } + (AutoTrait(ref a), AutoTrait(ref b)) => { + tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) + } + (Trait(_), _) => Ordering::Less, + (Projection(_), Trait(_)) => Ordering::Greater, + (Projection(_), _) => Ordering::Less, + (AutoTrait(_), _) => Ordering::Greater, + } + } +} + +pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>; + +impl<'tcx> PolyExistentialPredicate<'tcx> { + /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), + /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` + /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { + match self.skip_binder() { + ExistentialPredicate::Trait(tr) => { + self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) + } + ExistentialPredicate::Projection(p) => { + self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) + } + ExistentialPredicate::AutoTrait(did) => { + let generics = tcx.generics_of(did); + let trait_ref = if generics.params.len() == 1 { + ty::TraitRef::new(tcx, did, [self_ty]) + } else { + // If this is an ill-formed auto trait, then synthesize + // new error args for the missing generics. + let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); + ty::TraitRef::new(tcx, did, err_args) + }; + self.rebind(trait_ref).to_predicate(tcx) + } + } + } +} + +impl<'tcx> ty::List> { + /// Returns the "principal `DefId`" of this set of existential predicates. + /// + /// A Rust trait object type consists (in addition to a lifetime bound) + /// of a set of trait bounds, which are separated into any number + /// of auto-trait bounds, and at most one non-auto-trait bound. The + /// non-auto-trait bound is called the "principal" of the trait + /// object. + /// + /// Only the principal can have methods or type parameters (because + /// auto traits can have neither of them). This is important, because + /// it means the auto traits can be treated as an unordered set (methods + /// would force an order for the vtable, while relating traits with + /// type parameters without knowing the order to relate them in is + /// a rather non-trivial task). + /// + /// For example, in the trait object `dyn std::fmt::Debug + Sync`, the + /// principal bound is `Some(std::fmt::Debug)`, while the auto-trait bounds + /// are the set `{Sync}`. + /// + /// It is also possible to have a "trivial" trait object that + /// consists only of auto traits, with no principal - for example, + /// `dyn Send + Sync`. In that case, the set of auto-trait bounds + /// is `{Send, Sync}`, while there is no principal. These trait objects + /// have a "trivial" vtable consisting of just the size, alignment, + /// and destructor. + pub fn principal(&self) -> Option>> { + self[0] + .map_bound(|this| match this { + ExistentialPredicate::Trait(tr) => Some(tr), + _ => None, + }) + .transpose() + } + + pub fn principal_def_id(&self) -> Option { + self.principal().map(|trait_ref| trait_ref.skip_binder().def_id) + } + + #[inline] + pub fn projection_bounds<'a>( + &'a self, + ) -> impl Iterator>> + 'a { + self.iter().filter_map(|predicate| { + predicate + .map_bound(|pred| match pred { + ExistentialPredicate::Projection(projection) => Some(projection), + _ => None, + }) + .transpose() + }) + } + + #[inline] + pub fn auto_traits<'a>(&'a self) -> impl Iterator + Captures<'tcx> + 'a { + self.iter().filter_map(|predicate| match predicate.skip_binder() { + ExistentialPredicate::AutoTrait(did) => Some(did), + _ => None, + }) + } +} + +/// A complete reference to a trait. These take numerous guises in syntax, +/// but perhaps the most recognizable form is in a where-clause: +/// ```ignore (illustrative) +/// T: Foo +/// ``` +/// This would be represented by a trait-reference where the `DefId` is the +/// `DefId` for the trait `Foo` and the args define `T` as parameter 0, +/// and `U` as parameter 1. +/// +/// Trait references also appear in object types like `Foo`, but in +/// that case the `Self` parameter is absent from the substitutions. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct TraitRef<'tcx> { + pub def_id: DefId, + pub args: GenericArgsRef<'tcx>, + /// This field exists to prevent the creation of `TraitRef` without + /// calling [`TraitRef::new`]. + pub(super) _use_trait_ref_new_instead: (), +} + +impl<'tcx> TraitRef<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + trait_def_id: DefId, + args: impl IntoIterator>>, + ) -> Self { + let args = tcx.check_and_mk_args(trait_def_id, args); + Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () } + } + + pub fn from_lang_item( + tcx: TyCtxt<'tcx>, + trait_lang_item: LangItem, + span: Span, + args: impl IntoIterator>>, + ) -> Self { + let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span)); + Self::new(tcx, trait_def_id, args) + } + + pub fn from_method( + tcx: TyCtxt<'tcx>, + trait_id: DefId, + args: GenericArgsRef<'tcx>, + ) -> ty::TraitRef<'tcx> { + let defs = tcx.generics_of(trait_id); + ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.params.len()])) + } + + /// Returns a `TraitRef` of the form `P0: Foo` where `Pi` + /// are the parameters defined on trait. + pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> { + ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id)) + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + ty::TraitRef::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), + ) + } + + #[inline] + pub fn self_ty(&self) -> Ty<'tcx> { + self.args.type_at(0) + } +} + +pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>; + +impl<'tcx> PolyTraitRef<'tcx> { + pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> { + self.map_bound_ref(|tr| tr.self_ty()) + } + + pub fn def_id(&self) -> DefId { + self.skip_binder().def_id + } +} + +impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { + self.to_string().into_diagnostic_arg() + } +} + +/// An existential reference to a trait, where `Self` is erased. +/// For example, the trait object `Trait<'a, 'b, X, Y>` is: +/// ```ignore (illustrative) +/// exists T. T: Trait<'a, 'b, X, Y> +/// ``` +/// The substitutions don't include the erased `Self`, only trait +/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct ExistentialTraitRef<'tcx> { + pub def_id: DefId, + pub args: GenericArgsRef<'tcx>, +} + +impl<'tcx> ExistentialTraitRef<'tcx> { + pub fn erase_self_ty( + tcx: TyCtxt<'tcx>, + trait_ref: ty::TraitRef<'tcx>, + ) -> ty::ExistentialTraitRef<'tcx> { + // Assert there is a Self. + trait_ref.args.type_at(0); + + ty::ExistentialTraitRef { + def_id: trait_ref.def_id, + args: tcx.mk_args(&trait_ref.args[1..]), + } + } + + /// Object types don't have a self type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self type. A common choice is `mk_err()` + /// or some placeholder type. + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { + // otherwise the escaping vars would be captured by the binder + // debug_assert!(!self_ty.has_escaping_bound_vars()); + + ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) + } +} + +impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> { + fn into_diagnostic_arg(self) -> DiagnosticArgValue { + self.to_string().into_diagnostic_arg() + } +} + +pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>; + +impl<'tcx> PolyExistentialTraitRef<'tcx> { + pub fn def_id(&self) -> DefId { + self.skip_binder().def_id + } + + /// Object types don't have a self type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self type. A common choice is `mk_err()` + /// or some placeholder type. + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> { + self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty)) + } +} + +/// A `ProjectionPredicate` for an `ExistentialTraitRef`. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct ExistentialProjection<'tcx> { + pub def_id: DefId, + pub args: GenericArgsRef<'tcx>, + pub term: Term<'tcx>, +} + +pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>; + +impl<'tcx> ExistentialProjection<'tcx> { + /// Extracts the underlying existential trait reference from this projection. + /// For example, if this is a projection of `exists T. ::Item == X`, + /// then this function would return an `exists T. T: Iterator` existential trait + /// reference. + pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { + let def_id = tcx.parent(self.def_id); + let subst_count = tcx.generics_of(def_id).count() - 1; + let args = tcx.mk_args(&self.args[..subst_count]); + ty::ExistentialTraitRef { def_id, args } + } + + pub fn with_self_ty( + &self, + tcx: TyCtxt<'tcx>, + self_ty: Ty<'tcx>, + ) -> ty::ProjectionPredicate<'tcx> { + // otherwise the escaping regions would be captured by the binders + debug_assert!(!self_ty.has_escaping_bound_vars()); + + ty::ProjectionPredicate { + projection_ty: AliasTy::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args), + ), + term: self.term, + } + } + + pub fn erase_self_ty( + tcx: TyCtxt<'tcx>, + projection_predicate: ty::ProjectionPredicate<'tcx>, + ) -> Self { + // Assert there is a Self. + projection_predicate.projection_ty.args.type_at(0); + + Self { + def_id: projection_predicate.projection_ty.def_id, + args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]), + term: projection_predicate.term, + } + } +} + +impl<'tcx> PolyExistentialProjection<'tcx> { + pub fn with_self_ty( + &self, + tcx: TyCtxt<'tcx>, + self_ty: Ty<'tcx>, + ) -> ty::PolyProjectionPredicate<'tcx> { + self.map_bound(|p| p.with_self_ty(tcx, self_ty)) + } + + pub fn item_def_id(&self) -> DefId { + self.skip_binder().def_id + } +} + +impl<'tcx> Clause<'tcx> { + /// Performs a substitution suitable for going from a + /// poly-trait-ref to supertraits that must hold if that + /// poly-trait-ref holds. This is slightly different from a normal + /// substitution in terms of what happens with bound regions. See + /// lengthy comment below for details. + pub fn subst_supertrait( + self, + tcx: TyCtxt<'tcx>, + trait_ref: &ty::PolyTraitRef<'tcx>, + ) -> Clause<'tcx> { + // The interaction between HRTB and supertraits is not entirely + // obvious. Let me walk you (and myself) through an example. + // + // Let's start with an easy case. Consider two traits: + // + // trait Foo<'a>: Bar<'a,'a> { } + // trait Bar<'b,'c> { } + // + // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then + // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we + // knew that `Foo<'x>` (for any 'x) then we also know that + // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from + // normal substitution. + // + // In terms of why this is sound, the idea is that whenever there + // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` + // holds. So if there is an impl of `T:Foo<'a>` that applies to + // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all + // `'a`. + // + // Another example to be careful of is this: + // + // trait Foo1<'a>: for<'b> Bar1<'a,'b> { } + // trait Bar1<'b,'c> { } + // + // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know? + // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The + // reason is similar to the previous example: any impl of + // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So + // basically we would want to collapse the bound lifetimes from + // the input (`trait_ref`) and the supertraits. + // + // To achieve this in practice is fairly straightforward. Let's + // consider the more complicated scenario: + // + // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x` + // has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`, + // where both `'x` and `'b` would have a DB index of 1. + // The substitution from the input trait-ref is therefore going to be + // `'a => 'x` (where `'x` has a DB index of 1). + // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an + // early-bound parameter and `'b` is a late-bound parameter with a + // DB index of 1. + // - If we replace `'a` with `'x` from the input, it too will have + // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` + // just as we wanted. + // + // There is only one catch. If we just apply the substitution `'a + // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will + // adjust the DB index because we substituting into a binder (it + // tries to be so smart...) resulting in `for<'x> for<'b> + // Bar1<'x,'b>` (we have no syntax for this, so use your + // imagination). Basically the 'x will have DB index of 2 and 'b + // will have DB index of 1. Not quite what we want. So we apply + // the substitution to the *contents* of the trait reference, + // rather than the trait reference itself (put another way, the + // substitution code expects equal binding levels in the values + // from the substitution and the value being substituted into, and + // this trick achieves that). + + // Working through the second example: + // trait_ref: for<'x> T: Foo1<'^0.0>; args: [T, '^0.0] + // predicate: for<'b> Self: Bar1<'a, '^0.0>; args: [Self, 'a, '^0.0] + // We want to end up with: + // for<'x, 'b> T: Bar1<'^0.0, '^0.1> + // To do this: + // 1) We must shift all bound vars in predicate by the length + // of trait ref's bound vars. So, we would end up with predicate like + // Self: Bar1<'a, '^0.1> + // 2) We can then apply the trait args to this, ending up with + // T: Bar1<'^0.0, '^0.1> + // 3) Finally, to create the final bound vars, we concatenate the bound + // vars of the trait ref with those of the predicate: + // ['x, 'b] + let bound_pred = self.kind(); + let pred_bound_vars = bound_pred.bound_vars(); + let trait_bound_vars = trait_ref.bound_vars(); + // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1> + let shifted_pred = + tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); + // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> + let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args); + // 3) ['x] + ['b] -> ['x, 'b] + let bound_vars = + tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars)); + + // FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here? + tcx.reuse_or_mk_predicate( + self.as_predicate(), + ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars), + ) + .expect_clause() + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct TraitPredicate<'tcx> { + pub trait_ref: TraitRef<'tcx>, + + /// If polarity is Positive: we are proving that the trait is implemented. + /// + /// If polarity is Negative: we are proving that a negative impl of this trait + /// exists. (Note that coherence also checks whether negative impls of supertraits + /// exist via a series of predicates.) + /// + /// If polarity is Reserved: that's a bug. + pub polarity: ImplPolarity, +} + +pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; + +impl<'tcx> TraitPredicate<'tcx> { + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self } + } + + pub fn def_id(self) -> DefId { + self.trait_ref.def_id + } + + pub fn self_ty(self) -> Ty<'tcx> { + self.trait_ref.self_ty() + } +} + +impl<'tcx> PolyTraitPredicate<'tcx> { + pub fn def_id(self) -> DefId { + // Ok to skip binder since trait `DefId` does not care about regions. + self.skip_binder().def_id() + } + + pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { + self.map_bound(|trait_ref| trait_ref.self_ty()) + } + + #[inline] + pub fn polarity(self) -> ImplPolarity { + self.skip_binder().polarity + } +} + +/// `A: B` +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct OutlivesPredicate(pub A, pub B); +pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; +pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate, ty::Region<'tcx>>; +pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>; +pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>; + +/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates +/// whether the `a` type is the type that we should label as "expected" when +/// presenting user diagnostics. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct SubtypePredicate<'tcx> { + pub a_is_expected: bool, + pub a: Ty<'tcx>, + pub b: Ty<'tcx>, +} +pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>; + +/// Encodes that we have to coerce *from* the `a` type to the `b` type. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct CoercePredicate<'tcx> { + pub a: Ty<'tcx>, + pub b: Ty<'tcx>, +} +pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>; + +/// This kind of predicate has no *direct* correspondent in the +/// syntax, but it roughly corresponds to the syntactic forms: +/// +/// 1. `T: TraitRef<..., Item = Type>` +/// 2. `>::Item == Type` (NYI) +/// +/// In particular, form #1 is "desugared" to the combination of a +/// normal trait predicate (`T: TraitRef<...>`) and one of these +/// predicates. Form #2 is a broader form in that it also permits +/// equality between arbitrary types. Processing an instance of +/// Form #2 eventually yields one of these `ProjectionPredicate` +/// instances to normalize the LHS. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct ProjectionPredicate<'tcx> { + pub projection_ty: AliasTy<'tcx>, + pub term: Term<'tcx>, +} + +impl<'tcx> ProjectionPredicate<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.projection_ty.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { + Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.projection_ty.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.projection_ty.def_id + } +} + +pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; + +impl<'tcx> PolyProjectionPredicate<'tcx> { + /// Returns the `DefId` of the trait of the associated item being projected. + #[inline] + pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { + self.skip_binder().projection_ty.trait_def_id(tcx) + } + + /// Get the [PolyTraitRef] required for this projection to be well formed. + /// Note that for generic associated types the predicates of the associated + /// type also need to be checked. + #[inline] + pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> { + // Note: unlike with `TraitRef::to_poly_trait_ref()`, + // `self.0.trait_ref` is permitted to have escaping regions. + // This is because here `self` has a `Binder` and so does our + // return value, so we are preserving the number of binding + // levels. + self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) + } + + pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { + self.map_bound(|predicate| predicate.term) + } + + /// The `DefId` of the `TraitItem` for the associated type. + /// + /// Note that this is not the `DefId` of the `TraitRef` containing this + /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. + pub fn projection_def_id(&self) -> DefId { + // Ok to skip binder since trait `DefId` does not care about regions. + self.skip_binder().projection_ty.def_id + } +} + +/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be +/// proven by actually normalizing `alias`. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct NormalizesTo<'tcx> { + pub alias: AliasTy<'tcx>, + pub term: Term<'tcx>, +} + +impl<'tcx> NormalizesTo<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.alias.self_ty() + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> { + Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + self.alias.trait_def_id(tcx) + } + + pub fn def_id(self) -> DefId { + self.alias.def_id + } +} + +pub trait ToPolyTraitRef<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; +} + +impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { + fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { + self.map_bound_ref(|trait_pred| trait_pred.trait_ref) + } +} + +pub trait ToPredicate<'tcx, P = Predicate<'tcx>> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P; +} + +impl<'tcx, T> ToPredicate<'tcx, T> for T { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { + self + } +} + +impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(self) + } +} + +impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self))) + } +} + +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause)) + } +} + +impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.as_predicate() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(self).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { + TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive } + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| TraitPredicate { + trait_ref, + polarity: ty::ImplPolarity::Positive, + }) + } +} + +impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate, ty::Region<'tcx>> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(self))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx) + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { + let p: Predicate<'tcx> = self.to_predicate(tcx); + p.expect_clause() + } +} + +impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { + PredicateKind::NormalizesTo(self).to_predicate(tcx) + } +} + +impl<'tcx> Predicate<'tcx> { + pub fn to_opt_poly_trait_pred(self) -> Option> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(ClauseKind::Projection(..)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) + | PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) + | PredicateKind::Clause(ClauseKind::WellFormed(..)) + | PredicateKind::ObjectSafe(..) + | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous => None, + } + } + + pub fn to_opt_poly_projection_pred(self) -> Option> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)), + PredicateKind::Clause(ClauseKind::Trait(..)) + | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::NormalizesTo(..) + | PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::Clause(ClauseKind::RegionOutlives(..)) + | PredicateKind::Clause(ClauseKind::WellFormed(..)) + | PredicateKind::ObjectSafe(..) + | PredicateKind::Clause(ClauseKind::TypeOutlives(..)) + | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..)) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous => None, + } + } + + /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`. + pub fn as_clause(self) -> Option> { + match self.kind().skip_binder() { + PredicateKind::Clause(..) => Some(self.expect_clause()), + _ => None, + } + } + + /// Assert that the predicate is a clause. + pub fn expect_clause(self) -> Clause<'tcx> { + match self.kind().skip_binder() { + PredicateKind::Clause(..) => Clause(self.0), + _ => bug!("{self} is not a clause"), + } + } +} diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index f32b7b0852abc..19f8ba124f143 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -3,6 +3,7 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; +use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; @@ -130,8 +131,24 @@ pub trait Printer<'tcx>: Sized { parent_args = &args[..generics.parent_count.min(args.len())]; match key.disambiguated_data.data { - // Closures' own generics are only captures, don't print them. - DefPathData::Closure => {} + DefPathData::Closure => { + // FIXME(async_closures): This is somewhat ugly. + // We need to additionally print the `kind` field of a closure if + // it is desugared from a coroutine-closure. + if let Some(hir::CoroutineKind::Desugared( + _, + hir::CoroutineSource::Closure, + )) = self.tcx().coroutine_kind(def_id) + && args.len() >= parent_args.len() + 1 + { + return self.path_generic_args( + |cx| cx.print_def_path(def_id, parent_args), + &args[..parent_args.len() + 1][..1], + ); + } else { + // Closures' own generics are only captures, don't print them. + } + } // This covers both `DefKind::AnonConst` and `DefKind::InlineConst`. // Anon consts doesn't have their own generics, and inline consts' own // generics are their inferred types, so don't print them. @@ -259,6 +276,7 @@ fn characteristic_def_id_of_type_cached<'a>( ty::FnDef(def_id, _) | ty::Closure(def_id, _) + | ty::CoroutineClosure(def_id, _) | ty::Coroutine(def_id, _) | ty::CoroutineWitness(def_id, _) | ty::Foreign(def_id) => Some(def_id), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index bac5068a69b86..f90703e61844e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,7 +1,7 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::IntoQueryParam; use crate::query::Providers; -use crate::traits::util::supertraits_for_pretty_printing; +use crate::traits::util::{super_predicates_for_pretty_printing, supertraits_for_pretty_printing}; use crate::ty::GenericArgKind; use crate::ty::{ ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable, @@ -874,6 +874,48 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } p!("}}"); } + ty::CoroutineClosure(did, args) => { + p!(write("{{")); + if !self.should_print_verbose() { + p!(write("coroutine-closure")); + // FIXME(eddyb) should use `def_span`. + if let Some(did) = did.as_local() { + if self.tcx().sess.opts.unstable_opts.span_free_formats { + p!("@", print_def_path(did.to_def_id(), args)); + } else { + let span = self.tcx().def_span(did); + let preference = if with_forced_trimmed_paths() { + FileNameDisplayPreference::Short + } else { + FileNameDisplayPreference::Remapped + }; + p!(write( + "@{}", + // This may end up in stderr diagnostics but it may also be emitted + // into MIR. Hence we use the remapped path if available + self.tcx().sess.source_map().span_to_string(span, preference) + )); + } + } else { + p!(write("@"), print_def_path(did, args)); + } + } else { + p!(print_def_path(did, args)); + p!( + " closure_kind_ty=", + print(args.as_coroutine_closure().kind_ty()), + " signature_parts_ty=", + print(args.as_coroutine_closure().signature_parts_ty()), + " upvar_tys=", + print(args.as_coroutine_closure().tupled_upvars_ty()), + " coroutine_captures_by_ref_ty=", + print(args.as_coroutine_closure().coroutine_captures_by_ref_ty()), + " coroutine_witness_ty=", + print(args.as_coroutine_closure().coroutine_witness_ty()) + ); + } + p!("}}"); + } ty::Array(ty, sz) => p!("[", print(ty), "; ", print(sz), "]"), ty::Slice(ty) => p!("[", print(ty), "]"), } @@ -1213,8 +1255,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // Generate the main trait ref, including associated types. let mut first = true; - if let Some(principal) = predicates.principal() { - self.wrap_binder(&principal, |principal, cx| { + if let Some(bound_principal) = predicates.principal() { + self.wrap_binder(&bound_principal, |principal, cx| { define_scoped_cx!(cx); p!(print_def_path(principal.def_id, &[])); @@ -1239,19 +1281,53 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`, // in order to place the projections inside the `<...>`. if !resugared { - // Use a type that can't appear in defaults of type parameters. - let dummy_cx = Ty::new_fresh(cx.tcx(), 0); - let principal = principal.with_self_ty(cx.tcx(), dummy_cx); + let principal_with_self = + principal.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self); let args = cx .tcx() - .generics_of(principal.def_id) - .own_args_no_defaults(cx.tcx(), principal.args); - - let mut projections: Vec<_> = predicates.projection_bounds().collect(); - projections.sort_by_cached_key(|proj| { - cx.tcx().item_name(proj.item_def_id()).to_string() - }); + .generics_of(principal_with_self.def_id) + .own_args_no_defaults(cx.tcx(), principal_with_self.args); + + let bound_principal_with_self = bound_principal + .with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self); + + let super_projections: Vec<_> = + super_predicates_for_pretty_printing(cx.tcx(), bound_principal_with_self) + .filter_map(|clause| clause.as_projection_clause()) + .collect(); + + let mut projections: Vec<_> = predicates + .projection_bounds() + .filter(|&proj| { + // Filter out projections that are implied by the super predicates. + let proj_is_implied = super_projections.iter().any(|&super_proj| { + let super_proj = super_proj.map_bound(|super_proj| { + ty::ExistentialProjection::erase_self_ty(cx.tcx(), super_proj) + }); + + // This function is sometimes called on types with erased and + // anonymized regions, but the super projections can still + // contain named regions. So we erase and anonymize everything + // here to compare the types modulo regions below. + let proj = cx.tcx().erase_regions(proj); + let proj = cx.tcx().anonymize_bound_vars(proj); + let super_proj = cx.tcx().erase_regions(super_proj); + let super_proj = cx.tcx().anonymize_bound_vars(super_proj); + + proj == super_proj + }); + !proj_is_implied + }) + .map(|proj| { + // Skip the binder, because we don't want to print the binder in + // front of the associated item. + proj.skip_binder() + }) + .collect(); + + projections + .sort_by_cached_key(|proj| cx.tcx().item_name(proj.def_id).to_string()); if !args.is_empty() || !projections.is_empty() { p!(generic_delimiters(|cx| { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs new file mode 100644 index 0000000000000..75be380704e1f --- /dev/null +++ b/compiler/rustc_middle/src/ty/region.rs @@ -0,0 +1,399 @@ +use polonius_engine::Atom; +use rustc_data_structures::intern::Interned; +use rustc_errors::MultiSpan; +use rustc_hir::def_id::DefId; +use rustc_index::Idx; +use rustc_span::symbol::sym; +use rustc_span::symbol::{kw, Symbol}; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; +use rustc_type_ir::RegionKind as IrRegionKind; +use std::ops::Deref; + +use crate::ty::{self, BoundVar, TyCtxt, TypeFlags}; + +pub type RegionKind<'tcx> = IrRegionKind>; + +/// Use this rather than `RegionKind`, whenever possible. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] +#[rustc_pass_by_value] +pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); + +impl<'tcx> rustc_type_ir::IntoKind for Region<'tcx> { + type Kind = RegionKind<'tcx>; + + fn kind(self) -> RegionKind<'tcx> { + *self + } +} + +impl<'tcx> Region<'tcx> { + #[inline] + pub fn new_early_param( + tcx: TyCtxt<'tcx>, + early_bound_region: ty::EarlyParamRegion, + ) -> Region<'tcx> { + tcx.intern_region(ty::ReEarlyParam(early_bound_region)) + } + + #[inline] + pub fn new_bound( + tcx: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + bound_region: ty::BoundRegion, + ) -> Region<'tcx> { + // Use a pre-interned one when possible. + if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region + && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) + && let Some(re) = inner.get(var.as_usize()).copied() + { + re + } else { + tcx.intern_region(ty::ReBound(debruijn, bound_region)) + } + } + + #[inline] + pub fn new_late_param( + tcx: TyCtxt<'tcx>, + scope: DefId, + bound_region: ty::BoundRegionKind, + ) -> Region<'tcx> { + tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region })) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { + // Use a pre-interned one when possible. + tcx.lifetimes + .re_vars + .get(v.as_usize()) + .copied() + .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) + } + + #[inline] + pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> { + tcx.intern_region(ty::RePlaceholder(placeholder)) + } + + /// Constructs a `RegionKind::ReError` region. + #[track_caller] + pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> { + tcx.intern_region(ty::ReError(reported)) + } + + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it + /// gets used. + #[track_caller] + pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { + Region::new_error_with_message( + tcx, + DUMMY_SP, + "RegionKind::ReError constructed but no error reported", + ) + } + + /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given + /// `msg` to ensure it gets used. + #[track_caller] + pub fn new_error_with_message>( + tcx: TyCtxt<'tcx>, + span: S, + msg: &'static str, + ) -> Region<'tcx> { + let reported = tcx.dcx().span_delayed_bug(span, msg); + Region::new_error(tcx, reported) + } + + /// Avoid this in favour of more specific `new_*` methods, where possible, + /// to avoid the cost of the `match`. + pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { + match kind { + ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), + ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), + ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => { + Region::new_late_param(tcx, scope, bound_region) + } + ty::ReStatic => tcx.lifetimes.re_static, + ty::ReVar(vid) => Region::new_var(tcx, vid), + ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), + ty::ReErased => tcx.lifetimes.re_erased, + ty::ReError(reported) => Region::new_error(tcx, reported), + } + } +} + +/// Region utilities +impl<'tcx> Region<'tcx> { + pub fn kind(self) -> RegionKind<'tcx> { + *self.0.0 + } + + pub fn get_name(self) -> Option { + if self.has_name() { + match *self { + ty::ReEarlyParam(ebr) => Some(ebr.name), + ty::ReBound(_, br) => br.kind.get_name(), + ty::ReLateParam(fr) => fr.bound_region.get_name(), + ty::ReStatic => Some(kw::StaticLifetime), + ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), + _ => None, + } + } else { + None + } + } + + pub fn get_name_or_anon(self) -> Symbol { + match self.get_name() { + Some(name) => name, + None => sym::anon, + } + } + + /// Is this region named by the user? + pub fn has_name(self) -> bool { + match *self { + ty::ReEarlyParam(ebr) => ebr.has_name(), + ty::ReBound(_, br) => br.kind.is_named(), + ty::ReLateParam(fr) => fr.bound_region.is_named(), + ty::ReStatic => true, + ty::ReVar(..) => false, + ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), + ty::ReErased => false, + ty::ReError(_) => false, + } + } + + #[inline] + pub fn is_error(self) -> bool { + matches!(*self, ty::ReError(_)) + } + + #[inline] + pub fn is_static(self) -> bool { + matches!(*self, ty::ReStatic) + } + + #[inline] + pub fn is_erased(self) -> bool { + matches!(*self, ty::ReErased) + } + + #[inline] + pub fn is_bound(self) -> bool { + matches!(*self, ty::ReBound(..)) + } + + #[inline] + pub fn is_placeholder(self) -> bool { + matches!(*self, ty::RePlaceholder(..)) + } + + #[inline] + pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { + match *self { + ty::ReBound(debruijn, _) => debruijn >= index, + _ => false, + } + } + + pub fn type_flags(self) -> TypeFlags { + let mut flags = TypeFlags::empty(); + + match *self { + ty::ReVar(..) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_RE_INFER; + } + ty::RePlaceholder(..) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; + } + ty::ReEarlyParam(..) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + flags = flags | TypeFlags::HAS_RE_PARAM; + } + ty::ReLateParam { .. } => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; + } + ty::ReStatic => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + } + ty::ReBound(..) => { + flags = flags | TypeFlags::HAS_RE_BOUND; + } + ty::ReErased => { + flags = flags | TypeFlags::HAS_RE_ERASED; + } + ty::ReError(_) => { + flags = flags | TypeFlags::HAS_FREE_REGIONS; + } + } + + debug!("type_flags({:?}) = {:?}", self, flags); + + flags + } + + /// Given an early-bound or free region, returns the `DefId` where it was bound. + /// For example, consider the regions in this snippet of code: + /// + /// ```ignore (illustrative) + /// impl<'a> Foo { + /// // ^^ -- early bound, declared on an impl + /// + /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c + /// // ^^ ^^ ^ anonymous, late-bound + /// // | early-bound, appears in where-clauses + /// // late-bound, appears only in fn args + /// {..} + /// } + /// ``` + /// + /// Here, `free_region_binding_scope('a)` would return the `DefId` + /// of the impl, and for all the other highlighted regions, it + /// would return the `DefId` of the function. In other cases (not shown), this + /// function might return the `DefId` of a closure. + pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { + match *self { + ty::ReEarlyParam(br) => tcx.parent(br.def_id), + ty::ReLateParam(fr) => fr.scope, + _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), + } + } + + /// True for free regions other than `'static`. + pub fn is_param(self) -> bool { + matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) + } + + /// True for free region in the current context. + /// + /// This is the case for `'static` and param regions. + pub fn is_free(self) -> bool { + match *self { + ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true, + ty::ReVar(..) + | ty::RePlaceholder(..) + | ty::ReBound(..) + | ty::ReErased + | ty::ReError(..) => false, + } + } + + pub fn is_var(self) -> bool { + matches!(self.kind(), ty::ReVar(_)) + } + + pub fn as_var(self) -> RegionVid { + match self.kind() { + ty::ReVar(vid) => vid, + _ => bug!("expected region {:?} to be of kind ReVar", self), + } + } +} + +impl<'tcx> Deref for Region<'tcx> { + type Target = RegionKind<'tcx>; + + #[inline] + fn deref(&self) -> &RegionKind<'tcx> { + self.0.0 + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] +#[derive(HashStable)] +pub struct EarlyParamRegion { + pub def_id: DefId, + pub index: u32, + pub name: Symbol, +} + +impl std::fmt::Debug for EarlyParamRegion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) + } +} + +rustc_index::newtype_index! { + /// A **region** (lifetime) **v**ariable **ID**. + #[derive(HashStable)] + #[encodable] + #[orderable] + #[debug_format = "'?{}"] + pub struct RegionVid {} +} + +impl Atom for RegionVid { + fn index(self) -> usize { + Idx::index(self) + } +} + +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] +#[derive(HashStable)] +/// The parameter representation of late-bound function parameters, "some region +/// at least as big as the scope `fr.scope`". +pub struct LateParamRegion { + pub scope: DefId, + pub bound_region: BoundRegionKind, +} + +#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] +#[derive(HashStable)] +pub enum BoundRegionKind { + /// An anonymous region parameter for a given fn (&T) + BrAnon, + + /// Named region parameters for functions (a in &'a T) + /// + /// The `DefId` is needed to distinguish free regions in + /// the event of shadowing. + BrNamed(DefId, Symbol), + + /// Anonymous region for the implicit env pointer parameter + /// to a closure + BrEnv, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] +#[derive(HashStable)] +pub struct BoundRegion { + pub var: BoundVar, + pub kind: BoundRegionKind, +} + +impl BoundRegionKind { + pub fn is_named(&self) -> bool { + match *self { + BoundRegionKind::BrNamed(_, name) => { + name != kw::UnderscoreLifetime && name != kw::Empty + } + _ => false, + } + } + + pub fn get_name(&self) -> Option { + if self.is_named() { + match *self { + BoundRegionKind::BrNamed(_, name) => return Some(name), + _ => unreachable!(), + } + } + + None + } + + pub fn get_id(&self) -> Option { + match *self { + BoundRegionKind::BrNamed(id, _) => return Some(id), + _ => None, + } + } +} diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8543bd0bbdd96..f2321e7e1d22f 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -481,6 +481,13 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(Ty::new_closure(tcx, a_id, args)) } + (&ty::CoroutineClosure(a_id, a_args), &ty::CoroutineClosure(b_id, b_args)) + if a_id == b_id => + { + let args = relate_args_invariantly(relation, a_args, b_args)?; + Ok(Ty::new_coroutine_closure(tcx, a_id, args)) + } + (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; Ok(Ty::new_ptr(tcx, mt)) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 11b579a1f85b6..c6805ba932357 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -584,6 +584,9 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::CoroutineWitness(did, args.try_fold_with(folder)?) } ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?), + ty::CoroutineClosure(did, args) => { + ty::CoroutineClosure(did, args.try_fold_with(folder)?) + } ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?), ty::Bool @@ -632,6 +635,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { ty::Coroutine(_did, ref args) => args.visit_with(visitor), ty::CoroutineWitness(_did, ref args) => args.visit_with(visitor), ty::Closure(_did, ref args) => args.visit_with(visitor), + ty::CoroutineClosure(_did, ref args) => args.visit_with(visitor), ty::Alias(_, ref data) => data.visit_with(visitor), ty::Bool diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 43a6281481fa4..f592acd4b6ff5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -6,119 +6,44 @@ use crate::infer::canonical::Canonical; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, Discr, IntoKind, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, + self, AdtDef, BoundRegionKind, Discr, Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use crate::ty::{List, ParamEnv}; use hir::def::DefKind; -use polonius_engine::Atom; use rustc_data_structures::captures::Captures; -use rustc_data_structures::intern::Interned; use rustc_errors::{ DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; -use rustc_index::Idx; use rustc_macros::HashStable; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi::{self, Abi}; use std::assert_matches::debug_assert_matches; use std::borrow::Cow; -use std::cmp::Ordering; -use std::fmt; use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; use rustc_type_ir::BoundVar; -use rustc_type_ir::ClauseKind as IrClauseKind; use rustc_type_ir::CollectAndApply; -use rustc_type_ir::ConstKind as IrConstKind; -use rustc_type_ir::DebugWithInfcx; use rustc_type_ir::DynKind; -use rustc_type_ir::PredicateKind as IrPredicateKind; -use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; use rustc_type_ir::TyKind::*; use rustc_type_ir::TypeAndMut as IrTypeAndMut; +use super::fold::FnMutDelegate; use super::GenericParamDefKind; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind>; -pub type RegionKind<'tcx> = IrRegionKind>; -pub type ConstKind<'tcx> = IrConstKind>; -pub type PredicateKind<'tcx> = IrPredicateKind>; -pub type ClauseKind<'tcx> = IrClauseKind>; pub type TypeAndMut<'tcx> = IrTypeAndMut>; -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] -#[derive(HashStable)] -/// The parameter representation of late-bound function parameters, "some region -/// at least as big as the scope `fr.scope`". -pub struct LateParamRegion { - pub scope: DefId, - pub bound_region: BoundRegionKind, -} - -#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] -#[derive(HashStable)] -pub enum BoundRegionKind { - /// An anonymous region parameter for a given fn (&T) - BrAnon, - - /// Named region parameters for functions (a in &'a T) - /// - /// The `DefId` is needed to distinguish free regions in - /// the event of shadowing. - BrNamed(DefId, Symbol), - - /// Anonymous region for the implicit env pointer parameter - /// to a closure - BrEnv, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] -#[derive(HashStable)] -pub struct BoundRegion { - pub var: BoundVar, - pub kind: BoundRegionKind, -} - -impl BoundRegionKind { - pub fn is_named(&self) -> bool { - match *self { - BoundRegionKind::BrNamed(_, name) => { - name != kw::UnderscoreLifetime && name != kw::Empty - } - _ => false, - } - } - - pub fn get_name(&self) -> Option { - if self.is_named() { - match *self { - BoundRegionKind::BrNamed(_, name) => return Some(name), - _ => unreachable!(), - } - } - - None - } - - pub fn get_id(&self) -> Option { - match *self { - BoundRegionKind::BrNamed(id, _) => return Some(id), - _ => None, - } - } -} - pub trait Article { fn article(&self) -> &'static str; } @@ -345,6 +270,275 @@ impl<'tcx> ClosureArgs<'tcx> { } } +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] +pub struct CoroutineClosureArgs<'tcx> { + pub args: GenericArgsRef<'tcx>, +} + +/// See docs for explanation of how each argument is used. +/// +/// See [`CoroutineClosureSignature`] for how these arguments are put together +/// to make a callable [`FnSig`] suitable for typeck and borrowck. +pub struct CoroutineClosureArgsParts<'tcx> { + /// This is the args of the typeck root. + pub parent_args: &'tcx [GenericArg<'tcx>], + /// Represents the maximum calling capability of the closure. + pub closure_kind_ty: Ty<'tcx>, + /// Represents all of the relevant parts of the coroutine returned by this + /// coroutine-closure. This signature parts type will have the general + /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where + /// `resume_ty`, `return_ty`, and `yield_ty` are the respective types for the + /// coroutine returned by the coroutine-closure. + /// + /// Use `coroutine_closure_sig` to break up this type rather than using it + /// yourself. + pub signature_parts_ty: Ty<'tcx>, + /// The upvars captured by the closure. Remains an inference variable + /// until the upvar analysis, which happens late in HIR typeck. + pub tupled_upvars_ty: Ty<'tcx>, + /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`. + /// This allows us to represent the binder of the self-captures of the closure. + /// + /// For example, if the coroutine returned by the closure borrows `String` + /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`, + /// while the `tupled_upvars_ty`, representing the by-move version of the same + /// captures, will be `(String,)`. + pub coroutine_captures_by_ref_ty: Ty<'tcx>, + /// Witness type returned by the generator produced by this coroutine-closure. + pub coroutine_witness_ty: Ty<'tcx>, +} + +impl<'tcx> CoroutineClosureArgs<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + parts: CoroutineClosureArgsParts<'tcx>, + ) -> CoroutineClosureArgs<'tcx> { + CoroutineClosureArgs { + args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.closure_kind_ty.into(), + parts.signature_parts_ty.into(), + parts.tupled_upvars_ty.into(), + parts.coroutine_captures_by_ref_ty.into(), + parts.coroutine_witness_ty.into(), + ])), + } + } + + fn split(self) -> CoroutineClosureArgsParts<'tcx> { + match self.args[..] { + [ + ref parent_args @ .., + closure_kind_ty, + signature_parts_ty, + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + coroutine_witness_ty, + ] => CoroutineClosureArgsParts { + parent_args, + closure_kind_ty: closure_kind_ty.expect_ty(), + signature_parts_ty: signature_parts_ty.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(), + coroutine_witness_ty: coroutine_witness_ty.expect_ty(), + }, + _ => bug!("closure args missing synthetics"), + } + } + + pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] { + self.split().parent_args + } + + #[inline] + pub fn upvar_tys(self) -> &'tcx List> { + match self.tupled_upvars_ty().kind() { + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), + TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), + ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), + } + } + + #[inline] + pub fn tupled_upvars_ty(self) -> Ty<'tcx> { + self.split().tupled_upvars_ty + } + + pub fn kind_ty(self) -> Ty<'tcx> { + self.split().closure_kind_ty + } + + pub fn kind(self) -> ty::ClosureKind { + self.kind_ty().to_opt_closure_kind().unwrap() + } + + pub fn signature_parts_ty(self) -> Ty<'tcx> { + self.split().signature_parts_ty + } + + pub fn coroutine_closure_sig(self) -> ty::Binder<'tcx, CoroutineClosureSignature<'tcx>> { + let interior = self.coroutine_witness_ty(); + let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { bug!() }; + sig.map_bound(|sig| { + let [resume_ty, tupled_inputs_ty] = *sig.inputs() else { + bug!(); + }; + let [yield_ty, return_ty] = **sig.output().tuple_fields() else { bug!() }; + CoroutineClosureSignature { + interior, + tupled_inputs_ty, + resume_ty, + yield_ty, + return_ty, + c_variadic: sig.c_variadic, + unsafety: sig.unsafety, + abi: sig.abi, + } + }) + } + + pub fn coroutine_captures_by_ref_ty(self) -> Ty<'tcx> { + self.split().coroutine_captures_by_ref_ty + } + + pub fn coroutine_witness_ty(self) -> Ty<'tcx> { + self.split().coroutine_witness_ty + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] +pub struct CoroutineClosureSignature<'tcx> { + pub interior: Ty<'tcx>, + pub tupled_inputs_ty: Ty<'tcx>, + pub resume_ty: Ty<'tcx>, + pub yield_ty: Ty<'tcx>, + pub return_ty: Ty<'tcx>, + + // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types + // never actually differ. But we save them rather than recreating them + // from scratch just for good measure. + /// Always false + pub c_variadic: bool, + /// Always [`hir::Unsafety::Normal`] + pub unsafety: hir::Unsafety, + /// Always [`abi::Abi::RustCall`] + pub abi: abi::Abi, +} + +impl<'tcx> CoroutineClosureSignature<'tcx> { + /// Construct a coroutine from the closure signature. Since a coroutine signature + /// is agnostic to the type of generator that is returned (by-ref/by-move), + /// the caller must specify what "flavor" of generator that they'd like to + /// create. Additionally, they must manually compute the upvars of the closure. + /// + /// This helper is not really meant to be used directly except for early on + /// during typeck, when we want to put inference vars into the kind and upvars tys. + /// When the kind and upvars are known, use the other helper functions. + pub fn to_coroutine( + self, + tcx: TyCtxt<'tcx>, + parent_args: &'tcx [GenericArg<'tcx>], + coroutine_kind_ty: Ty<'tcx>, + coroutine_def_id: DefId, + tupled_upvars_ty: Ty<'tcx>, + ) -> Ty<'tcx> { + let coroutine_args = ty::CoroutineArgs::new( + tcx, + ty::CoroutineArgsParts { + parent_args, + kind_ty: coroutine_kind_ty, + resume_ty: self.resume_ty, + yield_ty: self.yield_ty, + return_ty: self.return_ty, + witness: self.interior, + tupled_upvars_ty, + }, + ); + + Ty::new_coroutine(tcx, coroutine_def_id, coroutine_args.args) + } + + /// Given known upvars and a [`ClosureKind`](ty::ClosureKind), compute the coroutine + /// returned by that corresponding async fn trait. + /// + /// This function expects the upvars to have been computed already, and doesn't check + /// that the `ClosureKind` is actually supported by the coroutine-closure. + pub fn to_coroutine_given_kind_and_upvars( + self, + tcx: TyCtxt<'tcx>, + parent_args: &'tcx [GenericArg<'tcx>], + coroutine_def_id: DefId, + goal_kind: ty::ClosureKind, + env_region: ty::Region<'tcx>, + closure_tupled_upvars_ty: Ty<'tcx>, + coroutine_captures_by_ref_ty: Ty<'tcx>, + ) -> Ty<'tcx> { + let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( + tcx, + goal_kind, + self.tupled_inputs_ty, + closure_tupled_upvars_ty, + coroutine_captures_by_ref_ty, + env_region, + ); + + self.to_coroutine( + tcx, + parent_args, + Ty::from_closure_kind(tcx, goal_kind), + coroutine_def_id, + tupled_upvars_ty, + ) + } + + /// Compute the tupled upvars that a coroutine-closure's output coroutine + /// would return for the given `ClosureKind`. + /// + /// When `ClosureKind` is `FnMut`/`Fn`, then this will use the "captures by ref" + /// to return a set of upvars which are borrowed with the given `env_region`. + /// + /// This ensures that the `AsyncFn::call` will return a coroutine whose upvars' + /// lifetimes are related to the lifetime of the borrow on the closure made for + /// the call. This allows borrowck to enforce the self-borrows correctly. + pub fn tupled_upvars_by_closure_kind( + tcx: TyCtxt<'tcx>, + kind: ty::ClosureKind, + tupled_inputs_ty: Ty<'tcx>, + closure_tupled_upvars_ty: Ty<'tcx>, + coroutine_captures_by_ref_ty: Ty<'tcx>, + env_region: ty::Region<'tcx>, + ) -> Ty<'tcx> { + match kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { + let ty::FnPtr(sig) = *coroutine_captures_by_ref_ty.kind() else { + bug!(); + }; + let coroutine_captures_by_ref_ty = tcx.replace_escaping_bound_vars_uncached( + sig.output().skip_binder(), + FnMutDelegate { + consts: &mut |c, t| ty::Const::new_bound(tcx, ty::INNERMOST, c, t), + types: &mut |t| Ty::new_bound(tcx, ty::INNERMOST, t), + regions: &mut |_| env_region, + }, + ); + Ty::new_tup_from_iter( + tcx, + tupled_inputs_ty + .tuple_fields() + .iter() + .chain(coroutine_captures_by_ref_ty.tuple_fields()), + ) + } + ty::ClosureKind::FnOnce => Ty::new_tup_from_iter( + tcx, + tupled_inputs_ty + .tuple_fields() + .iter() + .chain(closure_tupled_upvars_ty.tuple_fields()), + ), + } + } +} /// Similar to `ClosureArgs`; see the above documentation for more. #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)] pub struct CoroutineArgs<'tcx> { @@ -354,13 +548,27 @@ pub struct CoroutineArgs<'tcx> { pub struct CoroutineArgsParts<'tcx> { /// This is the args of the typeck root. pub parent_args: &'tcx [GenericArg<'tcx>], + + /// The coroutines returned by a coroutine-closure's `AsyncFnOnce`/`AsyncFnMut` + /// implementations must be distinguished since the former takes the closure's + /// upvars by move, and the latter takes the closure's upvars by ref. + /// + /// This field distinguishes these fields so that codegen can select the right + /// body for the coroutine. This has the same type representation as the closure + /// kind: `i8`/`i16`/`i32`. + /// + /// For regular coroutines, this field will always just be `()`. + pub kind_ty: Ty<'tcx>, + pub resume_ty: Ty<'tcx>, pub yield_ty: Ty<'tcx>, pub return_ty: Ty<'tcx>, + /// The interior type of the coroutine. /// Represents all types that are stored in locals /// in the coroutine's body. pub witness: Ty<'tcx>, + /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. pub tupled_upvars_ty: Ty<'tcx>, @@ -372,6 +580,7 @@ impl<'tcx> CoroutineArgs<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, parts: CoroutineArgsParts<'tcx>) -> CoroutineArgs<'tcx> { CoroutineArgs { args: tcx.mk_args_from_iter(parts.parent_args.iter().copied().chain([ + parts.kind_ty.into(), parts.resume_ty.into(), parts.yield_ty.into(), parts.return_ty.into(), @@ -385,16 +594,23 @@ impl<'tcx> CoroutineArgs<'tcx> { /// The ordering assumed here must match that used by `CoroutineArgs::new` above. fn split(self) -> CoroutineArgsParts<'tcx> { match self.args[..] { - [ref parent_args @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { - CoroutineArgsParts { - parent_args, - resume_ty: resume_ty.expect_ty(), - yield_ty: yield_ty.expect_ty(), - return_ty: return_ty.expect_ty(), - witness: witness.expect_ty(), - tupled_upvars_ty: tupled_upvars_ty.expect_ty(), - } - } + [ + ref parent_args @ .., + kind_ty, + resume_ty, + yield_ty, + return_ty, + witness, + tupled_upvars_ty, + ] => CoroutineArgsParts { + parent_args, + kind_ty: kind_ty.expect_ty(), + resume_ty: resume_ty.expect_ty(), + yield_ty: yield_ty.expect_ty(), + return_ty: return_ty.expect_ty(), + witness: witness.expect_ty(), + tupled_upvars_ty: tupled_upvars_ty.expect_ty(), + }, _ => bug!("coroutine args missing synthetics"), } } @@ -404,6 +620,11 @@ impl<'tcx> CoroutineArgs<'tcx> { self.split().parent_args } + // Returns the kind of the coroutine. See docs on the `kind_ty` field. + pub fn kind_ty(self) -> Ty<'tcx> { + self.split().kind_ty + } + /// This describes the types that can be contained in a coroutine. /// It will be a type variable initially and unified in the last stages of typeck of a body. /// It contains a tuple of all the types that could end up on a coroutine frame. @@ -555,6 +776,7 @@ impl<'tcx> CoroutineArgs<'tcx> { pub enum UpvarArgs<'tcx> { Closure(GenericArgsRef<'tcx>), Coroutine(GenericArgsRef<'tcx>), + CoroutineClosure(GenericArgsRef<'tcx>), } impl<'tcx> UpvarArgs<'tcx> { @@ -566,6 +788,7 @@ impl<'tcx> UpvarArgs<'tcx> { let tupled_tys = match self { UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(), + UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(), }; match tupled_tys.kind() { @@ -581,6 +804,7 @@ impl<'tcx> UpvarArgs<'tcx> { match self { UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(), + UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(), } } } @@ -645,290 +869,6 @@ impl<'tcx> InlineConstArgs<'tcx> { } } -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub enum ExistentialPredicate<'tcx> { - /// E.g., `Iterator`. - Trait(ExistentialTraitRef<'tcx>), - /// E.g., `Iterator::Item = T`. - Projection(ExistentialProjection<'tcx>), - /// E.g., `Send`. - AutoTrait(DefId), -} - -impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { - fn fmt>>( - this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - fmt::Debug::fmt(&this.data, f) - } -} - -impl<'tcx> ExistentialPredicate<'tcx> { - /// Compares via an ordering that will not change if modules are reordered or other changes are - /// made to the tree. In particular, this ordering is preserved across incremental compilations. - pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering { - use self::ExistentialPredicate::*; - match (*self, *other) { - (Trait(_), Trait(_)) => Ordering::Equal, - (Projection(ref a), Projection(ref b)) => { - tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id)) - } - (AutoTrait(ref a), AutoTrait(ref b)) => { - tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) - } - (Trait(_), _) => Ordering::Less, - (Projection(_), Trait(_)) => Ordering::Greater, - (Projection(_), _) => Ordering::Less, - (AutoTrait(_), _) => Ordering::Greater, - } - } -} - -pub type PolyExistentialPredicate<'tcx> = Binder<'tcx, ExistentialPredicate<'tcx>>; - -impl<'tcx> PolyExistentialPredicate<'tcx> { - /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), - /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` - /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { - use crate::ty::ToPredicate; - match self.skip_binder() { - ExistentialPredicate::Trait(tr) => { - self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) - } - ExistentialPredicate::Projection(p) => { - self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) - } - ExistentialPredicate::AutoTrait(did) => { - let generics = tcx.generics_of(did); - let trait_ref = if generics.params.len() == 1 { - ty::TraitRef::new(tcx, did, [self_ty]) - } else { - // If this is an ill-formed auto trait, then synthesize - // new error args for the missing generics. - let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); - ty::TraitRef::new(tcx, did, err_args) - }; - self.rebind(trait_ref).to_predicate(tcx) - } - } - } -} - -impl<'tcx> List> { - /// Returns the "principal `DefId`" of this set of existential predicates. - /// - /// A Rust trait object type consists (in addition to a lifetime bound) - /// of a set of trait bounds, which are separated into any number - /// of auto-trait bounds, and at most one non-auto-trait bound. The - /// non-auto-trait bound is called the "principal" of the trait - /// object. - /// - /// Only the principal can have methods or type parameters (because - /// auto traits can have neither of them). This is important, because - /// it means the auto traits can be treated as an unordered set (methods - /// would force an order for the vtable, while relating traits with - /// type parameters without knowing the order to relate them in is - /// a rather non-trivial task). - /// - /// For example, in the trait object `dyn fmt::Debug + Sync`, the - /// principal bound is `Some(fmt::Debug)`, while the auto-trait bounds - /// are the set `{Sync}`. - /// - /// It is also possible to have a "trivial" trait object that - /// consists only of auto traits, with no principal - for example, - /// `dyn Send + Sync`. In that case, the set of auto-trait bounds - /// is `{Send, Sync}`, while there is no principal. These trait objects - /// have a "trivial" vtable consisting of just the size, alignment, - /// and destructor. - pub fn principal(&self) -> Option>> { - self[0] - .map_bound(|this| match this { - ExistentialPredicate::Trait(tr) => Some(tr), - _ => None, - }) - .transpose() - } - - pub fn principal_def_id(&self) -> Option { - self.principal().map(|trait_ref| trait_ref.skip_binder().def_id) - } - - #[inline] - pub fn projection_bounds<'a>( - &'a self, - ) -> impl Iterator>> + 'a { - self.iter().filter_map(|predicate| { - predicate - .map_bound(|pred| match pred { - ExistentialPredicate::Projection(projection) => Some(projection), - _ => None, - }) - .transpose() - }) - } - - #[inline] - pub fn auto_traits<'a>(&'a self) -> impl Iterator + Captures<'tcx> + 'a { - self.iter().filter_map(|predicate| match predicate.skip_binder() { - ExistentialPredicate::AutoTrait(did) => Some(did), - _ => None, - }) - } -} - -/// A complete reference to a trait. These take numerous guises in syntax, -/// but perhaps the most recognizable form is in a where-clause: -/// ```ignore (illustrative) -/// T: Foo -/// ``` -/// This would be represented by a trait-reference where the `DefId` is the -/// `DefId` for the trait `Foo` and the args define `T` as parameter 0, -/// and `U` as parameter 1. -/// -/// Trait references also appear in object types like `Foo`, but in -/// that case the `Self` parameter is absent from the substitutions. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct TraitRef<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, - /// This field exists to prevent the creation of `TraitRef` without - /// calling [`TraitRef::new`]. - pub(super) _use_trait_ref_new_instead: (), -} - -impl<'tcx> TraitRef<'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - args: impl IntoIterator>>, - ) -> Self { - let args = tcx.check_and_mk_args(trait_def_id, args); - Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () } - } - - pub fn from_lang_item( - tcx: TyCtxt<'tcx>, - trait_lang_item: LangItem, - span: Span, - args: impl IntoIterator>>, - ) -> Self { - let trait_def_id = tcx.require_lang_item(trait_lang_item, Some(span)); - Self::new(tcx, trait_def_id, args) - } - - pub fn from_method( - tcx: TyCtxt<'tcx>, - trait_id: DefId, - args: GenericArgsRef<'tcx>, - ) -> ty::TraitRef<'tcx> { - let defs = tcx.generics_of(trait_id); - ty::TraitRef::new(tcx, trait_id, tcx.mk_args(&args[..defs.params.len()])) - } - - /// Returns a `TraitRef` of the form `P0: Foo` where `Pi` - /// are the parameters defined on trait. - pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> { - ty::TraitRef::new(tcx, def_id, GenericArgs::identity_for_item(tcx, def_id)) - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - ty::TraitRef::new( - tcx, - self.def_id, - [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), - ) - } - - #[inline] - pub fn self_ty(&self) -> Ty<'tcx> { - self.args.type_at(0) - } -} - -pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>; - -impl<'tcx> PolyTraitRef<'tcx> { - pub fn self_ty(&self) -> Binder<'tcx, Ty<'tcx>> { - self.map_bound_ref(|tr| tr.self_ty()) - } - - pub fn def_id(&self) -> DefId { - self.skip_binder().def_id - } -} - -impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue { - self.to_string().into_diagnostic_arg() - } -} - -/// An existential reference to a trait, where `Self` is erased. -/// For example, the trait object `Trait<'a, 'b, X, Y>` is: -/// ```ignore (illustrative) -/// exists T. T: Trait<'a, 'b, X, Y> -/// ``` -/// The substitutions don't include the erased `Self`, only trait -/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ExistentialTraitRef<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, -} - -impl<'tcx> ExistentialTraitRef<'tcx> { - pub fn erase_self_ty( - tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - ) -> ty::ExistentialTraitRef<'tcx> { - // Assert there is a Self. - trait_ref.args.type_at(0); - - ty::ExistentialTraitRef { - def_id: trait_ref.def_id, - args: tcx.mk_args(&trait_ref.args[1..]), - } - } - - /// Object types don't have a self type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self type. A common choice is `mk_err()` - /// or some placeholder type. - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { - // otherwise the escaping vars would be captured by the binder - // debug_assert!(!self_ty.has_escaping_bound_vars()); - - ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) - } -} - -impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> { - fn into_diagnostic_arg(self) -> DiagnosticArgValue { - self.to_string().into_diagnostic_arg() - } -} - -pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>; - -impl<'tcx> PolyExistentialTraitRef<'tcx> { - pub fn def_id(&self) -> DefId { - self.skip_binder().def_id - } - - /// Object types don't have a self type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self type. A common choice is `mk_err()` - /// or some placeholder type. - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> { - self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty)) - } -} - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable)] pub enum BoundVariableKind { @@ -1112,6 +1052,7 @@ impl<'tcx, T> Binder<'tcx, T> { where T: TypeVisitable>, { + // `self.value` is equivalent to `self.skip_binder()` if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } @@ -1372,6 +1313,7 @@ impl<'tcx> PolyFnSig<'tcx> { self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) } #[inline] + #[track_caller] pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } @@ -1452,154 +1394,6 @@ impl ParamConst { } } -/// Use this rather than `RegionKind`, whenever possible. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] -#[rustc_pass_by_value] -pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); - -impl<'tcx> IntoKind for Region<'tcx> { - type Kind = RegionKind<'tcx>; - - fn kind(self) -> RegionKind<'tcx> { - *self - } -} - -impl<'tcx> Region<'tcx> { - #[inline] - pub fn new_early_param( - tcx: TyCtxt<'tcx>, - early_bound_region: ty::EarlyParamRegion, - ) -> Region<'tcx> { - tcx.intern_region(ty::ReEarlyParam(early_bound_region)) - } - - #[inline] - pub fn new_bound( - tcx: TyCtxt<'tcx>, - debruijn: ty::DebruijnIndex, - bound_region: ty::BoundRegion, - ) -> Region<'tcx> { - // Use a pre-interned one when possible. - if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region - && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) - && let Some(re) = inner.get(var.as_usize()).copied() - { - re - } else { - tcx.intern_region(ty::ReBound(debruijn, bound_region)) - } - } - - #[inline] - pub fn new_late_param( - tcx: TyCtxt<'tcx>, - scope: DefId, - bound_region: ty::BoundRegionKind, - ) -> Region<'tcx> { - tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region })) - } - - #[inline] - pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { - // Use a pre-interned one when possible. - tcx.lifetimes - .re_vars - .get(v.as_usize()) - .copied() - .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) - } - - #[inline] - pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> { - tcx.intern_region(ty::RePlaceholder(placeholder)) - } - - /// Constructs a `RegionKind::ReError` region. - #[track_caller] - pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> { - tcx.intern_region(ty::ReError(reported)) - } - - /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` to ensure it - /// gets used. - #[track_caller] - pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { - Region::new_error_with_message( - tcx, - DUMMY_SP, - "RegionKind::ReError constructed but no error reported", - ) - } - - /// Constructs a `RegionKind::ReError` region and registers a `span_delayed_bug` with the given - /// `msg` to ensure it gets used. - #[track_caller] - pub fn new_error_with_message>( - tcx: TyCtxt<'tcx>, - span: S, - msg: &'static str, - ) -> Region<'tcx> { - let reported = tcx.dcx().span_delayed_bug(span, msg); - Region::new_error(tcx, reported) - } - - /// Avoid this in favour of more specific `new_*` methods, where possible, - /// to avoid the cost of the `match`. - pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { - match kind { - ty::ReEarlyParam(region) => Region::new_early_param(tcx, region), - ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region), - ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => { - Region::new_late_param(tcx, scope, bound_region) - } - ty::ReStatic => tcx.lifetimes.re_static, - ty::ReVar(vid) => Region::new_var(tcx, vid), - ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), - ty::ReErased => tcx.lifetimes.re_erased, - ty::ReError(reported) => Region::new_error(tcx, reported), - } - } -} - -impl<'tcx> Deref for Region<'tcx> { - type Target = RegionKind<'tcx>; - - #[inline] - fn deref(&self) -> &RegionKind<'tcx> { - self.0.0 - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] -#[derive(HashStable)] -pub struct EarlyParamRegion { - pub def_id: DefId, - pub index: u32, - pub name: Symbol, -} - -impl fmt::Debug for EarlyParamRegion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) - } -} - -rustc_index::newtype_index! { - /// A **region** (lifetime) **v**ariable **ID**. - #[derive(HashStable)] - #[encodable] - #[orderable] - #[debug_format = "'?{}"] - pub struct RegionVid {} -} - -impl Atom for RegionVid { - fn index(self) -> usize { - Idx::index(self) - } -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct BoundTy { @@ -1620,251 +1414,6 @@ impl From for BoundTy { } } -/// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ExistentialProjection<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, - pub term: Term<'tcx>, -} - -pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; - -impl<'tcx> ExistentialProjection<'tcx> { - /// Extracts the underlying existential trait reference from this projection. - /// For example, if this is a projection of `exists T. ::Item == X`, - /// then this function would return an `exists T. T: Iterator` existential trait - /// reference. - pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { - let def_id = tcx.parent(self.def_id); - let subst_count = tcx.generics_of(def_id).count() - 1; - let args = tcx.mk_args(&self.args[..subst_count]); - ty::ExistentialTraitRef { def_id, args } - } - - pub fn with_self_ty( - &self, - tcx: TyCtxt<'tcx>, - self_ty: Ty<'tcx>, - ) -> ty::ProjectionPredicate<'tcx> { - // otherwise the escaping regions would be captured by the binders - debug_assert!(!self_ty.has_escaping_bound_vars()); - - ty::ProjectionPredicate { - projection_ty: AliasTy::new( - tcx, - self.def_id, - [self_ty.into()].into_iter().chain(self.args), - ), - term: self.term, - } - } - - pub fn erase_self_ty( - tcx: TyCtxt<'tcx>, - projection_predicate: ty::ProjectionPredicate<'tcx>, - ) -> Self { - // Assert there is a Self. - projection_predicate.projection_ty.args.type_at(0); - - Self { - def_id: projection_predicate.projection_ty.def_id, - args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]), - term: projection_predicate.term, - } - } -} - -impl<'tcx> PolyExistentialProjection<'tcx> { - pub fn with_self_ty( - &self, - tcx: TyCtxt<'tcx>, - self_ty: Ty<'tcx>, - ) -> ty::PolyProjectionPredicate<'tcx> { - self.map_bound(|p| p.with_self_ty(tcx, self_ty)) - } - - pub fn item_def_id(&self) -> DefId { - self.skip_binder().def_id - } -} - -/// Region utilities -impl<'tcx> Region<'tcx> { - pub fn kind(self) -> RegionKind<'tcx> { - *self.0.0 - } - - pub fn get_name(self) -> Option { - if self.has_name() { - match *self { - ty::ReEarlyParam(ebr) => Some(ebr.name), - ty::ReBound(_, br) => br.kind.get_name(), - ty::ReLateParam(fr) => fr.bound_region.get_name(), - ty::ReStatic => Some(kw::StaticLifetime), - ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), - _ => None, - } - } else { - None - } - } - - pub fn get_name_or_anon(self) -> Symbol { - match self.get_name() { - Some(name) => name, - None => sym::anon, - } - } - - /// Is this region named by the user? - pub fn has_name(self) -> bool { - match *self { - ty::ReEarlyParam(ebr) => ebr.has_name(), - ty::ReBound(_, br) => br.kind.is_named(), - ty::ReLateParam(fr) => fr.bound_region.is_named(), - ty::ReStatic => true, - ty::ReVar(..) => false, - ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), - ty::ReErased => false, - ty::ReError(_) => false, - } - } - - #[inline] - pub fn is_error(self) -> bool { - matches!(*self, ty::ReError(_)) - } - - #[inline] - pub fn is_static(self) -> bool { - matches!(*self, ty::ReStatic) - } - - #[inline] - pub fn is_erased(self) -> bool { - matches!(*self, ty::ReErased) - } - - #[inline] - pub fn is_bound(self) -> bool { - matches!(*self, ty::ReBound(..)) - } - - #[inline] - pub fn is_placeholder(self) -> bool { - matches!(*self, ty::RePlaceholder(..)) - } - - #[inline] - pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { - match *self { - ty::ReBound(debruijn, _) => debruijn >= index, - _ => false, - } - } - - pub fn type_flags(self) -> TypeFlags { - let mut flags = TypeFlags::empty(); - - match *self { - ty::ReVar(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_RE_INFER; - } - ty::RePlaceholder(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; - } - ty::ReEarlyParam(..) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - flags = flags | TypeFlags::HAS_RE_PARAM; - } - ty::ReLateParam { .. } => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; - } - ty::ReStatic => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - } - ty::ReBound(..) => { - flags = flags | TypeFlags::HAS_RE_BOUND; - } - ty::ReErased => { - flags = flags | TypeFlags::HAS_RE_ERASED; - } - ty::ReError(_) => { - flags = flags | TypeFlags::HAS_FREE_REGIONS; - } - } - - debug!("type_flags({:?}) = {:?}", self, flags); - - flags - } - - /// Given an early-bound or free region, returns the `DefId` where it was bound. - /// For example, consider the regions in this snippet of code: - /// - /// ```ignore (illustrative) - /// impl<'a> Foo { - /// // ^^ -- early bound, declared on an impl - /// - /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c - /// // ^^ ^^ ^ anonymous, late-bound - /// // | early-bound, appears in where-clauses - /// // late-bound, appears only in fn args - /// {..} - /// } - /// ``` - /// - /// Here, `free_region_binding_scope('a)` would return the `DefId` - /// of the impl, and for all the other highlighted regions, it - /// would return the `DefId` of the function. In other cases (not shown), this - /// function might return the `DefId` of a closure. - pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { - match *self { - ty::ReEarlyParam(br) => tcx.parent(br.def_id), - ty::ReLateParam(fr) => fr.scope, - _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), - } - } - - /// True for free regions other than `'static`. - pub fn is_param(self) -> bool { - matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_)) - } - - /// True for free region in the current context. - /// - /// This is the case for `'static` and param regions. - pub fn is_free(self) -> bool { - match *self { - ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true, - ty::ReVar(..) - | ty::RePlaceholder(..) - | ty::ReBound(..) - | ty::ReErased - | ty::ReError(..) => false, - } - } - - pub fn is_var(self) -> bool { - matches!(self.kind(), ty::ReVar(_)) - } - - pub fn as_var(self) -> RegionVid { - match self.kind() { - ty::ReVar(vid) => vid, - _ => bug!("expected region {:?} to be of kind ReVar", self), - } - } -} - /// Constructors for `Ty` impl<'tcx> Ty<'tcx> { // Avoid this in favour of more specific `new_*` methods, where possible. @@ -2116,7 +1665,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_dynamic( tcx: TyCtxt<'tcx>, - obj: &'tcx List>, + obj: &'tcx List>, reg: ty::Region<'tcx>, repr: DynKind, ) -> Ty<'tcx> { @@ -2146,6 +1695,20 @@ impl<'tcx> Ty<'tcx> { Ty::new(tcx, Closure(def_id, closure_args)) } + #[inline] + pub fn new_coroutine_closure( + tcx: TyCtxt<'tcx>, + def_id: DefId, + closure_args: GenericArgsRef<'tcx>, + ) -> Ty<'tcx> { + debug_assert_eq!( + closure_args.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, + "closure constructed with incorrect substitutions" + ); + Ty::new(tcx, CoroutineClosure(def_id, closure_args)) + } + #[inline] pub fn new_coroutine( tcx: TyCtxt<'tcx>, @@ -2154,7 +1717,7 @@ impl<'tcx> Ty<'tcx> { ) -> Ty<'tcx> { debug_assert_eq!( coroutine_args.len(), - tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 6, "coroutine constructed with incorrect number of substitutions" ); Ty::new(tcx, Coroutine(def_id, coroutine_args)) @@ -2480,6 +2043,11 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), Coroutine(..)) } + #[inline] + pub fn is_coroutine_closure(self) -> bool { + matches!(self.kind(), CoroutineClosure(..)) + } + #[inline] pub fn is_integral(self) -> bool { matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_)) @@ -2548,7 +2116,7 @@ impl<'tcx> Ty<'tcx> { type BreakTy = (); fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { - if let ty::Closure(_, _) = t.kind() { + if let ty::Closure(..) = t.kind() { ControlFlow::Break(()) } else { t.super_visit_with(self) @@ -2695,6 +2263,7 @@ impl<'tcx> Ty<'tcx> { | ty::FnPtr(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) @@ -2710,12 +2279,12 @@ impl<'tcx> Ty<'tcx> { } /// Returns the type of metadata for (potentially fat) pointers to this type, - /// and a boolean signifying if this is conditional on this type being `Sized`. - pub fn ptr_metadata_ty( + /// or the struct tail if the metadata type cannot be determined. + pub fn ptr_metadata_ty_or_tail( self, tcx: TyCtxt<'tcx>, normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, - ) -> (Ty<'tcx>, bool) { + ) -> Result, Ty<'tcx>> { let tail = tcx.struct_tail_with_normalize(self, normalize, || {}); match tail.kind() { // Sized types @@ -2733,35 +2302,52 @@ impl<'tcx> Ty<'tcx> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Error(_) // Extern types have metadata = (). | ty::Foreign(..) - // `dyn*` has no metadata + // `dyn*` has metadata = (). | ty::Dynamic(_, _, ty::DynStar) - // If returned by `struct_tail_without_normalization` this is a unit struct + // If returned by `struct_tail_with_normalize` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) - // If returned by `struct_tail_without_normalization` this is the empty tuple, + // If returned by `struct_tail_with_normalize` this is the empty tuple, // a.k.a. unit type, which is Sized - | ty::Tuple(..) => (tcx.types.unit, false), + | ty::Tuple(..) => Ok(tcx.types.unit), + + ty::Str | ty::Slice(_) => Ok(tcx.types.usize), - ty::Str | ty::Slice(_) => (tcx.types.usize, false), ty::Dynamic(_, _, ty::Dyn) => { let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); - (tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false) - }, + Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()])) + } - // type parameters only have unit metadata if they're sized, so return true - // to make sure we double check this during confirmation - ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true), + // We don't know the metadata of `self`, but it must be equal to the + // metadata of `tail`. + ty::Param(_) | ty::Alias(..) => Err(tail), ty::Infer(ty::TyVar(_)) | ty::Bound(..) | ty::Placeholder(..) - | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`ptr_metadata_ty` applied to unexpected type: {:?} (tail = {:?})", self, tail) - } + | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!( + "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})" + ), + } + } + + /// Returns the type of metadata for (potentially fat) pointers to this type. + /// Causes an ICE if the metadata type cannot be determined. + pub fn ptr_metadata_ty( + self, + tcx: TyCtxt<'tcx>, + normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, + ) -> Ty<'tcx> { + match self.ptr_metadata_ty_or_tail(tcx, normalize) { + Ok(metadata) => metadata, + Err(tail) => bug!( + "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})" + ), } } @@ -2787,7 +2373,7 @@ impl<'tcx> Ty<'tcx> { // "Bound" types appear in canonical queries when the // closure type is not yet known - Bound(..) | Infer(_) => None, + Bound(..) | Param(_) | Infer(_) => None, Error(_) => Some(ty::ClosureKind::Fn), @@ -2830,6 +2416,7 @@ impl<'tcx> Ty<'tcx> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Error(_) => true, @@ -2893,7 +2480,7 @@ impl<'tcx> Ty<'tcx> { ty::Coroutine(..) | ty::CoroutineWitness(..) => false, // Might be, but not "trivial" so just giving the safe answer. - ty::Adt(..) | ty::Closure(..) => false, + ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false, // Needs normalization or revealing to determine, so no is the safe answer. ty::Alias(..) => false, @@ -2965,6 +2552,7 @@ impl<'tcx> Ty<'tcx> { | FnPtr(_) | Dynamic(_, _, _) | Closure(_, _) + | CoroutineClosure(_, _) | Coroutine(_, _) | CoroutineWitness(..) | Never @@ -3017,7 +2605,7 @@ mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; // tidy-alphabetical-start - static_assert_size!(RegionKind<'_>, 24); - static_assert_size!(TyKind<'_>, 32); + static_assert_size!(ty::RegionKind<'_>, 24); + static_assert_size!(ty::TyKind<'_>, 32); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8cc8abbe718d1..4feaeb0dd0523 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1119,6 +1119,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(..) | ty::Bound(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Dynamic(..) | ty::Foreign(_) | ty::Coroutine(..) @@ -1158,6 +1159,7 @@ impl<'tcx> Ty<'tcx> { ty::Adt(..) | ty::Bound(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Dynamic(..) | ty::Foreign(_) | ty::Coroutine(..) @@ -1280,7 +1282,11 @@ impl<'tcx> Ty<'tcx> { // Conservatively return `false` for all others... // Anonymous function types - ty::FnDef(..) | ty::Closure(..) | ty::Dynamic(..) | ty::Coroutine(..) => false, + ty::FnDef(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Dynamic(..) + | ty::Coroutine(..) => false, // Generic or inferred types // @@ -1424,6 +1430,7 @@ pub fn needs_drop_components<'tcx>( | ty::Placeholder(..) | ty::Infer(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) => Ok(smallvec![ty]), } @@ -1456,7 +1463,11 @@ pub fn is_trivially_const_drop(ty: Ty<'_>) -> bool { // Not trivial because they have components, and instead of looking inside, // we'll just perform trait selection. - ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Adt(..) => false, + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Adt(..) => false, ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 9050716db9d38..46c26241c3e78 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -189,6 +189,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } ty::Adt(_, args) | ty::Closure(_, args) + | ty::CoroutineClosure(_, args) | ty::Coroutine(_, args) | ty::CoroutineWitness(_, args) | ty::FnDef(_, args) => { diff --git a/compiler/rustc_middle/src/util/common.rs b/compiler/rustc_middle/src/util/common.rs index df101a2f6e4c6..dd3a36c7bf853 100644 --- a/compiler/rustc_middle/src/util/common.rs +++ b/compiler/rustc_middle/src/util/common.rs @@ -65,3 +65,19 @@ pub fn indenter() -> Indenter { debug!(">>"); Indenter { _cannot_construct_outside_of_this_module: () } } + +// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` +pub const fn c_name(name: &'static str) -> &'static str { + // FIXME Simplify the implementation once more `str` methods get const-stable. + // and inline into call site + let bytes = name.as_bytes(); + let mut i = bytes.len(); + while i > 0 && bytes[i - 1] != b':' { + i = i - 1; + } + let (_, bytes) = bytes.split_at(i); + match std::str::from_utf8(bytes) { + Ok(name) => name, + Err(_) => name, + } +} diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 9631b72f20c54..8a6ccdb857829 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -107,8 +107,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed = .note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior .label = use of extern static -mir_build_float_pattern = floating-point types cannot be used in patterns - mir_build_indirect_structural_match = to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]` @@ -232,6 +230,10 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa .note = mutating layout constrained fields cannot statically be checked for valid values .label = mutation of layout constrained field +mir_build_nan_pattern = cannot use NaN in patterns + .note = NaNs compare inequal to everything, even themselves, so this pattern would never match + .help = try using the `is_nan` method instead + mir_build_non_const_path = runtime values cannot be referenced in patterns mir_build_non_empty_never_pattern = diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 6e8af7bb6df6c..c77f4a06d0569 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -483,6 +483,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { UpvarArgs::Closure(args) => { Box::new(AggregateKind::Closure(closure_id.to_def_id(), args)) } + UpvarArgs::CoroutineClosure(args) => { + Box::new(AggregateKind::CoroutineClosure(closure_id.to_def_id(), args)) + } }; block.and(Rvalue::Aggregate(result, operands)) } diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 065c93e86a866..dba8e8b649926 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -40,43 +40,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: &mut Candidate<'pat, 'tcx>, ) -> bool { - // repeatedly simplify match pairs until fixed point is reached debug!("{candidate:#?}"); - - // existing_bindings and new_bindings exists to keep the semantics in order. - // Reversing the binding order for bindings after `@` changes the binding order in places - // it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)` + // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the + // bindings in `pat` before `x`. E.g. (#69971): + // + // struct NonCopyStruct { + // copy_field: u32, + // } + // + // fn foo1(x: NonCopyStruct) { + // let y @ NonCopyStruct { copy_field: z } = x; + // // the above should turn into + // let z = x.copy_field; + // let y = x; + // } // - // To avoid this, the binding occurs in the following manner: - // * the bindings for one iteration of the following loop occurs in order (i.e. left to - // right) - // * the bindings from the previous iteration of the loop is prepended to the bindings from - // the current iteration (in the implementation this is done by mem::swap and extend) - // * after all iterations, these new bindings are then appended to the bindings that were - // preexisting (i.e. `candidate.binding` when the function was called). + // We can't just reverse the binding order, because we must preserve pattern-order + // otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first, + // and bindings at the same depth stay in source order. + // + // To do this, every time around the loop we prepend the newly found bindings to the + // bindings we already had. // // example: // candidate.bindings = [1, 2, 3] - // binding in iter 1: [4, 5] - // binding in iter 2: [6, 7] + // bindings in iter 1: [4, 5] + // bindings in iter 2: [6, 7] // - // final binding: [1, 2, 3, 6, 7, 4, 5] - let mut existing_bindings = mem::take(&mut candidate.bindings); - let mut new_bindings = Vec::new(); + // final bindings: [6, 7, 4, 5, 1, 2, 3] + let mut accumulated_bindings = mem::take(&mut candidate.bindings); + // Repeatedly simplify match pairs until fixed point is reached loop { - let match_pairs = mem::take(&mut candidate.match_pairs); - - if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = - &*match_pairs - { - existing_bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut existing_bindings); - candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); - return true; - } - let mut changed = false; - for match_pair in match_pairs { + for match_pair in mem::take(&mut candidate.match_pairs) { match self.simplify_match_pair(match_pair, candidate) { Ok(()) => { changed = true; @@ -86,36 +82,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } } - // Avoid issue #69971: the binding order should be right to left if there are more - // bindings after `@` to please the borrow checker - // Ex - // struct NonCopyStruct { - // copy_field: u32, - // } - // - // fn foo1(x: NonCopyStruct) { - // let y @ NonCopyStruct { copy_field: z } = x; - // // the above should turn into - // let z = x.copy_field; - // let y = x; - // } - candidate.bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut new_bindings); + + // This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings + candidate.bindings.extend_from_slice(&accumulated_bindings); + mem::swap(&mut candidate.bindings, &mut accumulated_bindings); candidate.bindings.clear(); if !changed { - existing_bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut existing_bindings); - // Move or-patterns to the end, because they can result in us - // creating additional candidates, so we want to test them as - // late as possible. - candidate - .match_pairs - .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. })); - debug!(simplified = ?candidate, "simplify_candidate"); - return false; // if we were not able to simplify any, done. + // If we were not able to simplify anymore, done. + break; } } + + // Store computed bindings back in `candidate`. + mem::swap(&mut candidate.bindings, &mut accumulated_bindings); + + let did_expand_or = + if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = + &*candidate.match_pairs + { + candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); + candidate.match_pairs.clear(); + true + } else { + false + }; + + // Move or-patterns to the end, because they can result in us + // creating additional candidates, so we want to test them as + // late as possible. + candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. })); + debug!(simplified = ?candidate, "simplify_candidate"); + + did_expand_or } /// Given `candidate` that has a single or-pattern for its match-pairs, @@ -271,7 +270,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index || { - self.tcx.features().exhaustive_patterns + (self.tcx.features().exhaustive_patterns + || self.tcx.features().min_exhaustive_patterns) && !v .inhabited_predicate(self.tcx, adt_def) .instantiate(self.tcx, args) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 714c5f2686eb5..2b1a9fef360c0 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -495,7 +495,7 @@ fn construct_fn<'tcx>( args.as_coroutine().yield_ty(), args.as_coroutine().resume_ty(), ))), - ty::Closure(..) | ty::FnDef(..) => None, + ty::Closure(..) | ty::CoroutineClosure(..) | ty::FnDef(..) => None, ty => span_bug!(span_with_body, "unexpected type of body: {ty:?}"), }; @@ -666,7 +666,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - let yield_ty = args.yield_ty(); let return_ty = args.return_ty(); ( - vec![closure_ty, args.resume_ty()], + vec![closure_ty, resume_ty], return_ty, Some(Box::new(CoroutineInfo::initial( tcx.coroutine_kind(def_id).unwrap(), @@ -675,8 +675,39 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - ))), ) } - _ => { - span_bug!(span, "expected type of closure body to be a closure or coroutine"); + ty::CoroutineClosure(did, args) => { + let args = args.as_coroutine_closure(); + let sig = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + args.coroutine_closure_sig(), + ); + let self_ty = match args.kind() { + ty::ClosureKind::Fn => { + Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty) + } + ty::ClosureKind::FnMut => { + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty) + } + ty::ClosureKind::FnOnce => closure_ty, + }; + ( + [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()).collect(), + sig.to_coroutine( + tcx, + args.parent_args(), + args.kind_ty(), + tcx.coroutine_for_closure(*did), + Ty::new_error(tcx, guar), + ), + None, + ) + } + ty::Error(_) => (vec![closure_ty, closure_ty], closure_ty, None), + kind => { + span_bug!( + span, + "expected type of closure body to be a closure or coroutine, got {kind:?}" + ); } } } @@ -822,6 +853,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let upvar_args = match closure_ty.kind() { ty::Closure(_, args) => ty::UpvarArgs::Closure(args), ty::Coroutine(_, args) => ty::UpvarArgs::Coroutine(args), + ty::CoroutineClosure(_, args) => ty::UpvarArgs::CoroutineClosure(args), _ => return, }; diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 6827797df372c..2d3669487718b 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -655,7 +655,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let drops = if destination.is_some() { &mut self.scopes.breakable_scopes[break_index].break_drops } else { - self.scopes.breakable_scopes[break_index].continue_drops.as_mut().unwrap() + let Some(drops) = self.scopes.breakable_scopes[break_index].continue_drops.as_mut() + else { + self.tcx.dcx().span_delayed_bug( + source_info.span, + "unlabelled `continue` within labelled block", + ); + self.cfg.terminate(block, source_info, TerminatorKind::Unreachable); + + return self.cfg.start_new_block().unit(); + }; + drops }; let drop_idx = self.scopes.scopes[scope_index + 1..] diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 422549755d1e1..8688c58906331 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -583,7 +583,7 @@ impl UnsafeOpKind { suggest_unsafe_block: bool, ) { let parent_id = tcx.hir().get_parent_item(hir_id); - let parent_owner = tcx.hir().owner(parent_id); + let parent_owner = tcx.hir_owner_node(parent_id); let should_suggest = parent_owner.fn_sig().is_some_and(|sig| sig.header.is_unsafe()); let unsafe_not_inherited_note = if should_suggest { suggest_unsafe_block.then(|| { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3c1ba26a50309..0bc5fe6ef89ac 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage, + IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -420,10 +420,7 @@ pub struct UnsafeNotInheritedLintNote { } impl AddToDiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); let body_start = self.body_span.shrink_to_lo(); let body_end = self.body_span.shrink_to_hi(); @@ -780,9 +777,14 @@ pub struct UnsizedPattern<'tcx> { pub non_sm_ty: Ty<'tcx>, } -#[derive(LintDiagnostic)] -#[diag(mir_build_float_pattern)] -pub struct FloatPattern; +#[derive(Diagnostic)] +#[diag(mir_build_nan_pattern)] +#[note] +#[help] +pub struct NaNPattern { + #[primary_span] + pub span: Span, +} #[derive(LintDiagnostic)] #[diag(mir_build_pointer_pattern)] @@ -861,10 +863,7 @@ pub struct Variant { } impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index a3d88b1269686..43e44b47e3f96 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -1,6 +1,9 @@ //! Construction of MIR from HIR. //! //! This crate also contains the match exhaustiveness and usefulness checking. + +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(box_patterns)] diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 337493d15deca..508936be29d71 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -72,15 +72,14 @@ pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id)) && let Some(drop_trait) = tcx.lang_items().drop_trait() && drop_trait == trait_ref.instantiate_identity().def_id + // avoid erroneous `Drop` impls from causing ICEs below + && let sig = tcx.fn_sig(def_id).instantiate_identity() + && sig.inputs().skip_binder().len() == 1 { // It was. Now figure out for what type `Drop` is implemented and then // check for recursion. - if let ty::Ref(_, dropped_ty, _) = tcx - .liberate_late_bound_regions( - def_id.to_def_id(), - tcx.fn_sig(def_id).instantiate_identity().input(0), - ) - .kind() + if let ty::Ref(_, dropped_ty, _) = + tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind() { check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty }); } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 22094c112fc18..35adcc33480ca 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -556,6 +556,9 @@ impl<'tcx> Cx<'tcx> { ty::Coroutine(def_id, args) => { (def_id, UpvarArgs::Coroutine(args), Some(tcx.coroutine_movability(def_id))) } + ty::CoroutineClosure(def_id, args) => { + (def_id, UpvarArgs::CoroutineClosure(args), None) + } _ => { span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 5d0bb3954ccc6..f4f591d15b933 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -127,10 +127,24 @@ impl<'tcx> Cx<'tcx> { ty::Coroutine(..) => { Param { ty: closure_ty, pat: None, ty_span: None, self_kind: None, hir_id: None } } - ty::Closure(_, closure_args) => { + ty::Closure(_, args) => { let closure_env_ty = self.tcx.closure_env_ty( closure_ty, - closure_args.as_closure().kind(), + args.as_closure().kind(), + self.tcx.lifetimes.re_erased, + ); + Param { + ty: closure_env_ty, + pat: None, + ty_span: None, + self_kind: None, + hir_id: None, + } + } + ty::CoroutineClosure(_, args) => { + let closure_env_ty = self.tcx.closure_env_ty( + closure_ty, + args.as_coroutine_closure().kind(), self.tcx.lifetimes.re_erased, ); Param { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index caf7f4227dbf8..692f4511bb807 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -291,7 +291,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { err = err.and(check_never_pattern(cx, pat)); }); err?; - Ok(cx.pattern_arena.alloc(cx.lower_pat(pat))) + Ok(self.pattern_arena.alloc(cx.lower_pat(pat))) } } @@ -388,7 +388,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { typeck_results: self.typeck_results, param_env: self.param_env, module: self.tcx.parent_module(self.lint_level).to_def_id(), - pattern_arena: self.pattern_arena, dropless_arena: self.dropless_arena, match_lint_level: self.lint_level, whole_match_span, @@ -666,7 +665,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // Emit an extra note if the first uncovered witness would be uninhabited // if we disregard visibility. - let witness_1_is_privately_uninhabited = if self.tcx.features().exhaustive_patterns + let witness_1_is_privately_uninhabited = if (self.tcx.features().exhaustive_patterns + || self.tcx.features().min_exhaustive_patterns) && let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, args) = witness_1.ty().kind() && adt.is_enum() diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 22305f03a769d..18a00724c3d0e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,5 +1,5 @@ +use rustc_apfloat::Float; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_index::Idx; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::Obligation; @@ -16,8 +16,8 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch, - NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, + IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, PointerPattern, + TypeNotStructural, UnionPattern, UnsizedPattern, }; impl<'a, 'tcx> PatCtxt<'a, 'tcx> { @@ -32,11 +32,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { cv: mir::Const<'tcx>, id: hir::HirId, span: Span, - check_body_for_struct_match_violation: Option, ) -> Box> { let infcx = self.tcx.infer_ctxt().build(); let mut convert = ConstToPat::new(self, id, span, infcx); - convert.to_pat(cv, check_body_for_struct_match_violation) + convert.to_pat(cv) } } @@ -102,11 +101,7 @@ impl<'tcx> ConstToPat<'tcx> { ty.is_structural_eq_shallow(self.infcx.tcx) } - fn to_pat( - &mut self, - cv: mir::Const<'tcx>, - check_body_for_struct_match_violation: Option, - ) -> Box> { + fn to_pat(&mut self, cv: mir::Const<'tcx>) -> Box> { trace!(self.treat_byte_string_as_slice); // This method is just a wrapper handling a validity check; the heavy lifting is // performed by the recursive `recur` method, which is not meant to be @@ -115,14 +110,6 @@ impl<'tcx> ConstToPat<'tcx> { // once indirect_structural_match is a full fledged error, this // level of indirection can be eliminated - let mir_structural_match_violation = check_body_for_struct_match_violation.map(|def_id| { - // `mir_const_qualif` must be called with the `DefId` of the item where the const is - // defined, not where it is declared. The difference is significant for associated - // constants. - self.tcx().mir_const_qualif(def_id).custom_eq - }); - debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation); - let have_valtree = matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_))); let inlined_const_as_pat = match cv { @@ -136,15 +123,15 @@ impl<'tcx> ConstToPat<'tcx> { | ty::ConstKind::Expr(_) => { span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind()) } - ty::ConstKind::Value(valtree) => self - .recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false)) - .unwrap_or_else(|_: FallbackToOpaqueConst| { + ty::ConstKind::Value(valtree) => { + self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| { Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Constant { value: cv }, }) - }), + }) + } }, mir::Const::Unevaluated(_, _) => { span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}") @@ -159,7 +146,12 @@ impl<'tcx> ConstToPat<'tcx> { if self.saw_const_match_error.get().is_none() { // If we were able to successfully convert the const to some pat (possibly with some // lints, but no errors), double-check that all types in the const implement - // `Structural` and `PartialEq`. + // `PartialEq`. Even if we have a valtree, we may have found something + // in there with non-structural-equality, meaning we match using `PartialEq` + // and we hence have to check that that impl exists. + // This is all messy but not worth cleaning up: at some point we'll emit + // a hard error when we don't have a valtree or when we find something in + // the valtree that is not structural; then this can all be made a lot simpler. let structural = traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty()); @@ -169,19 +161,12 @@ impl<'tcx> ConstToPat<'tcx> { structural ); - // This can occur because const qualification treats all associated constants as - // opaque, whereas `search_for_structural_match_violation` tries to monomorphize them - // before it runs. - // - // FIXME(#73448): Find a way to bring const qualification into parity with - // `search_for_structural_match_violation`. - if structural.is_none() && mir_structural_match_violation.unwrap_or(false) { - warn!("MIR const-checker found novel structural match violation. See #73448."); - return inlined_const_as_pat; - } - if let Some(non_sm_ty) = structural { if !self.type_has_partial_eq_impl(cv.ty()) { + // This is reachable and important even if we have a valtree: there might be + // non-structural things in a valtree, in which case we fall back to `PartialEq` + // comparison, in which case we better make sure the trait is implemented for + // each inner type (and not just for the surrounding type). let e = if let ty::Adt(def, ..) = non_sm_ty.kind() { if def.is_union() { let err = UnionPattern { span: self.span }; @@ -200,35 +185,18 @@ impl<'tcx> ConstToPat<'tcx> { // We errored. Signal that in the pattern, so that follow up errors can be silenced. let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); - } else if let ty::Adt(..) = cv.ty().kind() - && matches!(cv, mir::Const::Val(..)) - { - // This branch is only entered when the current `cv` is `mir::Const::Val`. - // This is because `mir::Const::ty` has already been handled by `Self::recur` - // and the invalid types may be ignored. + } else if !have_valtree { + // Not being structural prevented us from constructing a valtree, + // so this is definitely a case we want to reject. let err = TypeNotStructural { span: self.span, non_sm_ty }; let e = self.tcx().dcx().emit_err(err); let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); - } else if !self.saw_const_match_lint.get() { - if let Some(mir_structural_match_violation) = mir_structural_match_violation { - match non_sm_ty.kind() { - ty::Adt(..) if mir_structural_match_violation => { - self.tcx().emit_node_span_lint( - lint::builtin::INDIRECT_STRUCTURAL_MATCH, - self.id, - self.span, - IndirectStructuralMatch { non_sm_ty }, - ); - } - _ => { - debug!( - "`search_for_structural_match_violation` found one, but `CustomEq` was \ - not in the qualifs for that `const`" - ); - } - } - } + } else { + // This could be a violation in an inactive enum variant. + // Since we have a valtree, we trust that we have traversed the full valtree and + // complained about structural match violations there, so we don't + // have to check anything any more. } } else if !have_valtree && !self.saw_const_match_lint.get() { // The only way valtree construction can fail without the structural match @@ -298,7 +266,7 @@ impl<'tcx> ConstToPat<'tcx> { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. let ty = self.tcx().normalize_erasing_regions(self.param_env, ty); - Ok(FieldPat { field, pattern: self.recur(val, ty, false)? }) + Ok(FieldPat { field, pattern: self.recur(val, ty)? }) }) .collect() } @@ -309,7 +277,6 @@ impl<'tcx> ConstToPat<'tcx> { &self, cv: ValTree<'tcx>, ty: Ty<'tcx>, - mir_structural_match_violation: bool, ) -> Result>, FallbackToOpaqueConst> { let id = self.id; let span = self.span; @@ -317,16 +284,6 @@ impl<'tcx> ConstToPat<'tcx> { let param_env = self.param_env; let kind = match ty.kind() { - ty::Float(_) => { - self.saw_const_match_lint.set(true); - tcx.emit_node_span_lint( - lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - id, - span, - FloatPattern, - ); - return Err(FallbackToOpaqueConst); - } // If the type is not structurally comparable, just emit the constant directly, // causing the pattern match code to treat it opaquely. // FIXME: This code doesn't emit errors itself, the caller emits the errors. @@ -404,7 +361,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.recur(*val, *elem_ty, false)) + .map(|val| self.recur(*val, *elem_ty)) .collect::>()?, slice: None, suffix: Box::new([]), @@ -413,7 +370,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.recur(*val, *elem_ty, false)) + .map(|val| self.recur(*val, *elem_ty)) .collect::>()?, slice: None, suffix: Box::new([]), @@ -480,12 +437,28 @@ impl<'tcx> ConstToPat<'tcx> { _ => *pointee_ty, }; // References have the same valtree representation as their pointee. - let subpattern = self.recur(cv, pointee_ty, false)?; + let subpattern = self.recur(cv, pointee_ty)?; self.behind_reference.set(old); PatKind::Deref { subpattern } } } }, + ty::Float(flt) => { + let v = cv.unwrap_leaf(); + let is_nan = match flt { + ty::FloatTy::F32 => v.try_to_f32().unwrap().is_nan(), + ty::FloatTy::F64 => v.try_to_f64().unwrap().is_nan(), + }; + if is_nan { + // NaNs are not ever equal to anything so they make no sense as patterns. + // Also see . + let e = tcx.dcx().emit_err(NaNPattern { span }); + self.saw_const_match_error.set(Some(e)); + return Err(FallbackToOpaqueConst); + } else { + PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } + } + } ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => { // The raw pointers we see here have been "vetted" by valtree construction to be // just integers, so we simply allow them. @@ -505,25 +478,6 @@ impl<'tcx> ConstToPat<'tcx> { } }; - if self.saw_const_match_error.get().is_none() - && !self.saw_const_match_lint.get() - && mir_structural_match_violation - // FIXME(#73448): Find a way to bring const qualification into parity with - // `search_for_structural_match_violation` and then remove this condition. - - // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we - // could get `Option`, even though `Option` is annotated with derive. - && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, ty) - { - self.saw_const_match_lint.set(true); - tcx.emit_node_span_lint( - lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH, - id, - span, - NontrivialStructuralMatch { non_sm_ty }, - ); - } - Ok(Box::new(Pat { span, ty, kind })) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 2190ad14b5511..1a5cf13e28978 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -542,7 +542,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match const_value { Ok(const_) => { - let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id())); + let pattern = self.const_to_pat(const_, id, span); if !is_associated_const { return pattern; @@ -612,7 +612,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; if let Some(lit_input) = lit_input { match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return self.const_to_pat(Const::Ty(c), id, span, None).kind, + Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind, // If an error occurred, ignore that it's a literal // and leave reporting the error up to const eval of // the unevaluated constant below. @@ -635,17 +635,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { - let subpattern = self.const_to_pat( - Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), - id, - span, - None, - ); + let subpattern = + self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span); PatKind::InlineConstant { subpattern, def: def_id } } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) { - Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind, + Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span).kind, Err(ErrorHandled::TooGeneric(_)) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. let e = self.tcx.dcx().emit_err(ConstPatternDependsOnGenericParameter { span }); @@ -681,9 +677,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(constant) => { - self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind - } + Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind, Err(LitToConstError::Reported(e)) => PatKind::Error(e), Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 862876f53c76c..1b2f2cd9477fc 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -861,6 +861,9 @@ where let ty = self.place_ty(self.place); match ty.kind() { ty::Closure(_, args) => self.open_drop_for_tuple(args.as_closure().upvar_tys()), + ty::CoroutineClosure(_, args) => { + self.open_drop_for_tuple(args.as_coroutine_closure().upvar_tys()) + } // Note that `elaborate_drops` only drops the upvars of a coroutine, // and this is ok because `open_drop` here can only be reached // within that own coroutine's resume function. diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 23111cc319956..a4b58e5bfc128 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -4,8 +4,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 38ee26c5a876e..80e0d0baf5786 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -154,7 +154,8 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -177,7 +178,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { union_path.get_or_insert(base); } } - ty::Closure(_, _) | ty::Coroutine(_, _) | ty::Tuple(_) => (), + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::Tuple(_) => (), ty::Bool | ty::Char | ty::Int(_) @@ -425,7 +429,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {} + | Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::DebugAssertions, + _, + ) => {} } } diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 2802f5491be03..2b2af6ee7da3e 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -1149,6 +1149,12 @@ pub fn iter_fields<'tcx>( ty::Closure(_, args) => { iter_fields(args.as_closure().tupled_upvars_ty(), tcx, param_env, f); } + ty::Coroutine(_, args) => { + iter_fields(args.as_coroutine().tupled_upvars_ty(), tcx, param_env, f); + } + ty::CoroutineClosure(_, args) => { + iter_fields(args.as_coroutine_closure().tupled_upvars_ty(), tcx, param_env, f); + } _ => (), } } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index dfc7a9891f921..ba70a4453d659 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -39,7 +39,9 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), ty::Closure(..) => Abi::RustCall, + ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + ty::Error(_) => return, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 6c4c3917cb5ec..fbb626953835e 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -128,7 +128,9 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { ), } } - &AggregateKind::Closure(def_id, _) | &AggregateKind::Coroutine(def_id, _) => { + &AggregateKind::Closure(def_id, _) + | &AggregateKind::CoroutineClosure(def_id, _) + | &AggregateKind::Coroutine(def_id, _) => { let def_id = def_id.expect_local(); let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = self.tcx.mir_unsafety_check_result(def_id); diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index c49f92f4f859f..eba62aae60f75 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -34,7 +34,7 @@ pub(crate) macro throw_machine_stop_str($($tt:tt)*) {{ fn add_args( self: Box, - _: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagnosticArgValue), + _: &mut dyn FnMut(rustc_errors::DiagnosticArgName, rustc_errors::DiagnosticArgValue), ) {} } throw_machine_stop!(Zst) diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index aa22b8c7c58e0..04d0a4f303f25 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -541,12 +541,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } #[instrument(level = "trace", skip(self), ret)] - fn eval_rvalue( - &mut self, - rvalue: &Rvalue<'tcx>, - location: Location, - dest: &Place<'tcx>, - ) -> Option<()> { + fn eval_rvalue(&mut self, rvalue: &Rvalue<'tcx>, dest: &Place<'tcx>) -> Option<()> { if !dest.projection.is_empty() { return None; } @@ -607,7 +602,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { AggregateKind::Array(_) | AggregateKind::Tuple | AggregateKind::Closure(_, _) - | AggregateKind::Coroutine(_, _) => VariantIdx::new(0), + | AggregateKind::Coroutine(_, _) + | AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0), }, }, @@ -638,6 +634,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { NullOp::OffsetOf(fields) => { op_layout.offset_of_subfield(self, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into() } @@ -733,7 +730,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { _ if place.is_indirect() => {} ConstPropMode::NoPropagation => self.ensure_not_propagated(place.local), ConstPropMode::OnlyInsideOwnBlock | ConstPropMode::FullConstProp => { - if self.eval_rvalue(rvalue, location, place).is_none() { + if self.eval_rvalue(rvalue, place).is_none() { // Const prop failed, so erase the destination, ensuring that whatever happens // from here on, does not know about the previous value. // This is important in case we have diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index bde879f6067c5..297b2fa143de2 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -50,6 +50,9 @@ //! For coroutines with state 1 (returned) and state 2 (poisoned) it does nothing. //! Otherwise it drops all the values in scope at the last suspension point. +mod by_move_body; +pub use by_move_body::ByMoveBody; + use crate::abort_unwinding_calls; use crate::deref_separator::deref_finder; use crate::errors; diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs new file mode 100644 index 0000000000000..e40f4520671bb --- /dev/null +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -0,0 +1,159 @@ +//! A MIR pass which duplicates a coroutine's body and removes any derefs which +//! would be present for upvars that are taken by-ref. The result of which will +//! be a coroutine body that takes all of its upvars by-move, and which we stash +//! into the `CoroutineInfo` for all coroutines returned by coroutine-closures. + +use rustc_data_structures::fx::FxIndexSet; +use rustc_hir as hir; +use rustc_middle::mir::visit::MutVisitor; +use rustc_middle::mir::{self, dump_mir, MirPass}; +use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt}; +use rustc_target::abi::FieldIdx; + +pub struct ByMoveBody; + +impl<'tcx> MirPass<'tcx> for ByMoveBody { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { + let Some(coroutine_def_id) = body.source.def_id().as_local() else { + return; + }; + let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = + tcx.coroutine_kind(coroutine_def_id) + else { + return; + }; + let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; + if coroutine_ty.references_error() { + return; + } + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; + + let coroutine_kind = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(); + if coroutine_kind == ty::ClosureKind::FnOnce { + return; + } + + let mut by_ref_fields = FxIndexSet::default(); + let by_move_upvars = Ty::new_tup_from_iter( + tcx, + tcx.closure_captures(coroutine_def_id).iter().enumerate().map(|(idx, capture)| { + if capture.is_by_ref() { + by_ref_fields.insert(FieldIdx::from_usize(idx)); + } + capture.place.ty() + }), + ); + let by_move_coroutine_ty = Ty::new_coroutine( + tcx, + coroutine_def_id.to_def_id(), + ty::CoroutineArgs::new( + tcx, + ty::CoroutineArgsParts { + parent_args: args.as_coroutine().parent_args(), + kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnOnce), + resume_ty: args.as_coroutine().resume_ty(), + yield_ty: args.as_coroutine().yield_ty(), + return_ty: args.as_coroutine().return_ty(), + witness: args.as_coroutine().witness(), + tupled_upvars_ty: by_move_upvars, + }, + ) + .args, + ); + + let mut by_move_body = body.clone(); + MakeByMoveBody { tcx, by_ref_fields, by_move_coroutine_ty }.visit_body(&mut by_move_body); + dump_mir(tcx, false, "coroutine_by_move", &0, &by_move_body, |_, _| Ok(())); + by_move_body.source = mir::MirSource { + instance: InstanceDef::CoroutineKindShim { + coroutine_def_id: coroutine_def_id.to_def_id(), + target_kind: ty::ClosureKind::FnOnce, + }, + promoted: None, + }; + body.coroutine.as_mut().unwrap().by_move_body = Some(by_move_body); + + // If this is coming from an `AsyncFn` coroutine-closure, we must also create a by-mut body. + // This is actually just a copy of the by-ref body, but with a different self type. + // FIXME(async_closures): We could probably unify this with the by-ref body somehow. + if coroutine_kind == ty::ClosureKind::Fn { + let by_mut_coroutine_ty = Ty::new_coroutine( + tcx, + coroutine_def_id.to_def_id(), + ty::CoroutineArgs::new( + tcx, + ty::CoroutineArgsParts { + parent_args: args.as_coroutine().parent_args(), + kind_ty: Ty::from_closure_kind(tcx, ty::ClosureKind::FnMut), + resume_ty: args.as_coroutine().resume_ty(), + yield_ty: args.as_coroutine().yield_ty(), + return_ty: args.as_coroutine().return_ty(), + witness: args.as_coroutine().witness(), + tupled_upvars_ty: args.as_coroutine().tupled_upvars_ty(), + }, + ) + .args, + ); + let mut by_mut_body = body.clone(); + by_mut_body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty = by_mut_coroutine_ty; + dump_mir(tcx, false, "coroutine_by_mut", &0, &by_mut_body, |_, _| Ok(())); + by_mut_body.source = mir::MirSource { + instance: InstanceDef::CoroutineKindShim { + coroutine_def_id: coroutine_def_id.to_def_id(), + target_kind: ty::ClosureKind::FnMut, + }, + promoted: None, + }; + body.coroutine.as_mut().unwrap().by_mut_body = Some(by_mut_body); + } + } +} + +struct MakeByMoveBody<'tcx> { + tcx: TyCtxt<'tcx>, + by_ref_fields: FxIndexSet, + by_move_coroutine_ty: Ty<'tcx>, +} + +impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_place( + &mut self, + place: &mut mir::Place<'tcx>, + context: mir::visit::PlaceContext, + location: mir::Location, + ) { + if place.local == ty::CAPTURE_STRUCT_LOCAL + && !place.projection.is_empty() + && let mir::ProjectionElem::Field(idx, ty) = place.projection[0] + && self.by_ref_fields.contains(&idx) + { + let (begin, end) = place.projection[1..].split_first().unwrap(); + // FIXME(async_closures): I'm actually a bit surprised to see that we always + // initially deref the by-ref upvars. If this is not actually true, then we + // will at least get an ICE that explains why this isn't true :^) + assert_eq!(*begin, mir::ProjectionElem::Deref); + // Peel one ref off of the ty. + let peeled_ty = ty.builtin_deref(true).unwrap().ty; + *place = mir::Place { + local: place.local, + projection: self.tcx.mk_place_elems_from_iter( + [mir::ProjectionElem::Field(idx, peeled_ty)] + .into_iter() + .chain(end.iter().copied()), + ), + }; + } + self.super_place(place, context, location); + } + + fn visit_local_decl(&mut self, local: mir::Local, local_decl: &mut mir::LocalDecl<'tcx>) { + // Replace the type of the self arg. + if local == ty::CAPTURE_STRUCT_LOCAL { + local_decl.ty = self.by_move_coroutine_ty; + } + } +} diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 8c11dea5d4ee6..9a1d8bae6b410 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -1,4 +1,5 @@ -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::captures::Captures; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::WithNumNodes; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -38,19 +39,27 @@ impl Debug for BcbCounter { } } +#[derive(Debug)] +pub(super) enum CounterIncrementSite { + Node { bcb: BasicCoverageBlock }, + Edge { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock }, +} + /// Generates and stores coverage counter and coverage expression information /// associated with nodes/edges in the BCB graph. pub(super) struct CoverageCounters { - next_counter_id: CounterId, + /// List of places where a counter-increment statement should be injected + /// into MIR, each with its corresponding counter ID. + counter_increment_sites: IndexVec, /// Coverage counters/expressions that are associated with individual BCBs. bcb_counters: IndexVec>, /// Coverage counters/expressions that are associated with the control-flow /// edge between two BCBs. /// - /// The iteration order of this map can affect the precise contents of MIR, - /// so we use `FxIndexMap` to avoid query stability hazards. - bcb_edge_counters: FxIndexMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, + /// We currently don't iterate over this map, but if we do in the future, + /// switch it back to `FxIndexMap` to avoid query stability hazards. + bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, /// Tracks which BCBs have a counter associated with some incoming edge. /// Only used by assertions, to verify that BCBs with incoming edge /// counters do not have their own physical counters (expressions are allowed). @@ -71,9 +80,9 @@ impl CoverageCounters { let num_bcbs = basic_coverage_blocks.num_nodes(); let mut this = Self { - next_counter_id: CounterId::START, + counter_increment_sites: IndexVec::new(), bcb_counters: IndexVec::from_elem_n(None, num_bcbs), - bcb_edge_counters: FxIndexMap::default(), + bcb_edge_counters: FxHashMap::default(), bcb_has_incoming_edge_counters: BitSet::new_empty(num_bcbs), expressions: IndexVec::new(), }; @@ -84,8 +93,8 @@ impl CoverageCounters { this } - fn make_counter(&mut self) -> BcbCounter { - let id = self.next_counter(); + fn make_counter(&mut self, site: CounterIncrementSite) -> BcbCounter { + let id = self.counter_increment_sites.push(site); BcbCounter::Counter { id } } @@ -103,15 +112,8 @@ impl CoverageCounters { self.make_expression(lhs, Op::Add, rhs) } - /// Counter IDs start from one and go up. - fn next_counter(&mut self) -> CounterId { - let next = self.next_counter_id; - self.next_counter_id = self.next_counter_id + 1; - next - } - pub(super) fn num_counters(&self) -> usize { - self.next_counter_id.as_usize() + self.counter_increment_sites.len() } #[cfg(test)] @@ -171,22 +173,26 @@ impl CoverageCounters { self.bcb_counters[bcb] } - pub(super) fn bcb_node_counters( + /// Returns an iterator over all the nodes/edges in the coverage graph that + /// should have a counter-increment statement injected into MIR, along with + /// each site's corresponding counter ID. + pub(super) fn counter_increment_sites( &self, - ) -> impl Iterator { - self.bcb_counters - .iter_enumerated() - .filter_map(|(bcb, counter_kind)| Some((bcb, counter_kind.as_ref()?))) + ) -> impl Iterator { + self.counter_increment_sites.iter_enumerated() } - /// For each edge in the BCB graph that has an associated counter, yields - /// that edge's *from* and *to* nodes, and its counter. - pub(super) fn bcb_edge_counters( + /// Returns an iterator over the subset of BCB nodes that have been associated + /// with a counter *expression*, along with the ID of that expression. + pub(super) fn bcb_nodes_with_coverage_expressions( &self, - ) -> impl Iterator { - self.bcb_edge_counters - .iter() - .map(|(&(from_bcb, to_bcb), counter_kind)| (from_bcb, to_bcb, counter_kind)) + ) -> impl Iterator + Captures<'_> { + self.bcb_counters.iter_enumerated().filter_map(|(bcb, &counter_kind)| match counter_kind { + // Yield the BCB along with its associated expression ID. + Some(BcbCounter::Expression { id }) => Some((bcb, id)), + // This BCB is associated with a counter or nothing, so skip it. + Some(BcbCounter::Counter { .. }) | None => None, + }) } pub(super) fn into_expressions(self) -> IndexVec { @@ -339,7 +345,8 @@ impl<'a> MakeBcbCounters<'a> { // program results in a tight infinite loop, but it should still compile. let one_path_to_target = !self.basic_coverage_blocks.bcb_has_multiple_in_edges(bcb); if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { - let counter_kind = self.coverage_counters.make_counter(); + let counter_kind = + self.coverage_counters.make_counter(CounterIncrementSite::Node { bcb }); if one_path_to_target { debug!("{bcb:?} gets a new counter: {counter_kind:?}"); } else { @@ -401,7 +408,8 @@ impl<'a> MakeBcbCounters<'a> { } // Make a new counter to count this edge. - let counter_kind = self.coverage_counters.make_counter(); + let counter_kind = + self.coverage_counters.make_counter(CounterIncrementSite::Edge { from_bcb, to_bcb }); debug!("Edge {from_bcb:?}->{to_bcb:?} gets a new counter: {counter_kind:?}"); self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind) } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index ad5fcc3acf12f..4c5be0a3f4bed 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -7,7 +7,7 @@ mod spans; #[cfg(test)] mod tests; -use self::counters::{BcbCounter, CoverageCounters}; +use self::counters::{CounterIncrementSite, CoverageCounters}; use self::graph::{BasicCoverageBlock, CoverageGraph}; use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans}; @@ -155,61 +155,52 @@ fn inject_coverage_statements<'tcx>( bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool, coverage_counters: &CoverageCounters, ) { - // Process the counters associated with BCB nodes. - for (bcb, counter_kind) in coverage_counters.bcb_node_counters() { - let do_inject = match counter_kind { - // Counter-increment statements always need to be injected. - BcbCounter::Counter { .. } => true, - // The only purpose of expression-used statements is to detect - // when a mapping is unreachable, so we only inject them for - // expressions with one or more mappings. - BcbCounter::Expression { .. } => bcb_has_coverage_spans(bcb), - }; - if do_inject { - inject_statement( - mir_body, - make_mir_coverage_kind(counter_kind), - basic_coverage_blocks[bcb].leader_bb(), - ); - } - } - - // Process the counters associated with BCB edges. - for (from_bcb, to_bcb, counter_kind) in coverage_counters.bcb_edge_counters() { - let do_inject = match counter_kind { - // Counter-increment statements always need to be injected. - BcbCounter::Counter { .. } => true, - // BCB-edge expressions never have mappings, so they never need - // a corresponding statement. - BcbCounter::Expression { .. } => false, + // Inject counter-increment statements into MIR. + for (id, counter_increment_site) in coverage_counters.counter_increment_sites() { + // Determine the block to inject a counter-increment statement into. + // For BCB nodes this is just their first block, but for edges we need + // to create a new block between the two BCBs, and inject into that. + let target_bb = match *counter_increment_site { + CounterIncrementSite::Node { bcb } => basic_coverage_blocks[bcb].leader_bb(), + CounterIncrementSite::Edge { from_bcb, to_bcb } => { + // Create a new block between the last block of `from_bcb` and + // the first block of `to_bcb`. + let from_bb = basic_coverage_blocks[from_bcb].last_bb(); + let to_bb = basic_coverage_blocks[to_bcb].leader_bb(); + + let new_bb = inject_edge_counter_basic_block(mir_body, from_bb, to_bb); + debug!( + "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \ + requires a new MIR BasicBlock {new_bb:?} for counter increment {id:?}", + ); + new_bb + } }; - if !do_inject { - continue; - } - - // We need to inject a coverage statement into a new BB between the - // last BB of `from_bcb` and the first BB of `to_bcb`. - let from_bb = basic_coverage_blocks[from_bcb].last_bb(); - let to_bb = basic_coverage_blocks[to_bcb].leader_bb(); - let new_bb = inject_edge_counter_basic_block(mir_body, from_bb, to_bb); - debug!( - "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \ - requires a new MIR BasicBlock {new_bb:?} for edge counter {counter_kind:?}", - ); - - // Inject a counter into the newly-created BB. - inject_statement(mir_body, make_mir_coverage_kind(counter_kind), new_bb); + inject_statement(mir_body, CoverageKind::CounterIncrement { id }, target_bb); } -} -fn make_mir_coverage_kind(counter_kind: &BcbCounter) -> CoverageKind { - match *counter_kind { - BcbCounter::Counter { id } => CoverageKind::CounterIncrement { id }, - BcbCounter::Expression { id } => CoverageKind::ExpressionUsed { id }, + // For each counter expression that is directly associated with at least one + // span, we inject an "expression-used" statement, so that coverage codegen + // can check whether the injected statement survived MIR optimization. + // (BCB edges can't have spans, so we only need to process BCB nodes here.) + // + // See the code in `rustc_codegen_llvm::coverageinfo::map_data` that deals + // with "expressions seen" and "zero terms". + for (bcb, expression_id) in coverage_counters + .bcb_nodes_with_coverage_expressions() + .filter(|&(bcb, _)| bcb_has_coverage_spans(bcb)) + { + inject_statement( + mir_body, + CoverageKind::ExpressionUsed { id: expression_id }, + basic_coverage_blocks[bcb].leader_bb(), + ); } } +/// Given two basic blocks that have a control-flow edge between them, creates +/// and returns a new block that sits between those blocks. fn inject_edge_counter_basic_block( mir_body: &mut mir::Body<'_>, from_bb: BasicBlock, @@ -394,7 +385,9 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { struct ExtractedHirInfo { function_source_hash: u64, is_async_fn: bool, - fn_sig_span: Span, + /// The span of the function's signature, extended to the start of `body_span`. + /// Must have the same context and filename as the body span. + fn_sig_span_extended: Option, body_span: Span, } @@ -407,13 +400,25 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir hir::map::associated_body(hir_node).expect("HIR node is a function with body"); let hir_body = tcx.hir().body(fn_body_id); - let is_async_fn = hir_node.fn_sig().is_some_and(|fn_sig| fn_sig.header.is_async()); - let body_span = get_body_span(tcx, hir_body, def_id); + let maybe_fn_sig = hir_node.fn_sig(); + let is_async_fn = maybe_fn_sig.is_some_and(|fn_sig| fn_sig.header.is_async()); + + let mut body_span = hir_body.value.span; + + use rustc_hir::{Closure, Expr, ExprKind, Node}; + // Unexpand a closure's body span back to the context of its declaration. + // This helps with closure bodies that consist of just a single bang-macro, + // and also with closure bodies produced by async desugaring. + if let Node::Expr(&Expr { kind: ExprKind::Closure(&Closure { fn_decl_span, .. }), .. }) = + hir_node + { + body_span = body_span.find_ancestor_in_same_ctxt(fn_decl_span).unwrap_or(body_span); + } // The actual signature span is only used if it has the same context and // filename as the body, and precedes the body. - let maybe_fn_sig_span = hir_node.fn_sig().map(|fn_sig| fn_sig.span); - let fn_sig_span = maybe_fn_sig_span + let fn_sig_span_extended = maybe_fn_sig + .map(|fn_sig| fn_sig.span) .filter(|&fn_sig_span| { let source_map = tcx.sess.source_map(); let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo()); @@ -423,39 +428,15 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir && file_idx(fn_sig_span) == file_idx(body_span) }) // If so, extend it to the start of the body span. - .map(|fn_sig_span| fn_sig_span.with_hi(body_span.lo())) - // Otherwise, create a dummy signature span at the start of the body. - .unwrap_or_else(|| body_span.shrink_to_lo()); + .map(|fn_sig_span| fn_sig_span.with_hi(body_span.lo())); let function_source_hash = hash_mir_source(tcx, hir_body); - ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span } -} - -fn get_body_span<'tcx>( - tcx: TyCtxt<'tcx>, - hir_body: &rustc_hir::Body<'tcx>, - def_id: LocalDefId, -) -> Span { - let mut body_span = hir_body.value.span; - - if tcx.is_closure_or_coroutine(def_id.to_def_id()) { - // If the current function is a closure, and its "body" span was created - // by macro expansion or compiler desugaring, try to walk backwards to - // the pre-expansion call site or body. - body_span = body_span.source_callsite(); - } - - body_span + ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span_extended, body_span } } fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 { // FIXME(cjgillot) Stop hashing HIR manually here. let owner = hir_body.id().hir_id.owner; - tcx.hir_owner_nodes(owner) - .unwrap() - .opt_hash_including_bodies - .unwrap() - .to_smaller_hash() - .as_u64() + tcx.hir_owner_nodes(owner).opt_hash_including_bodies.unwrap().to_smaller_hash().as_u64() } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index dee6a3b7143f5..d3d0c7bcc9501 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -3,7 +3,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir; use rustc_span::{BytePos, Span, DUMMY_SP}; -use super::graph::{BasicCoverageBlock, CoverageGraph}; +use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; use crate::coverage::ExtractedHirInfo; mod from_mir; @@ -46,13 +46,26 @@ pub(super) fn generate_coverage_spans( ) -> Option { let mut mappings = vec![]; - let sorted_spans = - from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks); - let coverage_spans = SpansRefiner::refine_sorted_spans(basic_coverage_blocks, sorted_spans); - mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| { - // Each span produced by the generator represents an ordinary code region. - BcbMapping { kind: BcbMappingKind::Code(bcb), span } - })); + if hir_info.is_async_fn { + // An async function desugars into a function that returns a future, + // with the user code wrapped in a closure. Any spans in the desugared + // outer function will be unhelpful, so just keep the signature span + // and ignore all of the spans in the MIR body. + if let Some(span) = hir_info.fn_sig_span_extended { + mappings.push(BcbMapping { kind: BcbMappingKind::Code(START_BCB), span }); + } + } else { + let sorted_spans = from_mir::mir_to_initial_sorted_coverage_spans( + mir_body, + hir_info, + basic_coverage_blocks, + ); + let coverage_spans = SpansRefiner::refine_sorted_spans(basic_coverage_blocks, sorted_spans); + mappings.extend(coverage_spans.into_iter().map(|CoverageSpan { bcb, span, .. }| { + // Each span produced by the generator represents an ordinary code region. + BcbMapping { kind: BcbMappingKind::Code(bcb), span } + })); + } if mappings.is_empty() { return None; diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 8d8e8e6132743..01fae7c0bec86 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -23,25 +23,21 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, ) -> Vec { - let &ExtractedHirInfo { is_async_fn, fn_sig_span, body_span, .. } = hir_info; - - let mut initial_spans = vec![SpanFromMir::for_fn_sig(fn_sig_span)]; - - if is_async_fn { - // An async function desugars into a function that returns a future, - // with the user code wrapped in a closure. Any spans in the desugared - // outer function will be unhelpful, so just keep the signature span - // and ignore all of the spans in the MIR body. - } else { - for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { - initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data)); - } + let &ExtractedHirInfo { body_span, .. } = hir_info; - // If no spans were extracted from the body, discard the signature span. - // FIXME: This preserves existing behavior; consider getting rid of it. - if initial_spans.len() == 1 { - initial_spans.clear(); - } + let mut initial_spans = vec![]; + + for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { + initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data)); + } + + // Only add the signature span if we found at least one span in the body. + if !initial_spans.is_empty() { + // If there is no usable signature span, add a fake one (before refinement) + // to avoid an ugly gap between the body start and the first real span. + // FIXME: Find a more principled way to solve this problem. + let fn_sig_span = hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo()); + initial_spans.push(SpanFromMir::for_fn_sig(fn_sig_span)); } initial_spans.sort_by(|a, b| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb)); @@ -160,7 +156,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( fn is_closure_or_coroutine(statement: &Statement<'_>) -> bool { match statement.kind { StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind { - AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _) => true, + AggregateKind::Closure(_, _) + | AggregateKind::Coroutine(_, _) + | AggregateKind::CoroutineClosure(..) => true, _ => false, }, _ => false, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index ad12bce9b0232..6a37047a69387 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -696,6 +696,7 @@ fn try_write_constant<'tcx>( | ty::Bound(..) | ty::Placeholder(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"), diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index c47abb4fcb478..663abbece851d 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -26,7 +26,6 @@ fn abi_can_unwind(abi: Abi) -> bool { PtxKernel | Msp430Interrupt | X86Interrupt - | AmdGpuKernel | EfiApi | AvrInterrupt | AvrNonBlockingInterrupt @@ -58,7 +57,9 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { let body_abi = match body_ty.kind() { ty::FnDef(..) => body_ty.fn_sig(tcx).abi(), ty::Closure(..) => Abi::RustCall, + ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + ty::Error(_) => return false, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 390ec3e1a36ac..36c441a394536 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -489,6 +489,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { NullOp::OffsetOf(fields) => { layout.offset_of_subfield(&self.ecx, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let imm = ImmTy::try_from_uint(val, usize_layout)?; @@ -861,9 +862,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let tcx = self.tcx; if fields.is_empty() { let is_zst = match *kind { - AggregateKind::Array(..) | AggregateKind::Tuple | AggregateKind::Closure(..) => { - true - } + AggregateKind::Array(..) + | AggregateKind::Tuple + | AggregateKind::Closure(..) + | AggregateKind::CoroutineClosure(..) => true, // Only enums can be non-ZST. AggregateKind::Adt(did, ..) => tcx.def_kind(did) != DefKind::Enum, // Coroutines are never ZST, as they at least contain the implicit states. @@ -885,7 +887,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { assert!(!fields.is_empty()); (AggregateTy::Tuple, FIRST_VARIANT) } - AggregateKind::Closure(did, substs) | AggregateKind::Coroutine(did, substs) => { + AggregateKind::Closure(did, substs) + | AggregateKind::CoroutineClosure(did, substs) + | AggregateKind::Coroutine(did, substs) => { (AggregateTy::Def(did, substs), FIRST_VARIANT) } AggregateKind::Adt(did, variant_index, substs, _, None) => { @@ -1228,8 +1232,8 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> { fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) { if let Operand::Move(place) = *operand - && let Some(local) = place.as_local() - && self.reused_locals.contains(local) + && !place.is_indirect_first_projection() + && self.reused_locals.contains(place.local) { *operand = Operand::Copy(place); } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 67668a216dee3..be19bd8349ed4 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -317,6 +317,8 @@ impl<'tcx> Inliner<'tcx> { | InstanceDef::ReifyShim(_) | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::ThreadLocalShim(..) @@ -1025,21 +1027,16 @@ fn try_instance_mir<'tcx>( tcx: TyCtxt<'tcx>, instance: InstanceDef<'tcx>, ) -> Result<&'tcx Body<'tcx>, &'static str> { - match instance { - ty::InstanceDef::DropGlue(_, Some(ty)) => match ty.kind() { - ty::Adt(def, args) => { - let fields = def.all_fields(); - for field in fields { - let field_ty = field.ty(tcx, args); - if field_ty.has_param() && field_ty.has_projections() { - return Err("cannot build drop shim for polymorphic type"); - } - } - - Ok(tcx.instance_mir(instance)) + if let ty::InstanceDef::DropGlue(_, Some(ty)) = instance + && let ty::Adt(def, args) = ty.kind() + { + let fields = def.all_fields(); + for field in fields { + let field_ty = field.ty(tcx, args); + if field_ty.has_param() && field_ty.has_projections() { + return Err("cannot build drop shim for polymorphic type"); } - _ => Ok(tcx.instance_mir(instance)), - }, - _ => Ok(tcx.instance_mir(instance)), + } } + Ok(tcx.instance_mir(instance)) } diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index d30e0bad81301..5b03bc361dd3c 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -87,6 +87,8 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceDef::ReifyShim(_) | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::ThreadLocalShim { .. } | InstanceDef::CloneShim(..) => {} diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a28db0defc993..f65eb5cbea938 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -2,10 +2,12 @@ use crate::simplify::simplify_duplicate_switch_targets; use rustc_middle::mir::*; +use rustc_middle::ty::layout; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt}; use rustc_span::symbol::Symbol; use rustc_target::abi::FieldIdx; +use rustc_target::spec::abi::Abi; pub struct InstSimplify; @@ -38,6 +40,7 @@ impl<'tcx> MirPass<'tcx> for InstSimplify { block.terminator.as_mut().unwrap(), &mut block.statements, ); + ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap()); simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); } } @@ -252,6 +255,28 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { terminator.kind = TerminatorKind::Goto { target: destination_block }; } + fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { + let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else { + return; + }; + + let Some((def_id, _)) = func.const_fn_def() else { + return; + }; + + let body_ty = self.tcx.type_of(def_id).skip_binder(); + let body_abi = match body_ty.kind() { + ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Coroutine(..) => Abi::Rust, + _ => bug!("unexpected body ty: {:?}", body_ty), + }; + + if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) { + *unwind = UnwindAction::Unreachable; + } + } + fn simplify_intrinsic_assert( &self, terminator: &mut Terminator<'tcx>, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 69f93fa3a0e21..8e5d69605aa35 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(const_type_name)] @@ -307,6 +305,10 @@ fn mir_const(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { &Lint(check_packed_ref::CheckPackedRef), &Lint(check_const_item_mutation::CheckConstItemMutation), &Lint(function_item_references::FunctionItemReferences), + // If this is an async closure's output coroutine, generate + // by-move and by-mut bodies if needed. We do this first so + // they can be optimized in lockstep with their parent bodies. + &coroutine::ByMoveBody, // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, &rustc_peek::SanityCheck, // Just a lint diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 897375e0e1645..f43b85173d428 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -21,6 +21,17 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { sym::unreachable => { terminator.kind = TerminatorKind::Unreachable; } + sym::debug_assertions => { + let target = target.unwrap(); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(NullOp::DebugAssertions, tcx.types.bool), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } sym::forget => { if let Some(target) = *target { block.statements.push(Statement { diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c1ef2b9f887fb..77478cc741d39 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -8,18 +8,10 @@ use crate::{lint::lint_body, validate, MirPass}; pub trait MirLint<'tcx> { fn name(&self) -> &'static str { // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirPass` const { let name = std::any::type_name::(); - let bytes = name.as_bytes(); - let mut i = bytes.len(); - while i > 0 && bytes[i - 1] != b':' { - i = i - 1; - } - let (_, bytes) = bytes.split_at(i); - match std::str::from_utf8(bytes) { - Ok(name) => name, - Err(_) => name, - } + rustc_middle::util::common::c_name(name) } } @@ -189,6 +181,15 @@ fn run_passes_inner<'tcx>( body.pass_count = 1; } + + if let Some(coroutine) = body.coroutine.as_mut() { + if let Some(by_move_body) = coroutine.by_move_body.as_mut() { + run_passes_inner(tcx, by_move_body, passes, phase_change, validate_each); + } + if let Some(by_mut_body) = coroutine.by_mut_body.as_mut() { + run_passes_inner(tcx, by_mut_body, passes, phase_change, validate_each); + } + } } pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index c00093ea27edd..577b8f2080fcd 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -446,6 +446,7 @@ impl<'tcx> Validator<'_, 'tcx> { NullOp::SizeOf => {} NullOp::AlignOf => {} NullOp::OffsetOf(_) => {} + NullOp::DebugAssertions => {} }, Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 34d57a45301d7..9a94cae338288 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -46,6 +46,7 @@ fn maybe_zst(ty: Ty<'_>) -> bool { ty::Adt(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Tuple(..) | ty::Alias(ty::Opaque, ..) => true, // definitely ZST diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 89414ce940e05..7b6de3a543955 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -3,8 +3,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt}; +use rustc_middle::ty::{GenericArgs, CAPTURE_STRUCT_LOCAL}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_index::{Idx, IndexVec}; @@ -66,11 +66,76 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut)) } + ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind, + } => match target_kind { + ty::ClosureKind::Fn => unreachable!("shouldn't be building shim for Fn"), + ty::ClosureKind::FnMut => { + // No need to optimize the body, it has already been optimized + // since we steal it from the `AsyncFn::call` body and just fix + // the return type. + return build_construct_coroutine_by_mut_shim(tcx, coroutine_closure_def_id); + } + ty::ClosureKind::FnOnce => { + build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id) + } + }, + + ty::InstanceDef::CoroutineKindShim { coroutine_def_id, target_kind } => match target_kind { + ty::ClosureKind::Fn => unreachable!(), + ty::ClosureKind::FnMut => { + return tcx + .optimized_mir(coroutine_def_id) + .coroutine_by_mut_body() + .unwrap() + .clone(); + } + ty::ClosureKind::FnOnce => { + return tcx + .optimized_mir(coroutine_def_id) + .coroutine_by_move_body() + .unwrap() + .clone(); + } + }, + ty::InstanceDef::DropGlue(def_id, ty) => { // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end // of this function. Is this intentional? if let Some(ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) { - let body = tcx.optimized_mir(*coroutine_def_id).coroutine_drop().unwrap(); + let coroutine_body = tcx.optimized_mir(*coroutine_def_id); + + let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind() + else { + bug!() + }; + + // If this is a regular coroutine, grab its drop shim. If this is a coroutine + // that comes from a coroutine-closure, and the kind ty differs from the "maximum" + // kind that it supports, then grab the appropriate drop shim. This ensures that + // the future returned by `<[coroutine-closure] as AsyncFnOnce>::call_once` will + // drop the coroutine-closure's upvars. + let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() { + coroutine_body.coroutine_drop().unwrap() + } else { + match args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap() { + ty::ClosureKind::Fn => { + unreachable!() + } + ty::ClosureKind::FnMut => coroutine_body + .coroutine_by_mut_body() + .unwrap() + .coroutine_drop() + .unwrap(), + ty::ClosureKind::FnOnce => coroutine_body + .coroutine_by_move_body() + .unwrap() + .coroutine_drop() + .unwrap(), + } + }; + let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args); debug!("make_shim({:?}) = {:?}", instance, body); @@ -981,3 +1046,114 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t let source = MirSource::from_instance(ty::InstanceDef::FnPtrAddrShim(def_id, self_ty)); new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) } + +fn build_construct_coroutine_by_move_shim<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_closure_def_id: DefId, +) -> Body<'tcx> { + let self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity(); + let ty::CoroutineClosure(_, args) = *self_ty.kind() else { + bug!(); + }; + + let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| { + tcx.mk_fn_sig( + [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()), + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.as_coroutine_closure().parent_args(), + tcx.coroutine_for_closure(coroutine_closure_def_id), + ty::ClosureKind::FnOnce, + tcx.lifetimes.re_erased, + args.as_coroutine_closure().tupled_upvars_ty(), + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + ), + sig.c_variadic, + sig.unsafety, + sig.abi, + ) + }); + let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig); + let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else { + bug!(); + }; + + let span = tcx.def_span(coroutine_closure_def_id); + let locals = local_decls_for_sig(&sig, span); + + let mut fields = vec![]; + for idx in 1..sig.inputs().len() { + fields.push(Operand::Move(Local::from_usize(idx + 1).into())); + } + for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() { + fields.push(Operand::Move(tcx.mk_place_field( + Local::from_usize(1).into(), + FieldIdx::from_usize(idx), + ty, + ))); + } + + let source_info = SourceInfo::outermost(span); + let rvalue = Rvalue::Aggregate( + Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)), + IndexVec::from_raw(fields), + ); + let stmt = Statement { + source_info, + kind: StatementKind::Assign(Box::new((Place::return_place(), rvalue))), + }; + let statements = vec![stmt]; + let start_block = BasicBlockData { + statements, + terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), + is_cleanup: false, + }; + + let source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind: ty::ClosureKind::FnOnce, + }); + + let body = + new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span); + dump_mir(tcx, false, "coroutine_closure_by_move", &0, &body, |_, _| Ok(())); + + body +} + +fn build_construct_coroutine_by_mut_shim<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_closure_def_id: DefId, +) -> Body<'tcx> { + let mut body = tcx.optimized_mir(coroutine_closure_def_id).clone(); + let coroutine_closure_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity(); + let ty::CoroutineClosure(_, args) = *coroutine_closure_ty.kind() else { + bug!(); + }; + let args = args.as_coroutine_closure(); + + body.local_decls[RETURN_PLACE].ty = + tcx.instantiate_bound_regions_with_erased(args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(coroutine_closure_def_id), + ty::ClosureKind::FnMut, + tcx.lifetimes.re_erased, + args.tupled_upvars_ty(), + args.coroutine_captures_by_ref_ty(), + ) + })); + body.local_decls[CAPTURE_STRUCT_LOCAL].ty = + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_closure_ty); + + body.source = MirSource::from_instance(ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind: ty::ClosureKind::FnMut, + }); + + body.pass_count = 0; + dump_mir(tcx, false, "coroutine_closure_by_mut", &0, &body, |_, _| Ok(())); + + body +} diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b86244e5a4bfd..3376af986531e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -983,6 +983,8 @@ fn visit_instance_use<'tcx>( | ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index b0cfa3568cad7..7f36ae91f1a03 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,8 +1,6 @@ #![feature(array_windows)] #![feature(is_sorted)] #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 7ff182381b835..5cfebcaa5a5f9 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -156,7 +156,7 @@ where placed }; - // Merge until we have at most `max_cgu_count` codegen units. + // Merge until we don't exceed the max CGU count. // `merge_codegen_units` is responsible for updating the CGU size // estimates. { @@ -620,6 +620,8 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::Virtual(..) @@ -783,6 +785,8 @@ fn mono_item_visibility<'tcx>( | InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } + | InstanceDef::ConstructCoroutineInClosureShim { .. } + | InstanceDef::CoroutineKindShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden, diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index db1aee1190359..42edbeaa622c2 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -332,7 +332,8 @@ impl, I: Interner> TypeFolder | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index aac8c0b310320..7c2ecf34c1754 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -22,6 +22,8 @@ parse_associated_static_item_not_allowed = associated `static` items are not all parse_async_block_in_2015 = `async` blocks are only allowed in Rust 2018 or later +parse_async_bound_modifier_in_2015 = `async` trait bounds are only allowed in Rust 2018 or later + parse_async_fn_in_2015 = `async fn` is not permitted in Rust 2015 .label = to use `async fn`, switch to Rust 2018 or later diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4e4bf9bdad98a..3c3a8d6fbb9c7 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,8 +3,8 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level, - SubdiagnosticMessage, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -1475,10 +1475,7 @@ pub(crate) struct FnTraitMissingParen { } impl AddToDiagnostic for FnTraitMissingParen { - fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { Applicability::MachineApplicable @@ -1588,6 +1585,15 @@ pub(crate) struct AsyncMoveBlockIn2015 { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_async_bound_modifier_in_2015)] +pub(crate) struct AsyncBoundModifierIn2015 { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub help: HelpUseLatestEdition, +} + #[derive(Diagnostic)] #[diag(parse_self_argument_pointer)] pub(crate) struct SelfArgumentPointer { diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 49e036c380133..5bd8bb72bd665 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,11 +1,13 @@ //! The main parser interface. +#![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![allow(internal_features)] #[macro_use] extern crate tracing; @@ -39,7 +41,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // uses a HOF to parse anything, and includes file and // `source_str`. -/// A variant of 'panictry!' that works on a `Vec` instead of a single +/// A variant of 'panictry!' that works on a `Vec` instead of a single /// `DiagnosticBuilder`. macro_rules! panictry_buffer { ($e:expr) => {{ diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9f748e2a3feb1..1a57474bac289 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2911,12 +2911,22 @@ impl<'a> Parser<'a> { Ok(arm) => arms.push(arm), Err(e) => { // Recover by skipping to the end of the block. - e.emit(); + let guar = e.emit(); self.recover_stmt(); let span = lo.to(self.token.span); if self.token == token::CloseDelim(Delimiter::Brace) { self.bump(); } + // Always push at least one arm to make the match non-empty + arms.push(Arm { + attrs: Default::default(), + pat: self.mk_pat(span, ast::PatKind::Err(guar)), + guard: None, + body: Some(self.mk_expr_err(span)), + span, + id: DUMMY_NODE_ID, + is_placeholder: false, + }); return Ok(self.mk_expr_with_attrs( span, ExprKind::Match(scrutinee, arms), @@ -3288,7 +3298,7 @@ impl<'a> Parser<'a> { } else { Applicability::MaybeIncorrect }; - err.span_suggestion_verbose(sugg_sp, msg, "=> ".to_string(), applicability); + err.span_suggestion_verbose(sugg_sp, msg, "=> ", applicability); } } err diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 48cf04f7790d0..e059e7074910a 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -148,7 +148,7 @@ impl<'a> Parser<'a> { .with_span_suggestion_verbose( mistyped_const_ident.span, "use the `const` keyword", - kw::Const.as_str(), + kw::Const, Applicability::MachineApplicable, ) .emit(); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9a77643f9510f..8050b34956ce9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1453,7 +1453,7 @@ impl<'a> Parser<'a> { err.span_suggestion_verbose( prev_span, "perhaps you meant to use `struct` here", - "struct".to_string(), + "struct", Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index a4fb92c67ac68..5fe54a536a7f1 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -3,19 +3,18 @@ use super::{Parser, PathStyle, TokenType}; use crate::errors::{ self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg, - InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType, - ReturnTypesUseThinArrow, + HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, + NestedCVariadicType, ReturnTypesUseThinArrow, }; 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; use rustc_ast::{ - self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, - GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, - TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, + self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, + GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, + TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; @@ -880,6 +879,24 @@ impl<'a> Parser<'a> { BoundConstness::Never }; + let asyncness = if self.token.span.at_least_rust_2018() && self.eat_keyword(kw::Async) { + self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span); + BoundAsyncness::Async(self.prev_token.span) + } else if self.may_recover() + && self.token.span.is_rust_2015() + && self.is_kw_followed_by_ident(kw::Async) + { + self.bump(); // eat `async` + self.dcx().emit_err(errors::AsyncBoundModifierIn2015 { + span: self.prev_token.span, + help: HelpUseLatestEdition::new(), + }); + self.sess.gated_spans.gate(sym::async_closure, self.prev_token.span); + BoundAsyncness::Async(self.prev_token.span) + } else { + BoundAsyncness::Normal + }; + let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) } else if self.eat(&token::Not) { @@ -889,7 +906,7 @@ impl<'a> Parser<'a> { BoundPolarity::Positive }; - Ok(TraitBoundModifiers { constness, polarity }) + Ok(TraitBoundModifiers { constness, asyncness, polarity }) } /// Parses a type bound according to: diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index d76ee161da6fd..0b65f400825ae 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -9,8 +9,6 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))) )] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index d41cc724408a4..648ef9d51deaa 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -323,9 +323,6 @@ passes_ffi_const_invalid_target = passes_ffi_pure_invalid_target = `#[ffi_pure]` may only be used on foreign functions -passes_ffi_returns_twice_invalid_target = - `#[ffi_returns_twice]` may only be used on foreign functions - passes_has_incoherent_inherent_impl = `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits. .label = only adts, extern types and traits are supported diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8f27d01794cc6..ec704dec352da 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -5,8 +5,10 @@ //! item. use crate::{errors, fluent_generated as fluent}; -use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem}; +use rustc_ast::{ast, AttrKind, AttrStyle, Attribute, LitKind}; +use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::StashKey; use rustc_errors::{Applicability, DiagCtxt, IntoDiagnosticArg, MultiSpan}; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; @@ -190,7 +192,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target), sym::ffi_const => self.check_ffi_const(attr.span, target), - sym::ffi_returns_twice => self.check_ffi_returns_twice(attr.span, target), sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -826,10 +827,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.doc_attr_str_error(meta, "keyword"); return false; } - match self.tcx.opt_hir_node(hir_id).and_then(|node| match node { + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, - }) { + }; + match item_kind { Some(ItemKind::Mod(module)) => { if !module.item_ids.is_empty() { self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() }); @@ -852,10 +854,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { - match self.tcx.opt_hir_node(hir_id).and_then(|node| match node { + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, - }) { + }; + match item_kind { Some(ItemKind::Impl(i)) => { let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) || if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind { @@ -1307,15 +1310,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_ffi_returns_twice(&self, attr_span: Span, target: Target) -> bool { - if target == Target::ForeignFn { - true - } else { - self.dcx().emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span }); - false - } - } - /// Warns against some misuses of `#[must_use]` fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool { if !matches!( @@ -2229,8 +2223,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } else { // special case when `#[macro_export]` is applied to a macro 2.0 - let (macro_definition, _) = - self.tcx.opt_hir_node(hir_id).unwrap().expect_item().expect_macro(); + let (macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); let is_decl_macro = !macro_definition.macro_rules; if is_decl_macro { @@ -2530,6 +2523,14 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { if attr.style == AttrStyle::Inner { for attr_to_check in ATTRS_TO_CHECK { if attr.has_name(*attr_to_check) { + if let AttrKind::Normal(ref p) = attr.kind + && let Some(diag) = tcx.dcx().steal_diagnostic( + p.item.path.span, + StashKey::UndeterminedMacroResolution, + ) + { + diag.cancel(); + } let item = tcx .hir() .items() diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 9be286744351f..e11102c459e42 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -4,6 +4,7 @@ // is dead. use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; +use hir::ItemKind; use rustc_data_structures::unord::UnordSet; use rustc_errors::MultiSpan; use rustc_hir as hir; @@ -14,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; use rustc_span::symbol::{sym, Symbol}; @@ -381,9 +382,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_item(self, item) } hir::ItemKind::ForeignMod { .. } => {} + hir::ItemKind::Trait(..) => { + for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) { + if let Some(local_def_id) = impl_def_id.as_local() + && let ItemKind::Impl(impl_ref) = + self.tcx.hir().expect_item(local_def_id).kind + { + // skip items + // mark dependent traits live + intravisit::walk_generics(self, impl_ref.generics); + // mark dependent parameters live + intravisit::walk_path(self, impl_ref.of_trait.unwrap().path); + } + } + + intravisit::walk_item(self, item) + } _ => intravisit::walk_item(self, item), }, Node::TraitItem(trait_item) => { + // mark corresponing ImplTerm live + let trait_item_id = trait_item.owner_id.to_def_id(); + if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) { + // mark the trait live + self.check_def_id(trait_id); + + for impl_id in self.tcx.all_impls(trait_id) { + if let Some(local_impl_id) = impl_id.as_local() + && let ItemKind::Impl(impl_ref) = + self.tcx.hir().expect_item(local_impl_id).kind + { + // mark self_ty live + intravisit::walk_ty(self, impl_ref.self_ty); + if let Some(&impl_item_id) = + self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id) + { + self.check_def_id(impl_item_id); + } + } + } + } intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { @@ -464,7 +502,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.lookup_and_handle_method(expr.hir_id); } hir::ExprKind::Field(ref lhs, ..) => { - self.handle_field_access(lhs, expr.hir_id); + if self.typeck_results().opt_field_index(expr.hir_id).is_some() { + self.handle_field_access(lhs, expr.hir_id); + } else { + self.tcx.dcx().span_delayed_bug(expr.span, "couldn't resolve index for field"); + } } hir::ExprKind::Struct(qpath, fields, _) => { let res = self.typeck_results().qpath_res(qpath, expr.hir_id); @@ -632,10 +674,6 @@ fn check_item<'tcx>( } } DefKind::Impl { of_trait } => { - if of_trait { - worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No)); - } - // get DefIds from another query let local_def_ids = tcx .associated_item_def_ids(id.owner_id) @@ -644,7 +682,11 @@ fn check_item<'tcx>( // And we access the Map here to get HirId from LocalDefId for id in local_def_ids { - if of_trait { + // for impl trait blocks, mark associate functions live if the trait is public + if of_trait + && (!matches!(tcx.def_kind(id), DefKind::AssocFn) + || tcx.local_visibility(id) == Visibility::Public) + { worklist.push((id, ComesFromAllowExpect::No)); } else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) { worklist.push((id, comes_from_allow)); @@ -675,7 +717,7 @@ fn check_trait_item( use hir::TraitItemKind::{Const, Fn}; if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); - if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) + if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) { @@ -944,7 +986,8 @@ impl<'tcx> DeadVisitor<'tcx> { | DefKind::TyAlias | DefKind::Enum | DefKind::Union - | DefKind::ForeignTy => self.warn_dead_code(def_id, "used"), + | DefKind::ForeignTy + | DefKind::Trait => self.warn_dead_code(def_id, "used"), DefKind::Struct => self.warn_dead_code(def_id, "constructed"), DefKind::Variant | DefKind::Field => bug!("should be handled specially"), _ => {} @@ -969,18 +1012,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { let module_items = tcx.hir_module_items(module); for item in module_items.items() { - if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind { - let mut dead_items = Vec::new(); - for item in impl_item.items { - let def_id = item.id.owner_id.def_id; - if !visitor.is_live_code(def_id) { - let name = tcx.item_name(def_id.to_def_id()); - let level = visitor.def_lint_level(def_id); + let def_kind = tcx.def_kind(item.owner_id); + + let mut dead_codes = Vec::new(); + // if we have diagnosed the trait, do not diagnose unused methods + if matches!(def_kind, DefKind::Impl { .. }) + || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) + { + for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { + // We have diagnosed unused methods in traits + if matches!(def_kind, DefKind::Impl { of_trait: true }) + && tcx.def_kind(def_id) == DefKind::AssocFn + || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn + { + continue; + } - dead_items.push(DeadItem { def_id, name, level }) + if let Some(local_def_id) = def_id.as_local() + && !visitor.is_live_code(local_def_id) + { + let name = tcx.item_name(def_id); + let level = visitor.def_lint_level(local_def_id); + dead_codes.push(DeadItem { def_id: local_def_id, name, level }); } } - visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, ReportOn::NamedField); + } + if !dead_codes.is_empty() { + visitor.warn_multiple(item.owner_id.def_id, "used", dead_codes, ReportOn::NamedField); } if !live_symbols.contains(&item.owner_id.def_id) { @@ -993,7 +1051,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { continue; } - let def_kind = tcx.def_kind(item.owner_id); if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind { let adt = tcx.adt_def(item.owner_id); let mut dead_variants = Vec::new(); @@ -1040,8 +1097,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { for foreign_item in module_items.foreign_items() { visitor.check_definition(foreign_item.owner_id.def_id); } - - // We do not warn trait items. } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 77bfe57e3706f..a732bdbca5115 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -8,6 +8,7 @@ use rustc_ast::Label; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, + SubdiagnosticMessageOp, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -390,13 +391,6 @@ pub struct FfiConstInvalidTarget { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_ffi_returns_twice_invalid_target, code = E0724)] -pub struct FfiReturnsTwiceInvalidTarget { - #[primary_span] - pub attr_span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_must_use_async)] pub struct MustUseAsync { @@ -1739,7 +1733,7 @@ pub struct UnusedVariableTryPrefix { #[derive(Subdiagnostic)] pub enum UnusedVariableSugg { - #[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] + #[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] TryPrefixSugg { #[suggestion_part(code = "_{name}")] spans: Vec, @@ -1760,7 +1754,7 @@ pub struct UnusedVariableStringInterp { } impl AddToDiagnostic for UnusedVariableStringInterp { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); diag.multipart_suggestion( crate::fluent_generated::passes_string_interpolation_only_works, @@ -1778,7 +1772,7 @@ pub struct UnusedVarTryIgnore { } #[derive(Subdiagnostic)] -#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] pub struct UnusedVarTryIgnoreSugg { #[suggestion_part(code = "{name}: _")] pub shorthands: Vec, diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 6aeaa8945fb59..9a21397789d6c 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -149,7 +149,9 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { } }; - self.tcx.dcx().emit_err(DuplicateLangItem { + // When there's a duplicate lang item, something went very wrong and there's no value in recovering or doing anything. + // Give the user the one message to let them debug the mess they created and then wish them farewell. + self.tcx.dcx().emit_fatal(DuplicateLangItem { local_span: item_span, lang_item_name, crate_name, diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 862b76b1f6048..064af5aec35aa 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,8 +12,6 @@ #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 99f8186d5543b..3a8dc3775206c 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -123,6 +123,7 @@ enum LiveNodeKind { VarDefNode(Span, HirId), ClosureNode, ExitNode, + ErrNode, } fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { @@ -133,6 +134,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { VarDefNode(s, _) => format!("Var def node [{}]", sm.span_to_diagnostic_string(s)), ClosureNode => "Closure node".to_owned(), ExitNode => "Exit node".to_owned(), + ErrNode => "Error node".to_owned(), } } @@ -719,6 +721,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { ty::ClosureKind::FnMut => {} ty::ClosureKind::FnOnce => return succ, }, + ty::CoroutineClosure(_def_id, args) => match args.as_coroutine_closure().kind() { + ty::ClosureKind::Fn => {} + ty::ClosureKind::FnMut => {} + ty::ClosureKind::FnOnce => return succ, + }, ty::Coroutine(..) => return succ, _ => { span_bug!( @@ -962,10 +969,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Now that we know the label we're going to, // look it up in the continue loop nodes table - self.cont_ln - .get(&sc) - .cloned() - .unwrap_or_else(|| span_bug!(expr.span, "continue to unknown label")) + self.cont_ln.get(&sc).cloned().unwrap_or_else(|| { + self.ir.tcx.dcx().span_delayed_bug(expr.span, "continue to unknown label"); + self.ir.add_live_node(ErrNode) + }) } hir::ExprKind::Assign(ref l, ref r, _) => { diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 0f8cc583b03cf..e10a22cdf31b9 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -134,7 +134,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { Err(hir::LoopIdError::UnresolvedLabel) => None, }; - if let Some(Node::Block(_)) = loop_id.and_then(|id| self.tcx.opt_hir_node(id)) { + if let Some(Node::Block(_)) = loop_id.map(|id| self.tcx.hir_node(id)) { return; } @@ -186,7 +186,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { match destination.target_id { Ok(loop_id) => { - if let Node::Block(block) = self.tcx.opt_hir_node(loop_id).unwrap() { + if let Node::Block(block) = self.tcx.hir_node(loop_id) { self.sess.dcx().emit_err(ContinueLabeledBlock { span: e.span, block_span: block.span, diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 4996015f86345..24824682b74cd 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -151,7 +151,6 @@ use std::cmp::{self, max, min, Ordering}; use std::fmt; use std::iter::once; -use std::mem; use smallvec::SmallVec; @@ -163,7 +162,6 @@ use self::MaybeInfiniteInt::*; use self::SliceKind::*; use crate::index; -use crate::usefulness::PlaceCtxt; use crate::TypeCx; /// Whether we have seen a constructor in the column or not. @@ -649,6 +647,7 @@ impl OpaqueId { /// `specialize_constructor` returns the list of fields corresponding to a pattern, given a /// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and /// `Fields`. +#[derive(Debug)] pub enum Constructor { /// Tuples and structs. Struct, @@ -718,74 +717,6 @@ impl Clone for Constructor { } } -impl fmt::Debug for Constructor { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Constructor::Struct => f.debug_tuple("Struct").finish(), - Constructor::Variant(idx) => f.debug_tuple("Variant").field(idx).finish(), - Constructor::Ref => f.debug_tuple("Ref").finish(), - Constructor::Slice(slice) => f.debug_tuple("Slice").field(slice).finish(), - Constructor::UnionField => f.debug_tuple("UnionField").finish(), - Constructor::Bool(b) => f.debug_tuple("Bool").field(b).finish(), - Constructor::IntRange(range) => f.debug_tuple("IntRange").field(range).finish(), - Constructor::F32Range(lo, hi, end) => { - f.debug_tuple("F32Range").field(lo).field(hi).field(end).finish() - } - Constructor::F64Range(lo, hi, end) => { - f.debug_tuple("F64Range").field(lo).field(hi).field(end).finish() - } - Constructor::Str(value) => f.debug_tuple("Str").field(value).finish(), - Constructor::Opaque(inner) => f.debug_tuple("Opaque").field(inner).finish(), - Constructor::Or => f.debug_tuple("Or").finish(), - Constructor::Wildcard => f.debug_tuple("Wildcard").finish(), - Constructor::NonExhaustive => f.debug_tuple("NonExhaustive").finish(), - Constructor::Hidden => f.debug_tuple("Hidden").finish(), - Constructor::Missing => f.debug_tuple("Missing").finish(), - } - } -} - -impl PartialEq for Constructor { - fn eq(&self, other: &Self) -> bool { - (mem::discriminant(self) == mem::discriminant(other)) - && match (self, other) { - (Constructor::Struct, Constructor::Struct) => true, - (Constructor::Variant(self_variant), Constructor::Variant(other_variant)) => { - self_variant == other_variant - } - (Constructor::Ref, Constructor::Ref) => true, - (Constructor::Slice(self_slice), Constructor::Slice(other_slice)) => { - self_slice == other_slice - } - (Constructor::UnionField, Constructor::UnionField) => true, - (Constructor::Bool(self_b), Constructor::Bool(other_b)) => self_b == other_b, - (Constructor::IntRange(self_range), Constructor::IntRange(other_range)) => { - self_range == other_range - } - ( - Constructor::F32Range(self_lo, self_hi, self_end), - Constructor::F32Range(other_lo, other_hi, other_end), - ) => self_lo == other_lo && self_hi == other_hi && self_end == other_end, - ( - Constructor::F64Range(self_lo, self_hi, self_end), - Constructor::F64Range(other_lo, other_hi, other_end), - ) => self_lo == other_lo && self_hi == other_hi && self_end == other_end, - (Constructor::Str(self_value), Constructor::Str(other_value)) => { - self_value == other_value - } - (Constructor::Opaque(self_inner), Constructor::Opaque(other_inner)) => { - self_inner == other_inner - } - (Constructor::Or, Constructor::Or) => true, - (Constructor::Wildcard, Constructor::Wildcard) => true, - (Constructor::NonExhaustive, Constructor::NonExhaustive) => true, - (Constructor::Hidden, Constructor::Hidden) => true, - (Constructor::Missing, Constructor::Missing) => true, - _ => unreachable!(), - } - } -} - impl Constructor { pub(crate) fn is_non_exhaustive(&self) -> bool { matches!(self, NonExhaustive) @@ -818,8 +749,8 @@ impl Constructor { /// The number of fields for this constructor. This must be kept in sync with /// `Fields::wildcards`. - pub(crate) fn arity(&self, pcx: &PlaceCtxt<'_, Cx>) -> usize { - pcx.ctor_arity(self) + pub(crate) fn arity(&self, cx: &Cx, ty: &Cx::Ty) -> usize { + cx.ctor_arity(self, ty) } /// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`. @@ -827,12 +758,13 @@ impl Constructor { /// this checks for inclusion. // We inline because this has a single call site in `Matrix::specialize_constructor`. #[inline] - pub(crate) fn is_covered_by(&self, pcx: &PlaceCtxt<'_, Cx>, other: &Self) -> bool { - match (self, other) { - (Wildcard, _) => pcx - .mcx - .tycx - .bug(format_args!("Constructor splitting should not have returned `Wildcard`")), + pub(crate) fn is_covered_by(&self, cx: &Cx, other: &Self) -> Result { + Ok(match (self, other) { + (Wildcard, _) => { + return Err(cx.bug(format_args!( + "Constructor splitting should not have returned `Wildcard`" + ))); + } // Wildcards cover anything (_, Wildcard) => true, // Only a wildcard pattern can match these special constructors. @@ -873,10 +805,12 @@ impl Constructor { (Opaque(self_id), Opaque(other_id)) => self_id == other_id, (Opaque(..), _) | (_, Opaque(..)) => false, - _ => pcx.mcx.tycx.bug(format_args!( - "trying to compare incompatible constructors {self:?} and {other:?}" - )), - } + _ => { + return Err(cx.bug(format_args!( + "trying to compare incompatible constructors {self:?} and {other:?}" + ))); + } + }) } } @@ -950,10 +884,10 @@ pub enum ConstructorSet { /// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be /// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4. #[derive(Debug)] -pub(crate) struct SplitConstructorSet { - pub(crate) present: SmallVec<[Constructor; 1]>, - pub(crate) missing: Vec>, - pub(crate) missing_empty: Vec>, +pub struct SplitConstructorSet { + pub present: SmallVec<[Constructor; 1]>, + pub missing: Vec>, + pub missing_empty: Vec>, } impl ConstructorSet { @@ -962,7 +896,7 @@ impl ConstructorSet { /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation /// and its invariants. #[instrument(level = "debug", skip(self, ctors), ret)] - pub(crate) fn split<'a>( + pub fn split<'a>( &self, ctors: impl Iterator> + Clone, ) -> SplitConstructorSet diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 88770b0c43b37..2dffdc9846c22 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; +use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::Ty; @@ -23,7 +23,10 @@ impl<'tcx> Uncovered<'tcx> { span: Span, cx: &RustcMatchCheckCtxt<'p, 'tcx>, witnesses: Vec>, - ) -> Self { + ) -> Self + where + 'tcx: 'p, + { let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap()); Self { span, @@ -59,10 +62,7 @@ pub struct Overlap<'tcx> { } impl<'tcx> AddToDiagnostic for Overlap<'tcx> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let Overlap { span, range } = self; // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index a53d7a0d8096a..164dc36b679e7 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -1,11 +1,15 @@ //! Analysis of patterns, notably match exhaustiveness checking. +#![allow(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] + pub mod constructor; #[cfg(feature = "rustc")] pub mod errors; #[cfg(feature = "rustc")] pub(crate) mod lints; pub mod pat; +pub mod pat_column; #[cfg(feature = "rustc")] pub mod rustc; pub mod usefulness; @@ -67,8 +71,9 @@ use rustc_span::ErrorGuaranteed; use crate::constructor::{Constructor, ConstructorSet, IntRange}; #[cfg(feature = "rustc")] -use crate::lints::{lint_nonexhaustive_missing_variants, PatternColumn}; +use crate::lints::lint_nonexhaustive_missing_variants; use crate::pat::DeconstructedPat; +use crate::pat_column::PatternColumn; #[cfg(feature = "rustc")] use crate::rustc::RustcMatchCheckCtxt; #[cfg(feature = "rustc")] @@ -117,42 +122,28 @@ pub trait TypeCx: Sized + fmt::Debug { /// `DeconstructedPat`. Only invoqued when `pat.ctor()` is `Struct | Variant(_) | UnionField`. fn write_variant_name( f: &mut fmt::Formatter<'_>, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat, ) -> fmt::Result; /// Raise a bug. - fn bug(&self, fmt: fmt::Arguments<'_>) -> !; + fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error; /// Lint that the range `pat` overlapped with all the ranges in `overlaps_with`, where the range /// they overlapped over is `overlaps_on`. We only detect singleton overlaps. /// The default implementation does nothing. fn lint_overlapping_range_endpoints( &self, - _pat: &DeconstructedPat<'_, Self>, + _pat: &DeconstructedPat, _overlaps_on: IntRange, - _overlaps_with: &[&DeconstructedPat<'_, Self>], + _overlaps_with: &[&DeconstructedPat], ) { } } -/// Context that provides information global to a match. -pub struct MatchCtxt<'a, Cx: TypeCx> { - /// The context for type information. - pub tycx: &'a Cx, -} - -impl<'a, Cx: TypeCx> Clone for MatchCtxt<'a, Cx> { - fn clone(&self) -> Self { - Self { tycx: self.tycx } - } -} - -impl<'a, Cx: TypeCx> Copy for MatchCtxt<'a, Cx> {} - /// The arm of a match expression. #[derive(Debug)] pub struct MatchArm<'p, Cx: TypeCx> { - pub pat: &'p DeconstructedPat<'p, Cx>, + pub pat: &'p DeconstructedPat, pub has_guard: bool, pub arm_data: Cx::ArmData, } @@ -175,15 +166,13 @@ pub fn analyze_match<'p, 'tcx>( ) -> Result, ErrorGuaranteed> { let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); - let cx = MatchCtxt { tycx }; - - let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity)?; + let report = compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity)?; // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting // `if let`s. Only run if the match is exhaustive otherwise the error is redundant. if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() { let pat_column = PatternColumn::new(arms); - lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)?; + lint_nonexhaustive_missing_variants(tycx, arms, &pat_column, scrut_ty)?; } Ok(report) diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 4bfe7dfb072c4..30e775733de75 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -1,109 +1,24 @@ use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::ErrorGuaranteed; +use crate::constructor::Constructor; use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; -use crate::pat::PatOrWild; -use crate::rustc::{ - Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt, - SplitConstructorSet, WitnessPat, -}; - -/// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that -/// inspect the same subvalue/place". -/// This is used to traverse patterns column-by-column for lints. Despite similarities with the -/// algorithm in [`crate::usefulness`], this does a different traversal. Notably this is linear in -/// the depth of patterns, whereas `compute_exhaustiveness_and_usefulness` is worst-case exponential -/// (exhaustiveness is NP-complete). The core difference is that we treat sub-columns separately. -/// -/// This must not contain an or-pattern. `expand_and_push` takes care to expand them. -/// -/// This is not used in the usefulness algorithm; only in lints. -#[derive(Debug)] -pub(crate) struct PatternColumn<'p, 'tcx> { - patterns: Vec<&'p DeconstructedPat<'p, 'tcx>>, -} - -impl<'p, 'tcx> PatternColumn<'p, 'tcx> { - pub(crate) fn new(arms: &[MatchArm<'p, 'tcx>]) -> Self { - let patterns = Vec::with_capacity(arms.len()); - let mut column = PatternColumn { patterns }; - for arm in arms { - column.expand_and_push(PatOrWild::Pat(arm.pat)); - } - column - } - /// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns. - /// Internal method, prefer [`PatternColumn::new`]. - fn expand_and_push(&mut self, pat: PatOrWild<'p, RustcMatchCheckCtxt<'p, 'tcx>>) { - // We flatten or-patterns and skip algorithm-generated wildcards. - if pat.is_or_pat() { - self.patterns.extend( - pat.flatten_or_pat().into_iter().filter_map(|pat_or_wild| pat_or_wild.as_pat()), - ) - } else if let Some(pat) = pat.as_pat() { - self.patterns.push(pat) - } - } - - fn head_ty(&self) -> Option> { - self.patterns.first().map(|pat| *pat.ty()) - } - - /// Do constructor splitting on the constructors of the column. - fn analyze_ctors( - &self, - pcx: &PlaceCtxt<'_, 'p, 'tcx>, - ) -> Result, ErrorGuaranteed> { - let column_ctors = self.patterns.iter().map(|p| p.ctor()); - let ctors_for_ty = &pcx.ctors_for_ty()?; - Ok(ctors_for_ty.split(column_ctors)) - } - - /// Does specialization: given a constructor, this takes the patterns from the column that match - /// the constructor, and outputs their fields. - /// This returns one column per field of the constructor. They usually all have the same length - /// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns - /// which may change the lengths. - fn specialize( - &self, - pcx: &PlaceCtxt<'_, 'p, 'tcx>, - ctor: &Constructor<'p, 'tcx>, - ) -> Vec> { - let arity = ctor.arity(pcx); - if arity == 0 { - return Vec::new(); - } - - // We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These - // columns may have different lengths in the presence of or-patterns (this is why we can't - // reuse `Matrix`). - let mut specialized_columns: Vec<_> = - (0..arity).map(|_| Self { patterns: Vec::new() }).collect(); - let relevant_patterns = - self.patterns.iter().filter(|pat| ctor.is_covered_by(pcx, pat.ctor())); - for pat in relevant_patterns { - let specialized = pat.specialize(ctor, arity); - for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) { - column.expand_and_push(subpat); - } - } - specialized_columns - } -} +use crate::pat_column::PatternColumn; +use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat}; +use crate::MatchArm; /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. #[instrument(level = "debug", skip(cx), ret)] -fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( - cx: MatchCtxt<'a, 'p, 'tcx>, - column: &PatternColumn<'p, 'tcx>, +fn collect_nonexhaustive_missing_variants<'p, 'tcx>( + cx: &RustcMatchCheckCtxt<'p, 'tcx>, + column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, ) -> Result>, ErrorGuaranteed> { - let Some(ty) = column.head_ty() else { + let Some(&ty) = column.head_ty() else { return Ok(Vec::new()); }; - let pcx = &PlaceCtxt::new_dummy(cx, &ty); - let set = column.analyze_ctors(pcx)?; + let set = column.analyze_ctors(cx, &ty)?; if set.present.is_empty() { // We can't consistently handle the case where no constructors are present (since this would // require digging deep through any type in case there's a non_exhaustive enum somewhere), @@ -112,20 +27,20 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( } let mut witnesses = Vec::new(); - if cx.tycx.is_foreign_non_exhaustive_enum(ty) { + if cx.is_foreign_non_exhaustive_enum(ty) { witnesses.extend( set.missing .into_iter() // This will list missing visible variants. .filter(|c| !matches!(c, Constructor::Hidden | Constructor::NonExhaustive)) - .map(|missing_ctor| WitnessPat::wild_from_ctor(pcx, missing_ctor)), + .map(|missing_ctor| WitnessPat::wild_from_ctor(cx, missing_ctor, ty)), ) } // Recurse into the fields. for ctor in set.present { - let specialized_columns = column.specialize(pcx, &ctor); - let wild_pat = WitnessPat::wild_from_ctor(pcx, ctor); + let specialized_columns = column.specialize(cx, &ty, &ctor); + let wild_pat = WitnessPat::wild_from_ctor(cx, ctor, ty); for (i, col_i) in specialized_columns.iter().enumerate() { // Compute witnesses for each column. let wits_for_col_i = collect_nonexhaustive_missing_variants(cx, col_i)?; @@ -141,18 +56,17 @@ fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( Ok(witnesses) } -pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>( - cx: MatchCtxt<'a, 'p, 'tcx>, - arms: &[MatchArm<'p, 'tcx>], - pat_column: &PatternColumn<'p, 'tcx>, +pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( + rcx: &RustcMatchCheckCtxt<'p, 'tcx>, + arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>], + pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx; if !matches!( rcx.tcx.lint_level_at_node(NON_EXHAUSTIVE_OMITTED_PATTERNS, rcx.match_lint_level).0, rustc_session::lint::Level::Allow ) { - let witnesses = collect_nonexhaustive_missing_variants(cx, pat_column)?; + let witnesses = collect_nonexhaustive_missing_variants(rcx, pat_column)?; if !witnesses.is_empty() { // Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns` // is not exhaustive enough. diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index d476766d466f2..9bde23c7bf124 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -6,8 +6,7 @@ use std::fmt; use smallvec::{smallvec, SmallVec}; use crate::constructor::{Constructor, Slice, SliceKind}; -use crate::usefulness::PlaceCtxt; -use crate::{Captures, TypeCx}; +use crate::TypeCx; use self::Constructor::*; @@ -22,9 +21,9 @@ use self::Constructor::*; /// This happens if a private or `non_exhaustive` field is uninhabited, because the code mustn't /// observe that it is uninhabited. In that case that field is not included in `fields`. Care must /// be taken when converting to/from `thir::Pat`. -pub struct DeconstructedPat<'p, Cx: TypeCx> { +pub struct DeconstructedPat { ctor: Constructor, - fields: &'p [DeconstructedPat<'p, Cx>], + fields: Vec>, ty: Cx::Ty, /// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not /// correspond to a user-supplied pattern. @@ -33,14 +32,20 @@ pub struct DeconstructedPat<'p, Cx: TypeCx> { useful: Cell, } -impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { +impl DeconstructedPat { pub fn wildcard(ty: Cx::Ty) -> Self { - DeconstructedPat { ctor: Wildcard, fields: &[], ty, data: None, useful: Cell::new(false) } + DeconstructedPat { + ctor: Wildcard, + fields: Vec::new(), + ty, + data: None, + useful: Cell::new(false), + } } pub fn new( ctor: Constructor, - fields: &'p [DeconstructedPat<'p, Cx>], + fields: Vec>, ty: Cx::Ty, data: Cx::PatData, ) -> Self { @@ -63,17 +68,17 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { self.data.as_ref() } - pub fn iter_fields(&self) -> impl Iterator> + Captures<'_> { + pub fn iter_fields<'a>(&'a self) -> impl Iterator> { self.fields.iter() } /// Specialize this pattern with a constructor. /// `other_ctor` can be different from `self.ctor`, but must be covered by it. - pub(crate) fn specialize( - &self, + pub(crate) fn specialize<'a>( + &'a self, other_ctor: &Constructor, ctor_arity: usize, - ) -> SmallVec<[PatOrWild<'p, Cx>; 2]> { + ) -> SmallVec<[PatOrWild<'a, Cx>; 2]> { let wildcard_sub_tys = || (0..ctor_arity).map(|_| PatOrWild::Wild).collect(); match (&self.ctor, other_ctor) { // Return a wildcard for each field of `other_ctor`. @@ -140,7 +145,7 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { } /// This is best effort and not good enough for a `Display` impl. -impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> { +impl fmt::Debug for DeconstructedPat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let pat = self; let mut first = true; @@ -222,7 +227,7 @@ pub(crate) enum PatOrWild<'p, Cx: TypeCx> { /// A non-user-provided wildcard, created during specialization. Wild, /// A user-provided pattern. - Pat(&'p DeconstructedPat<'p, Cx>), + Pat(&'p DeconstructedPat), } impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { @@ -237,7 +242,7 @@ impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {} impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { - pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<'p, Cx>> { + pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat> { match self { PatOrWild::Wild => None, PatOrWild::Pat(pat) => Some(pat), @@ -298,6 +303,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for PatOrWild<'p, Cx> { /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics /// purposes. As such they don't use interning and can be cloned. +#[derive(Debug)] pub struct WitnessPat { ctor: Constructor, pub(crate) fields: Vec>, @@ -310,16 +316,6 @@ impl Clone for WitnessPat { } } -impl fmt::Debug for WitnessPat { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_struct("WitnessPat") - .field("ctor", &self.ctor) - .field("fields", &self.fields) - .field("ty", &self.ty) - .finish() - } -} - impl WitnessPat { pub(crate) fn new(ctor: Constructor, fields: Vec, ty: Cx::Ty) -> Self { Self { ctor, fields, ty } @@ -331,9 +327,9 @@ impl WitnessPat { /// Construct a pattern that matches everything that starts with this constructor. /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern /// `Some(_)`. - pub(crate) fn wild_from_ctor(pcx: &PlaceCtxt<'_, Cx>, ctor: Constructor) -> Self { - let fields = pcx.ctor_sub_tys(&ctor).map(|ty| Self::wildcard(ty)).collect(); - Self::new(ctor, fields, pcx.ty.clone()) + pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor, ty: Cx::Ty) -> Self { + let fields = cx.ctor_sub_tys(&ctor, &ty).map(|ty| Self::wildcard(ty)).collect(); + Self::new(ctor, fields, ty) } pub fn ctor(&self) -> &Constructor { diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs new file mode 100644 index 0000000000000..ce14fdc364f79 --- /dev/null +++ b/compiler/rustc_pattern_analysis/src/pat_column.rs @@ -0,0 +1,90 @@ +use crate::constructor::{Constructor, SplitConstructorSet}; +use crate::pat::{DeconstructedPat, PatOrWild}; +use crate::{Captures, MatchArm, TypeCx}; + +/// A column of patterns in a match, where a column is the intuitive notion of "subpatterns that +/// inspect the same subvalue/place". +/// This is used to traverse patterns column-by-column for lints. Despite similarities with the +/// algorithm in [`crate::usefulness`], this does a different traversal. Notably this is linear in +/// the depth of patterns, whereas `compute_exhaustiveness_and_usefulness` is worst-case exponential +/// (exhaustiveness is NP-complete). The core difference is that we treat sub-columns separately. +/// +/// This is not used in the usefulness algorithm; only in lints. +#[derive(Debug)] +pub struct PatternColumn<'p, Cx: TypeCx> { + /// This must not contain an or-pattern. `expand_and_push` takes care to expand them. + patterns: Vec<&'p DeconstructedPat>, +} + +impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { + pub fn new(arms: &[MatchArm<'p, Cx>]) -> Self { + let patterns = Vec::with_capacity(arms.len()); + let mut column = PatternColumn { patterns }; + for arm in arms { + column.expand_and_push(PatOrWild::Pat(arm.pat)); + } + column + } + /// Pushes a pattern onto the column, expanding any or-patterns into its subpatterns. + /// Internal method, prefer [`PatternColumn::new`]. + fn expand_and_push(&mut self, pat: PatOrWild<'p, Cx>) { + // We flatten or-patterns and skip algorithm-generated wildcards. + if pat.is_or_pat() { + self.patterns.extend( + pat.flatten_or_pat().into_iter().filter_map(|pat_or_wild| pat_or_wild.as_pat()), + ) + } else if let Some(pat) = pat.as_pat() { + self.patterns.push(pat) + } + } + + pub fn head_ty(&self) -> Option<&Cx::Ty> { + self.patterns.first().map(|pat| pat.ty()) + } + pub fn iter<'a>(&'a self) -> impl Iterator> + Captures<'a> { + self.patterns.iter().copied() + } + + /// Do constructor splitting on the constructors of the column. + pub fn analyze_ctors( + &self, + cx: &Cx, + ty: &Cx::Ty, + ) -> Result, Cx::Error> { + let column_ctors = self.patterns.iter().map(|p| p.ctor()); + let ctors_for_ty = cx.ctors_for_ty(ty)?; + Ok(ctors_for_ty.split(column_ctors)) + } + + /// Does specialization: given a constructor, this takes the patterns from the column that match + /// the constructor, and outputs their fields. + /// This returns one column per field of the constructor. They usually all have the same length + /// (the number of patterns in `self` that matched `ctor`), except that we expand or-patterns + /// which may change the lengths. + pub fn specialize( + &self, + cx: &Cx, + ty: &Cx::Ty, + ctor: &Constructor, + ) -> Vec> { + let arity = ctor.arity(cx, ty); + if arity == 0 { + return Vec::new(); + } + + // We specialize the column by `ctor`. This gives us `arity`-many columns of patterns. These + // columns may have different lengths in the presence of or-patterns (this is why we can't + // reuse `Matrix`). + let mut specialized_columns: Vec<_> = + (0..arity).map(|_| Self { patterns: Vec::new() }).collect(); + let relevant_patterns = + self.patterns.iter().filter(|pat| ctor.is_covered_by(cx, pat.ctor()).unwrap_or(false)); + for pat in relevant_patterns { + let specialized = pat.specialize(ctor, arity); + for (subpat, column) in specialized.into_iter().zip(&mut specialized_columns) { + column.expand_and_push(subpat); + } + } + specialized_columns + } +} diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 223d6cefc83fe..a8fe0cb6a1dc7 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,8 +1,7 @@ -use smallvec::SmallVec; use std::fmt; use std::iter::once; -use rustc_arena::{DroplessArena, TypedArena}; +use rustc_arena::DroplessArena; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::{Idx, IndexVec}; @@ -27,14 +26,8 @@ use crate::constructor::Constructor::*; pub type Constructor<'p, 'tcx> = crate::constructor::Constructor>; pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet>; -pub type DeconstructedPat<'p, 'tcx> = - crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; +pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; -pub(crate) type PlaceCtxt<'a, 'p, 'tcx> = - crate::usefulness::PlaceCtxt<'a, RustcMatchCheckCtxt<'p, 'tcx>>; -pub(crate) type SplitConstructorSet<'p, 'tcx> = - crate::constructor::SplitConstructorSet>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>; @@ -69,7 +62,7 @@ impl<'tcx> RevealedTy<'tcx> { } #[derive(Clone)] -pub struct RustcMatchCheckCtxt<'p, 'tcx> { +pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> { pub tcx: TyCtxt<'tcx>, pub typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The module in which the match occurs. This is necessary for @@ -79,8 +72,6 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { /// outside its module and should not be matchable with an empty match statement. pub module: DefId, pub param_env: ty::ParamEnv<'tcx>, - /// To allocate lowered patterns - pub pattern_arena: &'p TypedArena>, /// To allocate the result of `self.ctor_sub_tys()` pub dropless_arena: &'p DroplessArena, /// Lint level at the match. @@ -96,13 +87,13 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { pub known_valid_scrutinee: bool, } -impl<'p, 'tcx> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RustcMatchCheckCtxt").finish() } } -impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { /// Type inference occasionally gives us opaque types in places where corresponding patterns /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited /// types, we use the corresponding concrete type if possible. @@ -428,7 +419,8 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::Alias(_, _) | ty::Param(_) @@ -463,21 +455,20 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { /// Note: the input patterns must have been lowered through /// `rustc_mir_build::thir::pattern::check_match::MatchVisitor::lower_pattern`. pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> { - let singleton = |pat| std::slice::from_ref(self.pattern_arena.alloc(pat)); let cx = self; let ty = cx.reveal_opaque_ty(pat.ty); let ctor; - let fields: &[_]; + let mut fields: Vec<_>; match &pat.kind { PatKind::AscribeUserType { subpattern, .. } | PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; - fields = &[]; + fields = vec![]; } PatKind::Deref { subpattern } => { - fields = singleton(self.lower_pat(subpattern)); + fields = vec![self.lower_pat(subpattern)]; ctor = match ty.kind() { // This is a box pattern. ty::Adt(adt, ..) if adt.is_box() => Struct, @@ -489,15 +480,14 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { match ty.kind() { ty::Tuple(fs) => { ctor = Struct; - let mut wilds: SmallVec<[_; 2]> = fs + fields = fs .iter() .map(|ty| cx.reveal_opaque_ty(ty)) .map(|ty| DeconstructedPat::wildcard(ty)) .collect(); for pat in subpatterns { - wilds[pat.field.index()] = self.lower_pat(&pat.pattern); + fields[pat.field.index()] = self.lower_pat(&pat.pattern); } - fields = cx.pattern_arena.alloc_from_iter(wilds); } ty::Adt(adt, args) if adt.is_box() => { // The only legal patterns of type `Box` (outside `std`) are `_` and box @@ -519,7 +509,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { DeconstructedPat::wildcard(self.reveal_opaque_ty(args.type_at(0))) }; ctor = Struct; - fields = singleton(pat); + fields = vec![pat]; } ty::Adt(adt, _) => { ctor = match pat.kind { @@ -539,14 +529,12 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { ty }, ); - let mut wilds: SmallVec<[_; 2]> = - tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); + fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); for pat in subpatterns { if let Some(i) = field_id_to_id[pat.field.index()] { - wilds[i] = self.lower_pat(&pat.pattern); + fields[i] = self.lower_pat(&pat.pattern); } } - fields = cx.pattern_arena.alloc_from_iter(wilds); } _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty), } @@ -558,7 +546,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { Some(b) => Bool(b), None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Char | ty::Int(_) | ty::Uint(_) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -574,7 +562,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Float(ty::FloatTy::F32) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -585,7 +573,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Float(ty::FloatTy::F64) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -596,7 +584,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Ref(_, t, _) if t.is_str() => { // We want a `&str` constant to behave like a `Deref` pattern, to be compatible @@ -607,16 +595,16 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { // subfields. // Note: `t` is `str`, not `&str`. let ty = self.reveal_opaque_ty(*t); - let subpattern = DeconstructedPat::new(Str(*value), &[], ty, pat); + let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat); ctor = Ref; - fields = singleton(subpattern) + fields = vec![subpattern] } // All constants that can be structurally matched have already been expanded // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are // opaque. _ => { ctor = Opaque(OpaqueId::new()); - fields = &[]; + fields = vec![]; } } } @@ -653,7 +641,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } _ => bug!("invalid type for range pattern: {}", ty.inner()), }; - fields = &[]; + fields = vec![]; } PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { let array_len = match ty.kind() { @@ -669,25 +657,23 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { SliceKind::FixedLen(prefix.len() + suffix.len()) }; ctor = Slice(Slice::new(array_len, kind)); - fields = cx.pattern_arena.alloc_from_iter( - prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)), - ) + fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect(); } PatKind::Or { .. } => { ctor = Or; let pats = expand_or_pat(pat); - fields = - cx.pattern_arena.alloc_from_iter(pats.into_iter().map(|p| self.lower_pat(p))) + fields = pats.into_iter().map(|p| self.lower_pat(p)).collect(); } PatKind::Never => { - // FIXME(never_patterns): handle `!` in exhaustiveness. This is a sane default - // in the meantime. + // A never pattern matches all the values of its type (namely none). Moreover it + // must be compatible with other constructors, since we can use `!` on a type like + // `Result` which has other constructors. Hence we lower it as a wildcard. ctor = Wildcard; - fields = &[]; + fields = vec![]; } PatKind::Error(_) => { ctor = Opaque(OpaqueId::new()); - fields = &[]; + fields = vec![]; } } DeconstructedPat::new(ctor, fields, ty, pat) @@ -858,7 +844,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } } -impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { type Ty = RevealedTy<'tcx>; type Error = ErrorGuaranteed; type VariantIdx = VariantIdx; @@ -892,7 +878,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn write_variant_name( f: &mut fmt::Formatter<'_>, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat, ) -> fmt::Result { if let ty::Adt(adt, _) = pat.ty().kind() { if adt.is_box() { @@ -905,15 +891,15 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { Ok(()) } - fn bug(&self, fmt: fmt::Arguments<'_>) -> ! { + fn bug(&self, fmt: fmt::Arguments<'_>) -> Self::Error { span_bug!(self.scrut_span, "{}", fmt) } fn lint_overlapping_range_endpoints( &self, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat, overlaps_on: IntRange, - overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>], + overlaps_with: &[&crate::pat::DeconstructedPat], ) { let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); let overlaps: Vec<_> = overlaps_with diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index b15de1c0ca9d7..80a807b4f2759 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -719,7 +719,7 @@ use std::fmt; use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::{DeconstructedPat, PatOrWild, WitnessPat}; -use crate::{Captures, MatchArm, MatchCtxt, TypeCx}; +use crate::{Captures, MatchArm, TypeCx}; use self::ValidityConstraint::*; @@ -730,21 +730,33 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { f() } +/// Context that provides information for usefulness checking. +pub struct UsefulnessCtxt<'a, Cx: TypeCx> { + /// The context for type information. + pub tycx: &'a Cx, +} + +impl<'a, Cx: TypeCx> Copy for UsefulnessCtxt<'a, Cx> {} +impl<'a, Cx: TypeCx> Clone for UsefulnessCtxt<'a, Cx> { + fn clone(&self) -> Self { + Self { tycx: self.tycx } + } +} + /// Context that provides information local to a place under investigation. -pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> { - pub(crate) mcx: MatchCtxt<'a, Cx>, +struct PlaceCtxt<'a, Cx: TypeCx> { + cx: &'a Cx, /// Type of the place under investigation. - pub(crate) ty: &'a Cx::Ty, + ty: &'a Cx::Ty, } +impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {} impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> { fn clone(&self) -> Self { - Self { mcx: self.mcx, ty: self.ty } + Self { cx: self.cx, ty: self.ty } } } -impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {} - impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish() @@ -752,23 +764,14 @@ impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> { } impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { - /// A `PlaceCtxt` when code other than `is_useful` needs one. - #[cfg_attr(not(feature = "rustc"), allow(dead_code))] - pub(crate) fn new_dummy(mcx: MatchCtxt<'a, Cx>, ty: &'a Cx::Ty) -> Self { - PlaceCtxt { mcx, ty } + fn ctor_arity(&self, ctor: &Constructor) -> usize { + self.cx.ctor_arity(ctor, self.ty) } - - pub(crate) fn ctor_arity(&self, ctor: &Constructor) -> usize { - self.mcx.tycx.ctor_arity(ctor, self.ty) + fn ctors_for_ty(&self) -> Result, Cx::Error> { + self.cx.ctors_for_ty(self.ty) } - pub(crate) fn ctor_sub_tys( - &'a self, - ctor: &'a Constructor, - ) -> impl Iterator + ExactSizeIterator + Captures<'a> { - self.mcx.tycx.ctor_sub_tys(ctor, self.ty) - } - pub(crate) fn ctors_for_ty(&self) -> Result, Cx::Error> { - self.mcx.tycx.ctors_for_ty(self.ty) + fn wild_from_ctor(&self, ctor: Constructor) -> WitnessPat { + WitnessPat::wild_from_ctor(self.cx, ctor, self.ty.clone()) } } @@ -819,6 +822,38 @@ impl fmt::Display for ValidityConstraint { } } +/// Data about a place under investigation. +struct PlaceInfo { + /// The type of the place. + ty: Cx::Ty, + /// Whether the place is known to contain valid data. + validity: ValidityConstraint, + /// Whether the place is the scrutinee itself or a subplace of it. + is_scrutinee: bool, +} + +impl PlaceInfo { + fn specialize<'a>( + &'a self, + cx: &'a Cx, + ctor: &'a Constructor, + ) -> impl Iterator + ExactSizeIterator + Captures<'a> { + let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty); + let ctor_sub_validity = self.validity.specialize(ctor); + ctor_sub_tys.map(move |ty| PlaceInfo { + ty, + validity: ctor_sub_validity, + is_scrutinee: false, + }) + } +} + +impl Clone for PlaceInfo { + fn clone(&self) -> Self { + Self { ty: self.ty.clone(), validity: self.validity, is_scrutinee: self.is_scrutinee } + } +} + /// Represents a pattern-tuple under investigation. // The three lifetimes are: // - 'p coming from the input @@ -839,7 +874,7 @@ impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> { } impl<'p, Cx: TypeCx> PatStack<'p, Cx> { - fn from_pattern(pat: &'p DeconstructedPat<'p, Cx>) -> Self { + fn from_pattern(pat: &'p DeconstructedPat) -> Self { PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true } } @@ -992,10 +1027,9 @@ struct Matrix<'p, Cx: TypeCx> { /// each column must have the same type. Each column corresponds to a place within the /// scrutinee. rows: Vec>, - /// Track the type of each column/place. - place_ty: SmallVec<[Cx::Ty; 2]>, - /// Track for each column/place whether it contains a known valid value. - place_validity: SmallVec<[ValidityConstraint; 2]>, + /// Track info about each place. Each place corresponds to a column in `rows`, and their types + /// must match. + place_info: SmallVec<[PlaceInfo; 2]>, /// Track whether the virtual wildcard row used to compute exhaustiveness is relevant. See top /// of the file for details on relevancy. wildcard_row_is_relevant: bool, @@ -1023,10 +1057,10 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Self { + let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity, is_scrutinee: true }; let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), - place_ty: smallvec![scrut_ty], - place_validity: smallvec![scrut_validity], + place_info: smallvec![place_info], wildcard_row_is_relevant: true, }; for (row_id, arm) in arms.iter().enumerate() { @@ -1042,11 +1076,11 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { matrix } - fn head_ty(&self) -> Option<&Cx::Ty> { - self.place_ty.first() + fn head_place(&self) -> Option<&PlaceInfo> { + self.place_info.first() } fn column_count(&self) -> usize { - self.place_ty.len() + self.place_info.len() } fn rows( @@ -1073,28 +1107,23 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor, ctor_is_relevant: bool, - ) -> Matrix<'p, Cx> { - let ctor_sub_tys = pcx.ctor_sub_tys(ctor); - let arity = ctor_sub_tys.len(); - let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect(); - let ctor_sub_validity = self.place_validity[0].specialize(ctor); - let specialized_place_validity = std::iter::repeat(ctor_sub_validity) - .take(arity) - .chain(self.place_validity[1..].iter().copied()) - .collect(); + ) -> Result, Cx::Error> { + let subfield_place_info = self.place_info[0].specialize(pcx.cx, ctor); + let arity = subfield_place_info.len(); + let specialized_place_info = + subfield_place_info.chain(self.place_info[1..].iter().cloned()).collect(); let mut matrix = Matrix { rows: Vec::new(), - place_ty: specialized_place_ty, - place_validity: specialized_place_validity, + place_info: specialized_place_info, wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, }; for (i, row) in self.rows().enumerate() { - if ctor.is_covered_by(pcx, row.head().ctor()) { + if ctor.is_covered_by(pcx.cx, row.head().ctor())? { let new_row = row.pop_head_constructor(ctor, arity, ctor_is_relevant, i); matrix.expand_and_push(new_row); } } - matrix + Ok(matrix) } } @@ -1118,11 +1147,11 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { .map(|row| row.iter().map(|pat| format!("{pat:?}")).collect()) .collect(); pretty_printed_matrix - .push(self.place_validity.iter().map(|validity| format!("{validity}")).collect()); + .push(self.place_info.iter().map(|place| format!("{}", place.validity)).collect()); let column_count = self.column_count(); assert!(self.rows.iter().all(|row| row.len() == column_count)); - assert!(self.place_validity.len() == column_count); + assert!(self.place_info.len() == column_count); let column_widths: Vec = (0..column_count) .map(|col| pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)) .collect(); @@ -1198,6 +1227,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { /// The final `Pair(Some(_), true)` is then the resulting witness. /// /// See the top of the file for more detailed explanations and examples. +#[derive(Debug)] struct WitnessStack(Vec>); impl Clone for WitnessStack { @@ -1206,12 +1236,6 @@ impl Clone for WitnessStack { } } -impl fmt::Debug for WitnessStack { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_tuple("WitnessStack").field(&self.0).finish() - } -} - impl WitnessStack { /// Asserts that the witness contains a single pattern, and returns it. fn single_pattern(self) -> WitnessPat { @@ -1240,7 +1264,7 @@ impl WitnessStack { /// ``` fn apply_constructor(&mut self, pcx: &PlaceCtxt<'_, Cx>, ctor: &Constructor) { let len = self.0.len(); - let arity = ctor.arity(pcx); + let arity = pcx.ctor_arity(ctor); let fields = self.0.drain((len - arity)..).rev().collect(); let pat = WitnessPat::new(ctor.clone(), fields, pcx.ty.clone()); self.0.push(pat); @@ -1256,6 +1280,7 @@ impl WitnessStack { /// /// Just as the `Matrix` starts with a single column, by the end of the algorithm, this has a single /// column, which contains the patterns that are missing for the match to be exhaustive. +#[derive(Debug)] struct WitnessMatrix(Vec>); impl Clone for WitnessMatrix { @@ -1264,12 +1289,6 @@ impl Clone for WitnessMatrix { } } -impl fmt::Debug for WitnessMatrix { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_tuple("WitnessMatrix").field(&self.0).finish() - } -} - impl WitnessMatrix { /// New matrix with no witnesses. fn empty() -> Self { @@ -1315,20 +1334,20 @@ impl WitnessMatrix { *self = Self::empty(); } else if !report_individual_missing_ctors { // Report `_` as missing. - let pat = WitnessPat::wild_from_ctor(pcx, Constructor::Wildcard); + let pat = pcx.wild_from_ctor(Constructor::Wildcard); self.push_pattern(pat); } else if missing_ctors.iter().any(|c| c.is_non_exhaustive()) { // We need to report a `_` anyway, so listing other constructors would be redundant. // `NonExhaustive` is displayed as `_` just like `Wildcard`, but it will be picked // up by diagnostics to add a note about why `_` is required here. - let pat = WitnessPat::wild_from_ctor(pcx, Constructor::NonExhaustive); + let pat = pcx.wild_from_ctor(Constructor::NonExhaustive); self.push_pattern(pat); } else { // For each missing constructor `c`, we add a `c(_, _, _)` witness appropriately // filled with wildcards. let mut ret = Self::empty(); for ctor in missing_ctors { - let pat = WitnessPat::wild_from_ctor(pcx, ctor.clone()); + let pat = pcx.wild_from_ctor(ctor.clone()); // Clone `self` and add `c(_, _, _)` to each of its witnesses. let mut wit_matrix = self.clone(); wit_matrix.push_pattern(pat); @@ -1362,7 +1381,7 @@ impl WitnessMatrix { /// We can however get false negatives because exhaustiveness does not explore all cases. See the /// section on relevancy at the top of the file. fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( - mcx: MatchCtxt<'_, Cx>, + mcx: UsefulnessCtxt<'_, Cx>, overlap_range: IntRange, matrix: &Matrix<'p, Cx>, specialized_matrix: &Matrix<'p, Cx>, @@ -1433,11 +1452,10 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( /// - unspecialization, where we lift the results from the previous step into results for this step /// (using `apply_constructor` and by updating `row.useful` for each parent row). /// This is all explained at the top of the file. -#[instrument(level = "debug", skip(mcx, is_top_level), ret)] +#[instrument(level = "debug", skip(mcx), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( - mcx: MatchCtxt<'a, Cx>, + mcx: UsefulnessCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, - is_top_level: bool, ) -> Result, Cx::Error> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1448,7 +1466,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( return Ok(WitnessMatrix::empty()); } - let Some(ty) = matrix.head_ty().cloned() else { + let Some(place) = matrix.head_place() else { // The base case: there are no columns in the matrix. We are morally pattern-matching on (). // A row is useful iff it has no (unguarded) rows above it. let mut useful = true; // Whether the next row is useful. @@ -1468,18 +1486,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( }; }; - debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { mcx, ty: &ty }; + let ty = &place.ty.clone(); // Clone it out so we can mutate `matrix` later. + let pcx = &PlaceCtxt { cx: mcx.tycx, ty }; + debug!("ty: {:?}", pcx.ty); let ctors_for_ty = pcx.ctors_for_ty()?; - // Whether the place/column we are inspecting is known to contain valid data. - let place_validity = matrix.place_validity[0]; // We treat match scrutinees of type `!` or `EmptyEnum` differently. let is_toplevel_exception = - is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); + place.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors); // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`). - let empty_arms_are_unreachable = place_validity.is_known_valid() + let empty_arms_are_unreachable = place.validity.is_known_valid() && (is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on() || mcx.tycx.is_min_exhaustive_patterns_feature_on()); @@ -1503,11 +1520,9 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( split_ctors.push(Constructor::Missing); } - // Decide what constructors to report. - let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); - let always_report_all = is_top_level && !is_integers; - // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". - let report_individual_missing_ctors = always_report_all || !all_missing; + // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". At the top + // level we prefer to list all constructors. + let report_individual_missing_ctors = place.is_scrutinee || !all_missing; // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() => // split_ctors.contains(Missing)`. The converse usually holds except when // `!place_validity.is_known_valid()`. @@ -1524,9 +1539,9 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( // strictly fewer rows. In that case we can sometimes skip it. See the top of the file for // details. let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty(); - let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant); + let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant)?; let mut witnesses = ensure_sufficient_stack(|| { - compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) + compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix) })?; // Transform witnesses for `spec_matrix` into witnesses for `matrix`. @@ -1576,7 +1591,7 @@ pub enum Usefulness<'p, Cx: TypeCx> { /// The arm is useful. This additionally carries a set of or-pattern branches that have been /// found to be redundant despite the overall arm being useful. Used only in the presence of /// or-patterns, otherwise it stays empty. - Useful(Vec<&'p DeconstructedPat<'p, Cx>>), + Useful(Vec<&'p DeconstructedPat>), /// The arm is redundant and can be removed without changing the behavior of the match /// expression. Redundant, @@ -1592,16 +1607,16 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> { } /// Computes whether a match is exhaustive and which of its arms are useful. -#[instrument(skip(cx, arms), level = "debug")] +#[instrument(skip(tycx, arms), level = "debug")] pub fn compute_match_usefulness<'p, Cx: TypeCx>( - cx: MatchCtxt<'_, Cx>, + tycx: &Cx, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Result, Cx::Error> { + let cx = UsefulnessCtxt { tycx }; let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity); - let non_exhaustiveness_witnesses = - compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?; + let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(cx, &mut matrix)?; let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column(); let arm_usefulness: Vec<_> = arms diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 90803c20d4312..e7a32771f350d 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -16,5 +16,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_ty_utils = { path = "../rustc_ty_utils" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a64b06e70d6bc..6d8e7ba937eee 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -5,8 +5,6 @@ #![feature(associated_type_defaults)] #![feature(try_blocks)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -21,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind}; +use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind}; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgs; @@ -98,9 +96,6 @@ trait DefIdVisitor<'tcx> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow { self.skeleton().visit_trait(trait_ref) } - fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow { - self.skeleton().visit_projection_ty(projection) - } fn visit_predicates( &mut self, predicates: ty::GenericPredicates<'tcx>, @@ -173,6 +168,10 @@ where { type BreakTy = V::BreakTy; + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { + self.visit_clause(p.as_clause().unwrap()) + } + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { let tcx = self.def_id_visitor.tcx(); // GenericArgs are not visited here because they are visited below @@ -182,6 +181,7 @@ where | ty::Foreign(def_id) | ty::FnDef(def_id, ..) | ty::Closure(def_id, ..) + | ty::CoroutineClosure(def_id, ..) | ty::Coroutine(def_id, ..) => { self.def_id_visitor.visit_def_id(def_id, "type", &ty)?; if V::SHALLOW { @@ -1075,6 +1075,14 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { } } +impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> { + type BreakTy = (); + fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> ControlFlow<()> { + self.span = span; + value.visit_with(&mut self.skeleton()) + } +} + impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_nested_body(&mut self, body_id: hir::BodyId) { let old_maybe_typeck_results = @@ -1085,18 +1093,15 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { self.span = hir_ty.span; - if let Some(typeck_results) = self.maybe_typeck_results { - // Types in bodies. - if self.visit(typeck_results.node_type(hir_ty.hir_id)).is_break() { - return; - } - } else { - // Types in signatures. - // FIXME: This is very ineffective. Ideally each HIR type should be converted - // into a semantic type only once and the result should be cached somehow. - if self.visit(rustc_hir_analysis::hir_ty_to_ty(self.tcx, hir_ty)).is_break() { - return; - } + if self + .visit( + self.maybe_typeck_results + .unwrap_or_else(|| span_bug!(hir_ty.span, "`hir::Ty` outside of a body")) + .node_type(hir_ty.hir_id), + ) + .is_break() + { + return; } intravisit::walk_ty(self, hir_ty); @@ -1104,56 +1109,20 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { self.span = inf.span; - if let Some(typeck_results) = self.maybe_typeck_results { - if let Some(ty) = typeck_results.node_type_opt(inf.hir_id) { - if self.visit(ty).is_break() { - return; - } - } else { - // FIXME: check types of const infers here. + if let Some(ty) = self + .maybe_typeck_results + .unwrap_or_else(|| span_bug!(inf.span, "`hir::InferArg` outside of a body")) + .node_type_opt(inf.hir_id) + { + if self.visit(ty).is_break() { + return; } } else { - span_bug!(self.span, "`hir::InferArg` outside of a body"); + // FIXME: check types of const infers here. } intravisit::walk_inf(self, inf); } - fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { - self.span = trait_ref.path.span; - if self.maybe_typeck_results.is_some() { - // Privacy of traits in bodies is checked as a part of trait object types. - } else { - let bounds = rustc_hir_analysis::hir_trait_to_predicates( - self.tcx, - trait_ref, - // NOTE: This isn't really right, but the actual type doesn't matter here. It's - // just required by `ty::TraitRef`. - self.tcx.types.never, - ); - - for (clause, _) in bounds.clauses() { - match clause.kind().skip_binder() { - ty::ClauseKind::Trait(trait_predicate) => { - if self.visit_trait(trait_predicate.trait_ref).is_break() { - return; - } - } - ty::ClauseKind::Projection(proj_predicate) => { - let term = self.visit(proj_predicate.term); - if term.is_break() - || self.visit_projection_ty(proj_predicate.projection_ty).is_break() - { - return; - } - } - _ => {} - } - } - } - - intravisit::walk_trait_ref(self, trait_ref); - } - // Check types of expressions fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if self.check_expr_pat_type(expr.hir_id, expr.span) { @@ -1726,7 +1695,26 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // inferred types of expressions and patterns. let span = tcx.def_span(module_def_id); let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span }; - tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor); + + let module = tcx.hir_module_items(module_def_id); + for def_id in module.definitions() { + rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor); + + if let Some(body_id) = tcx.hir().maybe_body_owned_by(def_id) { + visitor.visit_nested_body(body_id); + } + } + + for id in module.items() { + if let ItemKind::Impl(i) = tcx.hir().item(id).kind { + if let Some(item) = i.of_trait { + let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap(); + let trait_ref = trait_ref.instantiate_identity(); + visitor.span = item.path.span; + visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path()); + } + } + } } fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 818a67a7debf6..0fe5b9c664a35 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -6,8 +6,6 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![allow(rustc::potential_query_instability, unused_parens)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 2faa4876798e0..b6ac54a9ab59b 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -52,7 +52,7 @@ impl From for QueryInvocationId { } } -pub(crate) struct MarkFrame<'a> { +pub struct MarkFrame<'a> { index: SerializedDepNodeIndex, parent: Option<&'a MarkFrame<'a>>, } @@ -754,7 +754,6 @@ impl DepGraphData { &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option<()> { let dep_dep_node_color = self.colors.get(parent_dep_node_index); @@ -861,7 +860,7 @@ impl DepGraphData { let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); for dep_dep_node_index in prev_deps { - self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node, Some(&frame))?; + self.try_mark_parent_green(qcx, dep_dep_node_index, Some(&frame))?; } // If we got here without hitting a `return` that means that all diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 9b66b9a48d905..416f556f57d28 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -4,8 +4,6 @@ #![feature(min_specialization)] #![feature(let_chains)] #![allow(rustc::potential_query_instability, internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index c8ec10cad17c4..0747685c35c46 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -118,17 +118,27 @@ resolve_forward_declared_generic_param = .label = defaulted generic parameters cannot be forward declared resolve_generic_params_from_outer_item = - can't use generic parameters from outer item - .label = use of generic parameter from outer item + can't use {$is_self -> + [true] `Self` + *[false] generic parameters + } from outer item + .label = use of {$is_self -> + [true] `Self` + *[false] generic parameter + } from outer item .refer_to_type_directly = refer to the type directly here instead .suggestion = try introducing a local generic parameter here +resolve_generic_params_from_outer_item_const = a `const` is a separate item from the item that contains it + resolve_generic_params_from_outer_item_const_param = const parameter from outer item resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl` resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here +resolve_generic_params_from_outer_item_static = a `static` is a separate item from the item that contains it + resolve_generic_params_from_outer_item_ty_param = type parameter from outer item @@ -289,6 +299,12 @@ resolve_underscore_lifetime_name_cannot_be_used_here = `'_` cannot be used here .note = `'_` is a reserved lifetime name +resolve_unexpected_res_change_ty_to_const_param_sugg = + you might have meant to write a const parameter here + +resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg = + if you meant to collect the rest of the slice in `{$ident}`, use the at operator + resolve_unreachable_label = use of unreachable label `{$name}` .label = unreachable label `{$name}` diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f3a6eb65a7235..d91a865e38aba 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -561,13 +561,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolution_error: ResolutionError<'a>, ) -> DiagnosticBuilder<'_> { match resolution_error { - ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => { + ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => { use errs::GenericParamsFromOuterItemLabel as Label; + let static_or_const = match def_kind { + DefKind::Static(_) => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), + DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), + _ => None, + }; + let is_self = matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }); let mut err = errs::GenericParamsFromOuterItem { span, label: None, refer_to_type_directly: None, sugg: None, + static_or_const, + is_self, }; let sm = self.tcx.sess.source_map(); diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 50ff09feb4d9b..adc4cd911a79e 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::codes::*; +use rustc_errors::{codes::*, Applicability}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ symbol::{Ident, Symbol}, @@ -45,6 +45,17 @@ pub(crate) struct GenericParamsFromOuterItem { pub(crate) refer_to_type_directly: Option, #[subdiagnostic] pub(crate) sugg: Option, + #[subdiagnostic] + pub(crate) static_or_const: Option, + pub(crate) is_self: bool, +} + +#[derive(Subdiagnostic)] +pub(crate) enum GenericParamsFromOuterItemStaticOrConst { + #[note(resolve_generic_params_from_outer_item_static)] + Static, + #[note(resolve_generic_params_from_outer_item_const)] + Const, } #[derive(Subdiagnostic)] @@ -787,3 +798,30 @@ pub(crate) struct IsNotDirectlyImportable { pub(crate) span: Span, pub(crate) target: Ident, } + +#[derive(Subdiagnostic)] +#[suggestion( + resolve_unexpected_res_change_ty_to_const_param_sugg, + code = "const ", + style = "verbose" +)] +pub(crate) struct UnexpectedResChangeTyToConstParamSugg { + #[primary_span] + pub span: Span, + #[applicability] + pub applicability: Applicability, +} + +#[derive(Subdiagnostic)] +#[suggestion( + resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg, + code = "{snippet}", + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg { + #[primary_span] + pub span: Span, + pub ident: Ident, + pub snippet: String, +} diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 7fb9db16e9c7b..e47f2bdd4d2b1 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -10,9 +10,7 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; -use crate::late::{ - ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind, -}; +use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind}; use crate::macros::{sub_namespace_match, MacroRulesScope}; use crate::BindingKey; use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; @@ -1090,7 +1088,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { | RibKind::ForwardGenericParamBan => { // Nothing to do. Continue. } - RibKind::Item(_) | RibKind::AssocItem => { + RibKind::Item(..) | RibKind::AssocItem => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -1155,7 +1153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => { for rib in ribs { - let has_generic_params: HasGenericParams = match rib.kind { + let (has_generic_params, def_kind) = match rib.kind { RibKind::Normal | RibKind::FnOrCoroutine | RibKind::Module(..) @@ -1213,7 +1211,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // This was an attempt to use a type parameter outside its scope. - RibKind::Item(has_generic_params) => has_generic_params, + RibKind::Item(has_generic_params, def_kind) => { + (has_generic_params, def_kind) + } RibKind::ConstParamTy => { if let Some(span) = finalize { self.report_error( @@ -1231,7 +1231,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(span) = finalize { self.report_error( span, - ResolutionError::GenericParamsFromOuterItem(res, has_generic_params), + ResolutionError::GenericParamsFromOuterItem( + res, + has_generic_params, + def_kind, + ), ); } return Res::Err; @@ -1239,7 +1243,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Res::Def(DefKind::ConstParam, _) => { for rib in ribs { - let has_generic_params = match rib.kind { + let (has_generic_params, def_kind) = match rib.kind { RibKind::Normal | RibKind::FnOrCoroutine | RibKind::Module(..) @@ -1276,7 +1280,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { continue; } - RibKind::Item(has_generic_params) => has_generic_params, + RibKind::Item(has_generic_params, def_kind) => { + (has_generic_params, def_kind) + } RibKind::ConstParamTy => { if let Some(span) = finalize { self.report_error( @@ -1295,7 +1301,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(span) = finalize { self.report_error( span, - ResolutionError::GenericParamsFromOuterItem(res, has_generic_params), + ResolutionError::GenericParamsFromOuterItem( + res, + has_generic_params, + def_kind, + ), ); } return Res::Err; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9788fcb3c7d36..6bd221ff05874 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -23,6 +23,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; +use rustc_metadata::creader::CStore; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; @@ -185,7 +186,7 @@ pub(crate) enum RibKind<'a> { FnOrCoroutine, /// We passed through an item scope. Disallow upvars. - Item(HasGenericParams), + Item(HasGenericParams, DefKind), /// We're in a constant item. Can't refer to dynamic stuff. /// @@ -225,7 +226,7 @@ impl RibKind<'_> { | RibKind::MacroDefinition(_) | RibKind::ConstParamTy | RibKind::InlineAsmSym => false, - RibKind::AssocItem | RibKind::Item(_) | RibKind::ForwardGenericParamBan => true, + RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true, } } @@ -594,9 +595,9 @@ struct DiagnosticMetadata<'ast> { /// The current trait (used to suggest). current_item: Option<&'ast Item>, - /// When processing generics and encountering a type not found, suggest introducing a type - /// param. - currently_processing_generics: bool, + /// When processing generic arguments and encountering an unresolved ident not found, + /// suggest introducing a type or const param depending on the context. + currently_processing_generic_args: bool, /// The current enclosing (non-closure) function (used for better errors). current_function: Option<(FnKind<'ast>, Span)>, @@ -869,11 +870,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); + let def_kind = self.r.local_def_kind(foreign_item.id); match foreign_item.kind { ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: foreign_item.id, kind: LifetimeBinderKind::Item, @@ -885,7 +887,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ForeignItemKind::Fn(box Fn { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: foreign_item.id, kind: LifetimeBinderKind::Function, @@ -895,7 +897,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ); } ForeignItemKind::Static(..) => { - self.with_static_rib(|this| { + self.with_static_rib(def_kind, |this| { visit::walk_foreign_item(this, foreign_item); }); } @@ -1069,7 +1071,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, fn visit_generic_arg(&mut self, arg: &'ast GenericArg) { debug!("visit_generic_arg({:?})", arg); - let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true); + let prev = replace(&mut self.diagnostic_metadata.currently_processing_generic_args, true); match arg { GenericArg::Type(ref ty) => { // We parse const arguments as path types as we cannot distinguish them during @@ -1100,7 +1102,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, }, ); - self.diagnostic_metadata.currently_processing_generics = prev; + self.diagnostic_metadata.currently_processing_generic_args = prev; return; } } @@ -1113,7 +1115,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No)) } } - self.diagnostic_metadata.currently_processing_generics = prev; + self.diagnostic_metadata.currently_processing_generic_args = prev; } fn visit_assoc_constraint(&mut self, constraint: &'ast AssocConstraint) { @@ -1644,7 +1646,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { debug!(?rib.kind); match rib.kind { LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { - let res = self.create_fresh_lifetime(lifetime.id, lifetime.ident, binder); + let res = self.create_fresh_lifetime(lifetime.ident, binder); self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } @@ -1736,7 +1738,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, binder: NodeId) -> LifetimeRes { + fn create_fresh_lifetime(&mut self, ident: Ident, binder: NodeId) -> LifetimeRes { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); debug!(?ident.span); @@ -1757,7 +1759,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_elided_lifetimes_in_path( &mut self, - path_id: NodeId, partial_res: PartialRes, path: &[Segment], source: PathSource<'_>, @@ -1890,7 +1891,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Group all suggestions into the first record. let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for id in node_ids { - let res = self.create_fresh_lifetime(id, ident, binder); + let res = self.create_fresh_lifetime(ident, binder); self.record_lifetime_res( id, res, @@ -2266,10 +2267,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) { debug!("resolve_adt"); + let kind = self.r.local_def_kind(item.id); self.with_current_self_item(item, |this| { this.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2343,11 +2345,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let name = item.ident.name; debug!("(resolving item) resolving {} ({:?})", name, item.kind); + let def_kind = self.r.local_def_kind(item.id); match item.kind { ItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2360,7 +2363,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Fn(box Fn { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Function, @@ -2399,7 +2402,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2420,7 +2423,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2454,7 +2457,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { - self.with_static_rib(|this| { + self.with_static_rib(def_kind, |this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.visit_ty(ty); }); @@ -2469,11 +2472,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(if self.r.tcx.features().generic_const_items { - HasGenericParams::Yes(generics.span) - } else { - HasGenericParams::No - }), + RibKind::Item( + if self.r.tcx.features().generic_const_items { + HasGenericParams::Yes(generics.span) + } else { + HasGenericParams::No + }, + def_kind, + ), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::ConstItem, @@ -2558,7 +2564,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut add_bindings_for_ns = |ns| { let parent_rib = self.ribs[ns] .iter() - .rfind(|r| matches!(r.kind, RibKind::Item(_))) + .rfind(|r| matches!(r.kind, RibKind::Item(..))) .expect("associated item outside of an item"); seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); }; @@ -2693,8 +2699,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.label_ribs.pop(); } - fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) { - let kind = RibKind::Item(HasGenericParams::No); + fn with_static_rib(&mut self, def_kind: DefKind, f: impl FnOnce(&mut Self)) { + let kind = RibKind::Item(HasGenericParams::No, def_kind); self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) } @@ -2875,7 +2881,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // If applicable, create a rib for the type parameters. self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)), LifetimeRibKind::Generics { span: generics.span, binder: item_id, @@ -3935,7 +3941,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if record_partial_res == RecordPartialRes::Yes { // Avoid recording definition of `A::B` in `::B::C`. self.r.record_partial_res(node_id, partial_res); - self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); + self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span); } partial_res @@ -4541,14 +4547,20 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(res) = res && let Some(def_id) = res.opt_def_id() && !def_id.is_local() - && self.r.tcx.crate_types().contains(&CrateType::ProcMacro) - && matches!( - self.r.tcx.sess.opts.resolve_doc_links, - ResolveDocLinks::ExportedMetadata - ) { - // Encoding foreign def ids in proc macro crate metadata will ICE. - return None; + if self.r.tcx.crate_types().contains(&CrateType::ProcMacro) + && matches!( + self.r.tcx.sess.opts.resolve_doc_links, + ResolveDocLinks::ExportedMetadata + ) + { + // Encoding foreign def ids in proc macro crate metadata will ICE. + return None; + } + // Doc paths should be resolved speculatively and should not produce any + // diagnostics, but if they are indeed resolved, then we need to keep the + // corresponding crate alive. + CStore::from_tcx_mut(self.r.tcx).set_used_recursively(def_id.krate); } res }); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index a4c041f1ff247..5d712461993d8 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -444,6 +444,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } self.suggest_bare_struct_literal(&mut err); + self.suggest_changing_type_to_const_param(&mut err, res, source, span); if self.suggest_pattern_match_with_let(&mut err, source, span) { // Fallback label. @@ -452,7 +453,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } self.suggest_self_or_self_ref(&mut err, path, span); - self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error); + self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error); if self.suggest_self_ty(&mut err, source, path, span) || self.suggest_self_value(&mut err, source, path, span) { @@ -491,7 +492,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { (err, candidates) } - fn detect_assoct_type_constraint_meant_as_path( + fn detect_assoc_type_constraint_meant_as_path( &self, err: &mut Diagnostic, base_error: &BaseError, @@ -699,7 +700,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err.span_suggestion_verbose( span.shrink_to_lo(), msg, - "self.".to_string(), + "self.", Applicability::MachineApplicable, ); } @@ -710,7 +711,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err.span_suggestion_verbose( span.shrink_to_lo(), format!("you might have meant to {}", candidate.action()), - "Self::".to_string(), + "Self::", Applicability::MachineApplicable, ); } @@ -799,7 +800,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { false, ) = (source, res, is_macro) { - if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object { + if let Some(bounds @ [first_bound, .., last_bound]) = + self.diagnostic_metadata.current_trait_object + { fallback = true; let spans: Vec = bounds .iter() @@ -807,9 +810,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { .filter(|&sp| sp != base_error.span) .collect(); - let start_span = bounds[0].span(); + let start_span = first_bound.span(); // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><) - let end_span = bounds.last().unwrap().span(); + let end_span = last_bound.span(); // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar) let last_bound_span = spans.last().cloned().unwrap(); let mut multi_span: MultiSpan = spans.clone().into(); @@ -1074,24 +1077,34 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, path: &[Segment], ) { - if let Some(pat) = self.diagnostic_metadata.current_pat - && let ast::PatKind::Range(Some(start), None, range) = &pat.kind - && let ExprKind::Path(None, range_path) = &start.kind + let Some(pat) = self.diagnostic_metadata.current_pat else { return }; + let (bound, side, range) = match &pat.kind { + ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range), + ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range), + _ => return, + }; + if let ExprKind::Path(None, range_path) = &bound.kind && let [segment] = &range_path.segments[..] && let [s] = path && segment.ident == s.ident + && segment.ident.span.eq_ctxt(range.span) { - // We've encountered `[first, rest..]` where the user might have meant - // `[first, rest @ ..]` (#88404). - err.span_suggestion_verbose( - segment.ident.span.between(range.span), - format!( - "if you meant to collect the rest of the slice in `{}`, use the at operator", - segment.ident, - ), - " @ ", - Applicability::MaybeIncorrect, - ); + // We've encountered `[first, rest..]` (#88404) or `[first, ..rest]` (#120591) + // where the user might have meant `[first, rest @ ..]`. + let (span, snippet) = match side { + Side::Start => (segment.ident.span.between(range.span), " @ ".into()), + Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)), + }; + err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { + span, + ident: segment.ident, + snippet, + }); + } + + enum Side { + Start, + End, } } @@ -1136,6 +1149,55 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { } } + fn suggest_changing_type_to_const_param( + &mut self, + err: &mut Diagnostic, + res: Option, + source: PathSource<'_>, + span: Span, + ) { + let PathSource::Trait(_) = source else { return }; + + // We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway. + let applicability = match res { + Some(Res::PrimTy(PrimTy::Int(_) | PrimTy::Uint(_) | PrimTy::Bool | PrimTy::Char)) => { + Applicability::MachineApplicable + } + // FIXME(const_generics): Add `DefKind::TyParam` and `SelfTyParam` once we support generic + // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the + // benefits of including them here outweighs the small number of false positives. + Some(Res::Def(DefKind::Struct | DefKind::Enum, _)) + if self.r.tcx.features().adt_const_params => + { + Applicability::MaybeIncorrect + } + _ => return, + }; + + let Some(item) = self.diagnostic_metadata.current_item else { return }; + let Some(generics) = item.kind.generics() else { return }; + + let param = generics.params.iter().find_map(|param| { + // Only consider type params with exactly one trait bound. + if let [bound] = &*param.bounds + && let ast::GenericBound::Trait(tref, ast::TraitBoundModifiers::NONE) = bound + && tref.span == span + && param.ident.span.eq_ctxt(span) + { + Some(param.ident.span) + } else { + None + } + }); + + if let Some(param) = param { + err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg { + span: param.shrink_to_lo(), + applicability, + }); + } + } + fn suggest_pattern_match_with_let( &mut self, err: &mut Diagnostic, @@ -2419,10 +2481,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let mut iter = ident.chars().map(|c| c.is_uppercase()); let single_uppercase_char = matches!(iter.next(), Some(true)) && matches!(iter.next(), None); - if !self.diagnostic_metadata.currently_processing_generics && !single_uppercase_char { + if !self.diagnostic_metadata.currently_processing_generic_args && !single_uppercase_char { return None; } - match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generics) { + match (self.diagnostic_metadata.current_item, single_uppercase_char, self.diagnostic_metadata.currently_processing_generic_args) { (Some(Item { kind: ItemKind::Fn(..), ident, .. }), _, _) if ident.name == sym::main => { // Ignore `fn main()` as we don't want to suggest `fn main()` } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9d09d060b59b8..6c0f2b893474e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -17,7 +17,9 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![allow(rustdoc::private_intra_doc_links)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![allow(internal_features)] #[macro_use] @@ -184,7 +186,7 @@ struct BindingError { #[derive(Debug)] enum ResolutionError<'a> { /// Error E0401: can't use type or const parameters from outer item. - GenericParamsFromOuterItem(Res, HasGenericParams), + GenericParamsFromOuterItem(Res, HasGenericParams, DefKind), /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. NameAlreadyUsedInParameterList(Symbol, Span), @@ -1217,6 +1219,10 @@ impl<'tcx> Resolver<'_, 'tcx> { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } + fn local_def_kind(&self, node: NodeId) -> DefKind { + self.tcx.def_kind(self.local_def_id(node)) + } + /// Adds a definition with a parent definition. fn create_def( &mut self, @@ -1625,6 +1631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.tcx .sess .time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate))); + self.crate_loader(|c| c.unload_unused_crates()); }); // Make sure we don't mutate the cstore from here on. diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index a6bf289a76a4c..170cc1268c39d 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1,10 +1,9 @@ //! A bunch of methods and structures more or less related to resolving macros and //! interface provided by `Resolver` to macro expander. -use crate::errors::{ - self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope, - MacroExpectedFound, RemoveSurroundingDerive, -}; +use crate::errors::CannotDetermineMacroResolution; +use crate::errors::{self, AddAsNonDerive, CannotFindIdentInThisScope}; +use crate::errors::{MacroExpectedFound, RemoveSurroundingDerive}; use crate::Namespace::*; use crate::{BuiltinMacroState, Determinacy, MacroData}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; @@ -15,7 +14,7 @@ use rustc_ast_pretty::pprust; use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; -use rustc_errors::{codes::*, struct_span_code_err, Applicability}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, StashKey}; use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; @@ -25,9 +24,8 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; use rustc_middle::ty::{TyCtxt, Visibility}; -use rustc_session::lint::builtin::{ - LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, -}; +use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; +use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE}; use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::feature_err; @@ -703,21 +701,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // situations should be reported as errors, so this is a bug. this.dcx().span_delayed_bug(span, "inconsistent resolution for a macro"); } - } else { + } else if this.tcx.dcx().has_errors().is_none() && this.privacy_errors.is_empty() { // It's possible that the macro was unresolved (indeterminate) and silently // expanded into a dummy fragment for recovery during expansion. // Now, post-expansion, the resolution may succeed, but we can't change the // past and need to report an error. // However, non-speculative `resolve_path` can successfully return private items // even if speculative `resolve_path` returned nothing previously, so we skip this - // less informative error if the privacy error is reported elsewhere. - if this.privacy_errors.is_empty() { - this.dcx().emit_err(CannotDetermineMacroResolution { - span, - kind: kind.descr(), - path: Segment::names_to_string(path), - }); - } + // less informative error if no other error is reported elsewhere. + + let err = this.dcx().create_err(CannotDetermineMacroResolution { + span, + kind: kind.descr(), + path: Segment::names_to_string(path), + }); + err.stash(span, StashKey::UndeterminedMacroResolution); } }; diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 9c34aa9395764..95833f532f4d8 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -17,8 +17,6 @@ #![feature(ptr_sub_ptr)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 0d6328fbb071c..58e1394c09071 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -4,8 +4,6 @@ #![feature(rustc_attrs)] #![feature(map_many_mut)] #![feature(iter_intersperse)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d8d201d5f244d..ea93ac5841fe9 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1572,6 +1572,8 @@ options! { dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves (default: no)"), + direct_access_external_data: Option = (None, parse_opt_bool, [TRACKED], + "Direct or use GOT indirect to reference external data symbols"), dual_proc_macros: bool = (false, parse_bool, [TRACKED], "load proc macros for both target and host, but only link to the target (default: no)"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 1cfaa49401dac..8adb0cbcc9d76 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -258,7 +258,7 @@ impl ParseSess { } } - pub fn with_silent_emitter(fatal_note: Option) -> Self { + pub fn with_silent_emitter(fatal_note: String) -> Self { let fallback_bundle = fallback_fluent_bundle(Vec::new(), false); let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let fatal_dcx = DiagCtxt::with_tty_emitter(None, fallback_bundle).disable_warnings(); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 3a0ae74dd9215..0c084660761d8 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -288,19 +288,9 @@ impl Session { pub fn finish_diagnostics(&self, registry: &Registry) { self.check_miri_unleashed_features(); self.dcx().print_error_count(registry); - self.emit_future_breakage(); - } - - fn emit_future_breakage(&self) { - if !self.opts.json_future_incompat { - return; - } - - let diags = self.dcx().take_future_breakage_diagnostics(); - if diags.is_empty() { - return; + if self.opts.json_future_incompat { + self.dcx().emit_future_breakage_report(); } - self.dcx().emit_future_breakage_report(diags); } /// Returns true if the crate is a testing one. @@ -325,7 +315,7 @@ impl Session { pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> { // We must include lint errors here. if let Some(reported) = self.dcx().has_errors_or_lint_errors() { - let _ = self.dcx().emit_stashed_diagnostics(); + self.dcx().emit_stashed_diagnostics(); Err(reported) } else { Ok(()) @@ -777,6 +767,13 @@ impl Session { self.opts.unstable_opts.tls_model.unwrap_or(self.target.tls_model) } + pub fn direct_access_external_data(&self) -> Option { + self.opts + .unstable_opts + .direct_access_external_data + .or(self.target.direct_access_external_data) + } + pub fn split_debuginfo(&self) -> SplitDebuginfo { self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index fa52f52d60b99..6bbfcff5e87cc 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -449,7 +449,6 @@ impl RustcInternal for Abi { Abi::PtxKernel => rustc_target::spec::abi::Abi::PtxKernel, Abi::Msp430Interrupt => rustc_target::spec::abi::Abi::Msp430Interrupt, Abi::X86Interrupt => rustc_target::spec::abi::Abi::X86Interrupt, - Abi::AmdGpuKernel => rustc_target::spec::abi::Abi::AmdGpuKernel, Abi::EfiApi => rustc_target::spec::abi::Abi::EfiApi, Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt, Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index 68b564741dc1f..088a836c90182 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -111,7 +111,6 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv { Conv::X86VectorCall => CallConvention::X86VectorCall, Conv::X86_64SysV => CallConvention::X86_64SysV, Conv::X86_64Win64 => CallConvention::X86_64Win64, - Conv::AmdGpuKernel => CallConvention::AmdGpuKernel, Conv::AvrInterrupt => CallConvention::AvrInterrupt, Conv::AvrNonBlockingInterrupt => CallConvention::AvrNonBlockingInterrupt, Conv::RiscvInterrupt { .. } => CallConvention::RiscvInterrupt, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index e433460e2ad9d..501d6f7d304ef 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -257,6 +257,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( indices.iter().map(|idx| idx.stable(tables)).collect(), ), + DebugAssertions => stable_mir::mir::NullOp::DebugAssertions, } } } @@ -538,6 +539,9 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { tables.tcx.coroutine_movability(*def_id).stable(tables), ) } + mir::AggregateKind::CoroutineClosure(..) => { + todo!("FIXME(async_closures): Lower these to SMIR") + } } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index cffbdc376f1fa..959a17d24b7ce 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -223,7 +223,6 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { abi::Abi::PtxKernel => Abi::PtxKernel, abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt, abi::Abi::X86Interrupt => Abi::X86Interrupt, - abi::Abi::AmdGpuKernel => Abi::AmdGpuKernel, abi::Abi::EfiApi => Abi::EfiApi, abi::Abi::AvrInterrupt => Abi::AvrInterrupt, abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, @@ -384,6 +383,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { tables.closure_def(*def_id), generic_args.stable(tables), )), + ty::CoroutineClosure(..) => todo!("FIXME(async_closures): Lower these to SMIR"), ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine( tables.coroutine_def(*def_id), generic_args.stable(tables), @@ -799,6 +799,8 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::FnPtrAddrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } + | ty::InstanceDef::ConstructCoroutineInClosureShim { .. } + | ty::InstanceDef::CoroutineKindShim { .. } | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 3d26efec5a654..527938daae410 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1154,6 +1154,8 @@ pub enum DesugaringKind { Await, ForLoop, WhileLoop, + /// `async Fn()` bound modifier + BoundModifier, } impl DesugaringKind { @@ -1169,6 +1171,7 @@ impl DesugaringKind { DesugaringKind::OpaqueTy => "`impl Trait`", DesugaringKind::ForLoop => "`for` loop", DesugaringKind::WhileLoop => "`while` loop", + DesugaringKind::BoundModifier => "trait bound modifier", } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ea6766ea583be..7d95a0bc47821 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,8 +17,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![deny(rustc::diagnostic_outside_of_impl)] -#![deny(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] @@ -2477,10 +2475,9 @@ where pub struct ErrorGuaranteed(()); impl ErrorGuaranteed { - /// To be used only if you really know what you are doing... ideally, we would find a way to - /// eliminate all calls to this method. - #[deprecated = "`Session::span_delayed_bug` should be preferred over this function"] - pub fn unchecked_claim_error_was_emitted() -> Self { + /// Don't use this outside of `DiagCtxtInner::emit_diagnostic`! + #[deprecated = "should only be used in `DiagCtxtInner::emit_diagnostic`"] + pub fn unchecked_error_guaranteed() -> Self { ErrorGuaranteed(()) } } diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 5788d11ed43ca..51f8aa04e8a7f 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -1,5 +1,7 @@ use super::*; +use rustc_data_structures::sync::FreezeLock; + fn init_source_map() -> SourceMap { let sm = SourceMap::new(FilePathMapping::empty()); sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string()); @@ -263,53 +265,6 @@ fn t10() { ); } -/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`. -trait SourceMapExtension { - fn span_substr( - &self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize, - ) -> Span; -} - -impl SourceMapExtension for SourceMap { - fn span_substr( - &self, - file: &Lrc, - source_text: &str, - substring: &str, - n: usize, - ) -> Span { - eprintln!( - "span_substr(file={:?}/{:?}, substring={:?}, n={})", - file.name, file.start_pos, substring, n - ); - let mut i = 0; - let mut hi = 0; - loop { - let offset = source_text[hi..].find(substring).unwrap_or_else(|| { - panic!( - "source_text `{}` does not have {} occurrences of `{}`, only {}", - source_text, n, substring, i - ); - }); - let lo = hi + offset; - hi = lo + substring.len(); - if i == n { - let span = Span::with_root_ctxt( - BytePos(lo as u32 + file.start_pos.0), - BytePos(hi as u32 + file.start_pos.0), - ); - assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring); - return span; - } - i += 1; - } - } -} - // Takes a unix-style path and returns a platform specific path. fn path(p: &str) -> PathBuf { path_str(p).into() diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a54b928b908a7..ed6e69d919949 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -167,6 +167,9 @@ symbols! { Break, C, CStr, + CallFuture, + CallMutFuture, + CallOnceFuture, Capture, Center, Cleanup, @@ -318,6 +321,7 @@ symbols! { TyCtxt, TyKind, Unknown, + Upvars, Vec, VecDeque, Wrapper, @@ -420,9 +424,11 @@ symbols! { async_closure, async_fn, async_fn_in_trait, + async_fn_kind_helper, async_fn_mut, async_fn_once, async_fn_track_caller, + async_fn_traits, async_for_loop, async_iterator, async_iterator_poll_next, @@ -1789,7 +1795,6 @@ symbols! { warn, wasm_abi, wasm_import_module, - wasm_preview2, wasm_target_feature, while_let, windows, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 4a5f58443bc29..646649293fc76 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -64,16 +64,29 @@ pub(super) fn mangle<'tcx>( ) .unwrap(); - if let ty::InstanceDef::ThreadLocalShim(..) = instance.def { - let _ = printer.write_str("{{tls-shim}}"); - } - - if let ty::InstanceDef::VTableShim(..) = instance.def { - let _ = printer.write_str("{{vtable-shim}}"); - } - - if let ty::InstanceDef::ReifyShim(..) = instance.def { - let _ = printer.write_str("{{reify-shim}}"); + match instance.def { + ty::InstanceDef::ThreadLocalShim(..) => { + printer.write_str("{{tls-shim}}").unwrap(); + } + ty::InstanceDef::VTableShim(..) => { + printer.write_str("{{vtable-shim}}").unwrap(); + } + ty::InstanceDef::ReifyShim(..) => { + printer.write_str("{{reify-shim}}").unwrap(); + } + // FIXME(async_closures): This shouldn't be needed when we fix + // `Instance::ty`/`Instance::def_id`. + ty::InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } + | ty::InstanceDef::CoroutineKindShim { target_kind, .. } => match target_kind { + ty::ClosureKind::Fn => unreachable!(), + ty::ClosureKind::FnMut => { + printer.write_str("{{fn-mut-shim}}").unwrap(); + } + ty::ClosureKind::FnOnce => { + printer.write_str("{{fn-once-shim}}").unwrap(); + } + }, + _ => {} } printer.path.finish(hash) @@ -211,6 +224,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), // The `pretty_print_type` formatting of array size depends on @@ -281,7 +295,11 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { // Similar to `pretty_path_qualified`, but for the other // types that are printed as paths (see `print_type` above). match self_ty.kind() { - ty::FnDef(..) | ty::Alias(..) | ty::Closure(..) | ty::Coroutine(..) + ty::FnDef(..) + | ty::Alias(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) if trait_ref.is_none() => { self.print_type(self_ty) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 362aaca63642e..02bb1fde75c1b 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -91,8 +91,6 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; 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 0cc82ac7506cb..9d1b92e106803 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 @@ -628,7 +628,9 @@ fn encode_ty<'tcx>( } // Function types - ty::FnDef(def_id, args) | ty::Closure(def_id, args) => { + ty::FnDef(def_id, args) + | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) => { // u[IE], where is , // as vendor extended type. let mut s = String::new(); @@ -895,6 +897,10 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options)); } + ty::CoroutineClosure(def_id, args) => { + ty = Ty::new_coroutine_closure(tcx, *def_id, transform_args(tcx, args, options)); + } + ty::Coroutine(def_id, args) => { ty = Ty::new_coroutine(tcx, *def_id, transform_args(tcx, args, options)); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 16ebda55a7a51..530221555c52e 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -46,6 +46,13 @@ pub(super) fn mangle<'tcx>( ty::InstanceDef::VTableShim(_) => Some("vtable"), ty::InstanceDef::ReifyShim(_) => Some("reify"), + ty::InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } + | ty::InstanceDef::CoroutineKindShim { target_kind, .. } => match target_kind { + ty::ClosureKind::Fn => unreachable!(), + ty::ClosureKind::FnMut => Some("fn_mut"), + ty::ClosureKind::FnOnce => Some("fn_once"), + }, + _ => None, }; @@ -386,6 +393,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { | ty::FnDef(def_id, args) | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) | ty::Closure(def_id, args) + | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => { self.print_def_path(def_id, args)?; } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 1c83039047e05..db721212f8e91 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -705,7 +705,6 @@ pub enum Conv { X86_64SysV, X86_64Win64, - AmdGpuKernel, AvrInterrupt, AvrNonBlockingInterrupt, @@ -887,7 +886,6 @@ impl FromStr for Conv { "X86VectorCall" => Ok(Conv::X86VectorCall), "X86_64SysV" => Ok(Conv::X86_64SysV), "X86_64Win64" => Ok(Conv::X86_64Win64), - "AmdGpuKernel" => Ok(Conv::AmdGpuKernel), "AvrInterrupt" => Ok(Conv::AvrInterrupt), "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt), "RiscvInterrupt(machine)" => { diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs index c613514908141..f3aecaaab984f 100644 --- a/compiler/rustc_target/src/json.rs +++ b/compiler/rustc_target/src/json.rs @@ -110,7 +110,6 @@ impl ToJson for crate::abi::call::Conv { Self::X86VectorCall => "X86VectorCall", Self::X86_64SysV => "X86_64SysV", Self::X86_64Win64 => "X86_64Win64", - Self::AmdGpuKernel => "AmdGpuKernel", Self::AvrInterrupt => "AvrInterrupt", Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt", Self::RiscvInterrupt { kind } => { diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index bffb3681f1309..b19c5b6f28f08 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -17,8 +17,6 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![feature(step_trait)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 1a0aa6f0c4a2e..6231787bb9fdb 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -44,7 +44,6 @@ pub enum Abi { PtxKernel, Msp430Interrupt, X86Interrupt, - AmdGpuKernel, EfiApi, AvrInterrupt, AvrNonBlockingInterrupt, @@ -121,7 +120,6 @@ const AbiDatas: &[AbiData] = &[ AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" }, AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" }, AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" }, - AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel" }, AbiData { abi: Abi::EfiApi, name: "efiapi" }, AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" }, AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" }, @@ -237,10 +235,6 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> { feature: sym::abi_x86_interrupt, explain: "x86-interrupt ABI is experimental and subject to change", }), - "amdgpu-kernel" => Err(AbiDisabled::Unstable { - feature: sym::abi_amdgpu_kernel, - explain: "amdgpu-kernel ABI is experimental and subject to change", - }), "avr-interrupt" | "avr-non-blocking-interrupt" => Err(AbiDisabled::Unstable { feature: sym::abi_avr_interrupt, explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change", @@ -295,22 +289,21 @@ impl Abi { PtxKernel => 19, Msp430Interrupt => 20, X86Interrupt => 21, - AmdGpuKernel => 22, - EfiApi => 23, - AvrInterrupt => 24, - AvrNonBlockingInterrupt => 25, - CCmseNonSecureCall => 26, - Wasm => 27, + EfiApi => 22, + AvrInterrupt => 23, + AvrNonBlockingInterrupt => 24, + CCmseNonSecureCall => 25, + Wasm => 26, // Cross-platform ABIs - System { unwind: false } => 28, - System { unwind: true } => 29, - RustIntrinsic => 30, - RustCall => 31, - PlatformIntrinsic => 32, - Unadjusted => 33, - RustCold => 34, - RiscvInterruptM => 35, - RiscvInterruptS => 36, + System { unwind: false } => 27, + System { unwind: true } => 28, + RustIntrinsic => 29, + RustCall => 30, + PlatformIntrinsic => 31, + Unadjusted => 32, + RustCold => 33, + RiscvInterruptM => 34, + RiscvInterruptS => 35, }; debug_assert!( AbiDatas diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ead3be7fd529b..d04bcb2d78aac 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1543,6 +1543,7 @@ supported_targets! { ("armebv7r-none-eabihf", armebv7r_none_eabihf), ("armv7r-none-eabi", armv7r_none_eabi), ("armv7r-none-eabihf", armv7r_none_eabihf), + ("armv8r-none-eabihf", armv8r_none_eabihf), ("x86_64-pc-solaris", x86_64_pc_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), @@ -1574,7 +1575,6 @@ supported_targets! { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), - ("wasm32-wasi-preview2", wasm32_wasi_preview2), ("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads), ("wasm64-unknown-unknown", wasm64_unknown_unknown), @@ -1887,6 +1887,8 @@ pub struct TargetOptions { /// passed, and cannot be disabled even via `-C`. Corresponds to `llc /// -mattr=$features`. pub features: StaticCow, + /// Direct or use GOT indirect to reference external data symbols + pub direct_access_external_data: Option, /// Whether dynamic linking is available on this target. Defaults to false. pub dynamic_linking: bool, /// Whether dynamic linking can export TLS globals. Defaults to true. @@ -2281,6 +2283,7 @@ impl Default for TargetOptions { asm_args: cvs![], cpu: "generic".into(), features: "".into(), + direct_access_external_data: None, dynamic_linking: false, dll_tls_export: true, only_cdylib: false, @@ -2458,7 +2461,6 @@ impl Target { Win64 { .. } | SysV64 { .. } => self.arch == "x86_64", PtxKernel => self.arch == "nvptx64", Msp430Interrupt => self.arch == "msp430", - AmdGpuKernel => self.arch == "amdgcn", RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]), AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr", Wasm => ["wasm32", "wasm64"].contains(&&self.arch[..]), @@ -2581,6 +2583,12 @@ impl Target { base.$key_name = s as u32; } } ); + ($key_name:ident, Option) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { + base.$key_name = Some(s); + } + } ); ($key_name:ident, Option) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { @@ -3009,6 +3017,7 @@ impl Target { key!(cpu); key!(features); key!(dynamic_linking, bool); + key!(direct_access_external_data, Option); key!(dll_tls_export, bool); key!(only_cdylib, bool); key!(executables, bool); @@ -3263,6 +3272,7 @@ impl ToJson for Target { target_option_val!(cpu); target_option_val!(features); target_option_val!(dynamic_linking); + target_option_val!(direct_access_external_data); target_option_val!(dll_tls_export); target_option_val!(only_cdylib); target_option_val!(executables); diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs new file mode 100644 index 0000000000000..28dba4f7f5d83 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs @@ -0,0 +1,35 @@ +// Targets the Little-endian Cortex-R52 processor (ARMv8-R) + +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "armv8r-none-eabihf".into(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + abi: "eabihf".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + relocation_model: RelocModel::Static, + panic_strategy: PanicStrategy::Abort, + // The Cortex-R52 has two variants with respect to floating-point support: + // 1. fp-armv8, SP-only, with 16 DP (32 SP) registers + // 2. neon-fp-armv8, SP+DP, with 32 DP registers + // Use the lesser of these two options as the default, as it will produce code + // compatible with either variant. + // + // Reference: + // Arm Cortex-R52 Processor Technical Reference Manual + // - Chapter 15 Advanced SIMD and floating-point support + features: "+fp-armv8,-fp64,-d32".into(), + max_atomic_width: Some(64), + emit_debug_gdb_scripts: false, + // GCC defaults to 8 for arm-none here. + c_enum_min_bits: Some(8), + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index 0f05e7c475a83..f43507089865c 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -1,4 +1,4 @@ -use crate::spec::{base, Target, TargetOptions}; +use crate::spec::{base, CodeModel, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -7,10 +7,12 @@ pub fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(), arch: "loongarch64".into(), options: TargetOptions { + code_model: Some(CodeModel::Medium), cpu: "generic".into(), features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + direct_access_external_data: Some(false), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs index 3b1ea8e206f1c..f448017a2a58d 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs @@ -16,7 +16,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, - code_model: Some(CodeModel::Small), + code_model: Some(CodeModel::Medium), ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs index ab9300ef9c723..d636c9599a7be 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs @@ -17,7 +17,7 @@ pub fn target() -> Target { max_atomic_width: Some(64), relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, - code_model: Some(CodeModel::Small), + code_model: Some(CodeModel::Medium), ..Default::default() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs index 06e8f1837637f..0be32cbd77165 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs index 722703d2384fe..cfa9990dac9bd 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "ilp32d".into(), max_atomic_width: Some(32), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs index 40e447dbb8362..762197d7217c7 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -13,6 +15,7 @@ pub fn target() -> Target { llvm_abiname: "lp64d".into(), supported_sanitizers: SanitizerSet::ADDRESS, max_atomic_width: Some(64), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::android::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs index c0969d4e11eb9..e71929a190479 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs index 656e260d094d8..8ea28d6b162cc 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs @@ -1,4 +1,6 @@ -use crate::spec::{base, CodeModel, Target, TargetOptions}; +use std::borrow::Cow; + +use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions}; pub fn target() -> Target { Target { @@ -12,6 +14,7 @@ pub fn target() -> Target { features: "+m,+a,+f,+d,+c".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..base::linux_musl::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs index 389c67f8ae93b..28ea4cc9ece30 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs @@ -72,12 +72,11 @@ //! best we can with this target. Don't start relying on too much here unless //! you know what you're getting in to! -use crate::spec::{base, crt_objects, cvs, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; +use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; pub fn target() -> Target { let mut options = base::wasm::options(); - options.families = cvs!["wasm", "wasi"]; options.os = "wasi".into(); options.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs deleted file mode 100644 index fc44e5d4cbce9..0000000000000 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview2.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! The `wasm32-wasi-preview2` target is the next evolution of the -//! wasm32-wasi target. While the wasi specification is still under -//! active development, the {review 2 iteration is considered an "island -//! of stability" that should allow users to rely on it indefinitely. -//! -//! The `wasi` target is a proposal to define a standardized set of WebAssembly -//! component imports that allow it to interoperate with the host system in a -//! standardized way. This set of imports is intended to empower WebAssembly -//! binaries with host capabilities such as filesystem access, network access, etc. -//! -//! Wasi Preview 2 relies on the WebAssembly component model which is an extension of -//! the core WebAssembly specification which allows interoperability between WebAssembly -//! modules (known as "components") through high-level, shared-nothing APIs instead of the -//! low-level, shared-everything linear memory model of the core WebAssembly specification. -//! -//! You can see more about wasi at and the component model at -//! . - -use crate::spec::crt_objects; -use crate::spec::LinkSelfContainedDefault; -use crate::spec::{base, Target}; - -pub fn target() -> Target { - let mut options = base::wasm::options(); - - options.os = "wasi".into(); - options.env = "preview2".into(); - options.linker = Some("wasm-component-ld".into()); - - options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); - options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); - - // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - options.link_self_contained = LinkSelfContainedDefault::True; - - // Right now this is a bit of a workaround but we're currently saying that - // the target by default has a static crt which we're taking as a signal - // for "use the bundled crt". If that's turned off then the system's crt - // will be used, but this means that default usage of this target doesn't - // need an external compiler but it's still interoperable with an external - // compiler if configured correctly. - options.crt_static_default = true; - options.crt_static_respected = true; - - // Allow `+crt-static` to create a "cdylib" output which is just a wasm file - // without a main function. - options.crt_static_allows_dylibs = true; - - // WASI's `sys::args::init` function ignores its arguments; instead, - // `args::args()` makes the WASI API calls itself. - options.main_needs_argc_argv = false; - - // And, WASI mangles the name of "main" to distinguish between different - // signatures. - options.entry_name = "__main_void".into(); - - Target { - llvm_target: "wasm32-unknown-unknown".into(), - pointer_width: 32, - data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), - arch: "wasm32".into(), - options, - } -} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 5f5de57dd1d87..c350a37975d23 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -201,6 +201,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("avx512dq", Unstable(sym::avx512_target_feature)), ("avx512er", Unstable(sym::avx512_target_feature)), ("avx512f", Unstable(sym::avx512_target_feature)), + ("avx512fp16", Unstable(sym::avx512_target_feature)), ("avx512ifma", Unstable(sym::avx512_target_feature)), ("avx512pf", Unstable(sym::avx512_target_feature)), ("avx512vbmi", Unstable(sym::avx512_target_feature)), diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 7894f8dd98fff..20cd573f46e9b 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessage, + EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -102,10 +102,7 @@ pub enum AdjustSignatureBorrow { } impl AddToDiagnostic for AdjustSignatureBorrow { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 995ed1e3b573b..053ecfc681ceb 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -14,6 +14,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] @@ -39,6 +41,7 @@ extern crate smallvec; pub mod errors; pub mod infer; +pub mod regions; pub mod solve; pub mod traits; diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs new file mode 100644 index 0000000000000..756db7cc2063f --- /dev/null +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -0,0 +1,41 @@ +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{InferCtxt, RegionResolutionError}; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::ObligationCause; + +pub trait InferCtxtRegionExt<'tcx> { + /// Resolve regions, using the deep normalizer to normalize any type-outlives + /// obligations in the process. This is in `rustc_trait_selection` because + /// we need to normalize. + /// + /// Prefer this method over `resolve_regions_with_normalize`, unless you are + /// doing something specific for normalization. + fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec>; +} + +impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { + fn resolve_regions( + &self, + outlives_env: &OutlivesEnvironment<'tcx>, + ) -> Vec> { + self.resolve_regions_with_normalize(outlives_env, |ty, origin| { + let ty = self.resolve_vars_if_possible(ty); + + if self.next_trait_solver() { + crate::solve::deeply_normalize( + self.at( + &ObligationCause::dummy_with_span(origin.span()), + outlives_env.param_env, + ), + ty, + ) + .map_err(|_| NoSolution) + } else { + Ok(ty) + } + }) + } +} diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 915d722dd0206..81c0cfea85a77 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -8,7 +8,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::inspect::ProbeKind; use rustc_middle::traits::solve::{ - CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult, + CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult, }; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; @@ -182,6 +182,22 @@ pub(super) trait GoalKind<'tcx>: kind: ty::ClosureKind, ) -> QueryResult<'tcx>; + /// An async closure is known to implement the `AsyncFn` family of traits + /// where `A` is given by the signature of the type. + fn consider_builtin_async_fn_trait_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + kind: ty::ClosureKind, + ) -> QueryResult<'tcx>; + + /// Compute the built-in logic of the `AsyncFnKindHelper` helper trait, which + /// is used internally to delay computation for async closures until after + /// upvar analysis is performed in HIR typeck. + fn consider_builtin_async_fn_kind_helper_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx>; + /// `Tuple` is implemented if the `Self` type is a tuple. fn consider_builtin_tuple_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, @@ -260,25 +276,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, goal: Goal<'tcx, G>, ) -> Vec> { - let dummy_candidate = |this: &mut EvalCtxt<'_, 'tcx>, certainty| { - let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); - let result = this.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(); - let mut dummy_probe = this.inspect.new_probe(); - dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) }); - this.inspect.finish_probe(dummy_probe); - vec![Candidate { source, result }] - }; - let Some(normalized_self_ty) = self.try_normalize_ty(goal.param_env, goal.predicate.self_ty()) else { debug!("overflow while evaluating self type"); - return dummy_candidate(self, Certainty::OVERFLOW); + return self.forced_ambiguity(MaybeCause::Overflow); }; if normalized_self_ty.is_ty_var() { debug!("self type has been normalized to infer"); - return dummy_candidate(self, Certainty::AMBIGUOUS); + return self.forced_ambiguity(MaybeCause::Ambiguity); } let goal = @@ -299,11 +306,26 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.assemble_param_env_candidates(goal, &mut candidates); - self.assemble_coherence_unknowable_candidates(goal, &mut candidates); + match self.solver_mode() { + SolverMode::Normal => self.discard_impls_shadowed_by_env(goal, &mut candidates), + SolverMode::Coherence => { + self.assemble_coherence_unknowable_candidates(goal, &mut candidates) + } + } candidates } + fn forced_ambiguity(&mut self, cause: MaybeCause) -> Vec> { + let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); + let certainty = Certainty::Maybe(cause); + let result = self.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(); + let mut dummy_probe = self.inspect.new_probe(); + dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) }); + self.inspect.finish_probe(dummy_probe); + vec![Candidate { source, result }] + } + #[instrument(level = "debug", skip_all)] fn assemble_non_blanket_impl_candidates>( &mut self, @@ -340,7 +362,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::Never | ty::Tuple(_) => { @@ -460,6 +483,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { G::consider_builtin_fn_ptr_trait_candidate(self, goal) } else if let Some(kind) = self.tcx().fn_trait_kind_from_def_id(trait_def_id) { G::consider_builtin_fn_trait_candidates(self, goal, kind) + } else if let Some(kind) = self.tcx().async_fn_trait_kind_from_def_id(trait_def_id) { + G::consider_builtin_async_fn_trait_candidates(self, goal, kind) + } else if lang_items.async_fn_kind_helper() == Some(trait_def_id) { + G::consider_builtin_async_fn_kind_helper_candidate(self, goal) } else if lang_items.tuple_trait() == Some(trait_def_id) { G::consider_builtin_tuple_candidate(self, goal) } else if lang_items.pointee_trait() == Some(trait_def_id) { @@ -521,7 +548,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - let alias_ty = match goal.predicate.self_ty().kind() { + let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| { + ecx.assemble_alias_bound_candidates_recur(goal.predicate.self_ty(), goal, candidates); + }); + } + + /// For some deeply nested `::A::B::C::D` rigid associated type, + /// we should explore the item bounds for all levels, since the + /// `associated_type_bounds` feature means that a parent associated + /// type may carry bounds for a nested associated type. + /// + /// If we have a projection, check that its self type is a rigid projection. + /// If so, continue searching by recursively calling after normalization. + // FIXME: This may recurse infinitely, but I can't seem to trigger it without + // hitting another overflow error something. Add a depth parameter needed later. + fn assemble_alias_bound_candidates_recur>( + &mut self, + self_ty: Ty<'tcx>, + goal: Goal<'tcx, G>, + candidates: &mut Vec>, + ) { + let (kind, alias_ty) = match *self_ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -538,6 +585,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnPtr(_) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never @@ -545,13 +593,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Param(_) | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) - | ty::Alias(ty::Inherent, _) - | ty::Alias(ty::Weak, _) | ty::Error(_) => return, - ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) - | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"), - // Excluding IATs and type aliases here as they don't have meaningful item bounds. - ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty, + ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => { + bug!("unexpected self type for `{goal:?}`") + } + + ty::Infer(ty::TyVar(_)) => { + // If we hit infer when normalizing the self type of an alias, + // then bail with ambiguity. We should never encounter this on + // the *first* iteration of this recursive function. + if let Ok(result) = + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }); + } + return; + } + + ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), + ty::Alias(ty::Inherent | ty::Weak, _) => { + unreachable!("Weak and Inherent aliases should have been normalized away already") + } }; for assumption in @@ -559,9 +621,28 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { { match G::consider_alias_bound_candidate(self, goal, assumption) { Ok(result) => { - candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + candidates.push(Candidate { source: CandidateSource::AliasBound, result }); + } + Err(NoSolution) => {} + } + } + + if kind != ty::Projection { + return; + } + + match self.try_normalize_ty(goal.param_env, alias_ty.self_ty()) { + // Recurse on the self type of the projection. + Some(next_self_ty) => { + self.assemble_alias_bound_candidates_recur(next_self_ty, goal, candidates); + } + // Bail if we overflow when normalizing, adding an ambiguous candidate. + None => { + if let Ok(result) = + self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW) + { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }); } - Err(NoSolution) => (), } } } @@ -694,6 +775,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::FnPtr(_) | ty::Alias(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never @@ -756,6 +838,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + /// In coherence we have to not only care about all impls we know about, but + /// also consider impls which may get added in a downstream or sibling crate + /// or which an upstream impl may add in a minor release. + /// + /// To do so we add an ambiguous candidate in case such an unknown impl could + /// apply to the current goal. #[instrument(level = "debug", skip_all)] fn assemble_coherence_unknowable_candidates>( &mut self, @@ -763,11 +851,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec>, ) { let tcx = self.tcx(); - match self.solver_mode() { - SolverMode::Normal => return, - SolverMode::Coherence => {} - }; - let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| { let trait_ref = goal.predicate.trait_ref(tcx); #[derive(Debug)] @@ -797,46 +880,65 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + /// If there's a where-bound for the current goal, do not use any impl candidates + /// to prove the current goal. Most importantly, if there is a where-bound which does + /// not specify any associated types, we do not allow normalizing the associated type + /// by using an impl, even if it would apply. + /// + /// + // FIXME(@lcnr): The current structure here makes me unhappy and feels ugly. idk how + // to improve this however. However, this should make it fairly straightforward to refine + // the filtering going forward, so it seems alright-ish for now. + fn discard_impls_shadowed_by_env>( + &mut self, + goal: Goal<'tcx, G>, + candidates: &mut Vec>, + ) { + let tcx = self.tcx(); + let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = + goal.with(tcx, goal.predicate.trait_ref(tcx)); + let mut trait_candidates_from_env = Vec::new(); + self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); + self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); + if !trait_candidates_from_env.is_empty() { + let trait_env_result = self.merge_candidates(trait_candidates_from_env); + match trait_env_result.unwrap().value.certainty { + // If proving the trait goal succeeds by using the env, + // we freely drop all impl candidates. + // + // FIXME(@lcnr): It feels like this could easily hide + // a forced ambiguity candidate added earlier. + // This feels dangerous. + Certainty::Yes => { + candidates.retain(|c| match c.source { + CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_) => false, + CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => true, + }); + } + // If it is still ambiguous we instead just force the whole goal + // to be ambig and wait for inference constraints. See + // tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs + Certainty::Maybe(cause) => { + *candidates = self.forced_ambiguity(cause); + } + } + } + } + /// If there are multiple ways to prove a trait or projection goal, we have /// to somehow try to merge the candidates into one. If that fails, we return /// ambiguity. #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_candidates( &mut self, - mut candidates: Vec>, + candidates: Vec>, ) -> QueryResult<'tcx> { // First try merging all candidates. This is complete and fully sound. let responses = candidates.iter().map(|c| c.result).collect::>(); if let Some(result) = self.try_merge_responses(&responses) { return Ok(result); + } else { + self.flounder(&responses) } - - // We then check whether we should prioritize `ParamEnv` candidates. - // - // Doing so is incomplete and would therefore be unsound during coherence. - match self.solver_mode() { - SolverMode::Coherence => (), - // Prioritize `ParamEnv` candidates only if they do not guide inference. - // - // This is still incomplete as we may add incorrect region bounds. - SolverMode::Normal => { - let param_env_responses = candidates - .iter() - .filter(|c| { - matches!( - c.source, - CandidateSource::ParamEnv(_) | CandidateSource::AliasBound - ) - }) - .map(|c| c.result) - .collect::>(); - if let Some(result) = self.try_merge_responses(¶m_env_responses) { - // We strongly prefer alias and param-env bounds here, even if they affect inference. - // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/11. - return Ok(result); - } - } - } - self.flounder(&responses) } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 274a75a125c58..8dec04e2c4f28 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -1,12 +1,14 @@ //! Code which is used by built-in goals that match "structurally", such a auto //! traits, `Copy`/`Clone`. use rustc_data_structures::fx::FxHashMap; +use rustc_hir::LangItem; use rustc_hir::{def_id::DefId, Movability, Mutability}; use rustc_infer::traits::query::NoSolution; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + self, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; +use rustc_span::sym; use crate::solve::EvalCtxt; @@ -18,7 +20,7 @@ use crate::solve::EvalCtxt; pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result>, NoSolution> { +) -> Result>>, NoSolution> { let tcx = ecx.tcx(); match *ty.kind() { ty::Uint(_) @@ -32,7 +34,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( | ty::Char => Ok(vec![]), // Treat `str` like it's defined as `struct str([u8]);` - ty::Str => Ok(vec![Ty::new_slice(tcx, tcx.types.u8)]), + ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, tcx.types.u8))]), ty::Dynamic(..) | ty::Param(..) @@ -45,44 +47,48 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => { - Ok(vec![element_ty]) + Ok(vec![ty::Binder::dummy(element_ty)]) } - ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]), + ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![ty::Binder::dummy(element_ty)]), ty::Tuple(tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - Ok(tys.iter().collect()) + Ok(tys.iter().map(ty::Binder::dummy).collect()) } - ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), + + ty::CoroutineClosure(_, args) => { + Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())]) + } ty::Coroutine(_, args) => { let coroutine_args = args.as_coroutine(); - Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]) + Ok(vec![ + ty::Binder::dummy(coroutine_args.tupled_upvars_ty()), + ty::Binder::dummy(coroutine_args.witness()), + ]) } ty::CoroutineWitness(def_id, args) => Ok(ecx .tcx() .coroutine_hidden_types(def_id) - .map(|bty| { - ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( - tcx, - bty.instantiate(tcx, args), - )) - }) + .map(|bty| replace_erased_lifetimes_with_bound_vars(tcx, bty.instantiate(tcx, args))) .collect()), // For `PhantomData`, we pass `T`. - ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![args.type_at(0)]), + ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]), - ty::Adt(def, args) => Ok(def.all_fields().map(|f| f.ty(tcx, args)).collect()), + ty::Adt(def, args) => { + Ok(def.all_fields().map(|f| ty::Binder::dummy(f.ty(tcx, args))).collect()) + } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - Ok(vec![tcx.type_of(def_id).instantiate(tcx, args)]) + Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))]) } } } @@ -112,7 +118,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result>, NoSolution> { +) -> Result>>, NoSolution> { match *ty.kind() { ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Uint(_) @@ -128,6 +134,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Dynamic(_, _, ty::DynStar) | ty::Error(_) => Ok(vec![]), @@ -145,11 +152,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( bug!("unexpected type `{ty}`") } - ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()), ty::Adt(def, args) => { let sized_crit = def.sized_constraint(ecx.tcx()); - Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect()) + Ok(sized_crit.iter_instantiated(ecx.tcx(), args).map(ty::Binder::dummy).collect()) } } } @@ -158,7 +165,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result>, NoSolution> { +) -> Result>>, NoSolution> { match *ty.kind() { ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]), @@ -189,16 +196,21 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( bug!("unexpected type `{ty}`") } - ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()), - ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), + + ty::CoroutineClosure(..) => Err(NoSolution), ty::Coroutine(def_id, args) => match ecx.tcx().coroutine_movability(def_id) { Movability::Static => Err(NoSolution), Movability::Movable => { if ecx.tcx().features().coroutine_clone { let coroutine = args.as_coroutine(); - Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]) + Ok(vec![ + ty::Binder::dummy(coroutine.tupled_upvars_ty()), + ty::Binder::dummy(coroutine.witness()), + ]) } else { Err(NoSolution) } @@ -209,10 +221,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( .tcx() .coroutine_hidden_types(def_id) .map(|bty| { - ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( + replace_erased_lifetimes_with_bound_vars( ecx.tcx(), bty.instantiate(ecx.tcx(), args), - )) + ) }) .collect()), } @@ -267,6 +279,131 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( } Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output())))) } + + // Coroutine-closures don't implement `Fn` traits the normal way. + ty::CoroutineClosure(..) => Err(NoSolution), + + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::Dynamic(_, _, _) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Placeholder(..) + | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + | ty::Error(_) => Err(NoSolution), + + ty::Bound(..) + | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + bug!("unexpected type `{self_ty}`") + } + } +} + +// Returns a binder of the tupled inputs types, output type, and coroutine type +// from a builtin coroutine-closure type. If we don't yet know the closure kind of +// the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper` +// which enforces the closure is actually callable with the given trait. When we +// know the kind already, we can short-circuit this check. +pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tcx>( + tcx: TyCtxt<'tcx>, + self_ty: Ty<'tcx>, + goal_kind: ty::ClosureKind, + env_region: ty::Region<'tcx>, +) -> Result< + (ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Option>), + NoSolution, +> { + match *self_ty.kind() { + ty::CoroutineClosure(def_id, args) => { + let args = args.as_coroutine_closure(); + let kind_ty = args.kind_ty(); + + if let Some(closure_kind) = kind_ty.to_opt_closure_kind() { + if !closure_kind.extends(goal_kind) { + return Err(NoSolution); + } + Ok(( + args.coroutine_closure_sig().map_bound(|sig| { + let coroutine_ty = sig.to_coroutine_given_kind_and_upvars( + tcx, + args.parent_args(), + tcx.coroutine_for_closure(def_id), + goal_kind, + env_region, + args.tupled_upvars_ty(), + args.coroutine_captures_by_ref_ty(), + ); + (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty) + }), + None, + )) + } else { + let async_fn_kind_trait_def_id = + tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); + let upvars_projection_def_id = tcx + .associated_items(async_fn_kind_trait_def_id) + .filter_by_name_unhygienic(sym::Upvars) + .next() + .unwrap() + .def_id; + // When we don't know the closure kind (and therefore also the closure's upvars, + // which are computed at the same time), we must delay the computation of the + // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait + // goal functions similarly to the old `ClosureKind` predicate, and ensures that + // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars` + // will project to the right upvars for the generator, appending the inputs and + // coroutine upvars respecting the closure kind. + Ok(( + args.coroutine_closure_sig().map_bound(|sig| { + let tupled_upvars_ty = Ty::new_projection( + tcx, + upvars_projection_def_id, + [ + ty::GenericArg::from(kind_ty), + Ty::from_closure_kind(tcx, goal_kind).into(), + env_region.into(), + sig.tupled_inputs_ty.into(), + args.tupled_upvars_ty().into(), + args.coroutine_captures_by_ref_ty().into(), + ], + ); + let coroutine_ty = sig.to_coroutine( + tcx, + args.parent_args(), + Ty::from_closure_kind(tcx, goal_kind), + tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ); + (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty) + }), + Some( + ty::TraitRef::new( + tcx, + async_fn_kind_trait_def_id, + [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], + ) + .to_predicate(tcx), + ), + )) + } + } + + ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) => Err(NoSolution), + ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 76c50a111027d..803379af005f9 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -477,10 +477,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } } else { - let kind = self.infcx.instantiate_binder_with_placeholders(kind); - let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); - self.add_goal(GoalSource::Misc, goal); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.infcx.enter_forall(kind, |kind| { + let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); + self.add_goal(GoalSource::Misc, goal); + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } } @@ -801,13 +802,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) } - pub(super) fn instantiate_binder_with_placeholders> + Copy>( + pub(super) fn enter_forall> + Copy, U>( &self, value: ty::Binder<'tcx, T>, - ) -> T { - self.infcx.instantiate_binder_with_placeholders(value) + f: impl FnOnce(T) -> U, + ) -> U { + self.infcx.enter_forall(value, f) } - pub(super) fn resolve_vars_if_possible(&self, value: T) -> T where T: TypeFoldable>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 315df06be417c..69b6993043268 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -31,103 +31,108 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); - let trait_goal = Goal::new( - self.tcx, - obligation.param_env, - self.instantiate_binder_with_placeholders(obligation.predicate), - ); - - let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| { - let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate); - let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal); - let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal); - - // pseudo-winnow - if candidates.len() == 0 { - return Err(SelectionError::Unimplemented); - } else if candidates.len() > 1 { - let mut i = 0; - while i < candidates.len() { - let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { - candidate_should_be_dropped_in_favor_of( - ecx.tcx(), - &candidates[i], - &candidates[j], - ) - }); - if should_drop_i { - candidates.swap_remove(i); - } else { - i += 1; - if i > 1 { - return Ok(None); + self.enter_forall(obligation.predicate, |pred| { + let trait_goal = Goal::new(self.tcx, obligation.param_env, pred); + + let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| { + let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate); + let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal); + let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal); + + // pseudo-winnow + if candidates.len() == 0 { + return Err(SelectionError::Unimplemented); + } else if candidates.len() > 1 { + let mut i = 0; + while i < candidates.len() { + let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { + candidate_should_be_dropped_in_favor_of( + ecx.tcx(), + &candidates[i], + &candidates[j], + ) + }); + if should_drop_i { + candidates.swap_remove(i); + } else { + i += 1; + if i > 1 { + return Ok(None); + } } } } - } - let candidate = candidates.pop().unwrap(); - let (certainty, nested_goals) = ecx - .instantiate_and_apply_query_response( - trait_goal.param_env, - orig_values, - candidate.result, - ) - .map_err(|_| SelectionError::Unimplemented)?; - - Ok(Some((candidate, certainty, nested_goals))) - }); - - let (candidate, certainty, nested_goals) = match result { - Ok(Some((candidate, certainty, nested_goals))) => (candidate, certainty, nested_goals), - Ok(None) => return Ok(None), - Err(e) => return Err(e), - }; - - let nested_obligations: Vec<_> = nested_goals - .into_iter() - .map(|goal| { - Obligation::new(self.tcx, ObligationCause::dummy(), goal.param_env, goal.predicate) - }) - .collect(); - - let goal = self.resolve_vars_if_possible(trait_goal); - match (certainty, candidate.source) { - // Rematching the implementation will instantiate the same nested goals that - // would have caused the ambiguity, so we can still make progress here regardless. - (_, CandidateSource::Impl(def_id)) => { - rematch_impl(self, goal, def_id, nested_obligations) - } + let candidate = candidates.pop().unwrap(); + let (certainty, nested_goals) = ecx + .instantiate_and_apply_query_response( + trait_goal.param_env, + orig_values, + candidate.result, + ) + .map_err(|_| SelectionError::Unimplemented)?; + + Ok(Some((candidate, certainty, nested_goals))) + }); + + let (candidate, certainty, nested_goals) = match result { + Ok(Some((candidate, certainty, nested_goals))) => { + (candidate, certainty, nested_goals) + } + Ok(None) => return Ok(None), + Err(e) => return Err(e), + }; + + let nested_obligations: Vec<_> = nested_goals + .into_iter() + .map(|goal| { + Obligation::new( + self.tcx, + ObligationCause::dummy(), + goal.param_env, + goal.predicate, + ) + }) + .collect(); + + let goal = self.resolve_vars_if_possible(trait_goal); + match (certainty, candidate.source) { + // Rematching the implementation will instantiate the same nested goals that + // would have caused the ambiguity, so we can still make progress here regardless. + (_, CandidateSource::Impl(def_id)) => { + rematch_impl(self, goal, def_id, nested_obligations) + } - // If an unsize goal is ambiguous, then we can manually rematch it to make - // selection progress for coercion during HIR typeck. If it is *not* ambiguous, - // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, - // and we need to rematch those to detect tuple unsizing and trait upcasting. - // FIXME: This will be wrong if we have param-env or where-clause bounds - // with the unsize goal -- we may need to mark those with different impl - // sources. - (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) - | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) - if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => - { - rematch_unsize(self, goal, nested_obligations, src, certainty) - } + // If an unsize goal is ambiguous, then we can manually rematch it to make + // selection progress for coercion during HIR typeck. If it is *not* ambiguous, + // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, + // and we need to rematch those to detect tuple unsizing and trait upcasting. + // FIXME: This will be wrong if we have param-env or where-clause bounds + // with the unsize goal -- we may need to mark those with different impl + // sources. + (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) + | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) + if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => + { + rematch_unsize(self, goal, nested_obligations, src, certainty) + } - // Technically some builtin impls have nested obligations, but if - // `Certainty::Yes`, then they should've all been verified and don't - // need re-checking. - (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { - Ok(Some(ImplSource::Builtin(src, nested_obligations))) - } + // Technically some builtin impls have nested obligations, but if + // `Certainty::Yes`, then they should've all been verified and don't + // need re-checking. + (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { + Ok(Some(ImplSource::Builtin(src, nested_obligations))) + } - // It's fine not to do anything to rematch these, since there are no - // nested obligations. - (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { - Ok(Some(ImplSource::Param(nested_obligations))) - } + // It's fine not to do anything to rematch these, since there are no + // nested obligations. + (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { + Ok(Some(ImplSource::Param(nested_obligations))) + } - (Certainty::Maybe(_), _) => Ok(None), - } + (Certainty::Maybe(_), _) => Ok(None), + } + }) } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index f08622816ec28..63555a305d855 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -140,7 +140,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) } ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( + let (a, b) = infcx.enter_forall_and_leak_universe( goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(true, a, b); @@ -150,7 +150,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) } ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( + let (a, b) = infcx.enter_forall_and_leak_universe( goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(false, a, b); diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 6984f0ba69473..a7330136fe789 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -124,25 +124,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } - #[instrument(level = "debug", skip(self))] - fn compute_closure_kind_goal( - &mut self, - goal: Goal<'tcx, (DefId, ty::GenericArgsRef<'tcx>, ty::ClosureKind)>, - ) -> QueryResult<'tcx> { - let (_, args, expected_kind) = goal.predicate; - let found_kind = args.as_closure().kind_ty().to_opt_closure_kind(); - - let Some(found_kind) = found_kind else { - return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); - }; - if found_kind.extends(expected_kind) { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } else { - Err(NoSolution) - } - } - - #[instrument(level = "debug", skip(self))] fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> { if self.tcx().check_is_object_safe(trait_def_id) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 9f1b4a09a20ba..d177109c42046 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -366,6 +366,119 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)]) } + fn consider_builtin_async_fn_trait_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + goal_kind: ty::ClosureKind, + ) -> QueryResult<'tcx> { + let tcx = ecx.tcx(); + + let env_region = match goal_kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => goal.predicate.alias.args.region_at(2), + // Doesn't matter what this region is + ty::ClosureKind::FnOnce => tcx.lifetimes.re_static, + }; + let (tupled_inputs_and_output_and_coroutine, nested_preds) = + structural_traits::extract_tupled_inputs_and_output_from_async_callable( + tcx, + goal.predicate.self_ty(), + goal_kind, + env_region, + )?; + let output_is_sized_pred = + tupled_inputs_and_output_and_coroutine.map_bound(|(_, output, _)| { + ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output]) + }); + + let pred = tupled_inputs_and_output_and_coroutine + .map_bound(|(inputs, output, coroutine)| { + let (projection_ty, term) = match tcx.item_name(goal.predicate.def_id()) { + sym::CallOnceFuture => ( + ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [goal.predicate.self_ty(), inputs], + ), + coroutine.into(), + ), + sym::CallMutFuture | sym::CallFuture => ( + ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [ + ty::GenericArg::from(goal.predicate.self_ty()), + inputs.into(), + env_region.into(), + ], + ), + coroutine.into(), + ), + sym::Output => ( + ty::AliasTy::new( + tcx, + goal.predicate.def_id(), + [ty::GenericArg::from(goal.predicate.self_ty()), inputs.into()], + ), + output.into(), + ), + name => bug!("no such associated type: {name}"), + }; + ty::ProjectionPredicate { projection_ty, term } + }) + .to_predicate(tcx); + + // A built-in `AsyncFn` impl only holds if the output is sized. + // (FIXME: technically we only need to check this if the type is a fn ptr...) + Self::consider_implied_clause( + ecx, + goal, + pred, + [goal.with(tcx, output_is_sized_pred)] + .into_iter() + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + ) + } + + fn consider_builtin_async_fn_kind_helper_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let [ + closure_fn_kind_ty, + goal_kind_ty, + borrow_region, + tupled_inputs_ty, + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + ] = **goal.predicate.alias.args + else { + bug!(); + }; + + let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else { + // We don't need to worry about the self type being an infer var. + return Err(NoSolution); + }; + let Some(goal_kind) = goal_kind_ty.expect_ty().to_opt_closure_kind() else { + return Err(NoSolution); + }; + if !closure_kind.extends(goal_kind) { + return Err(NoSolution); + } + + let upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( + ecx.tcx(), + goal_kind, + tupled_inputs_ty.expect_ty(), + tupled_upvars_ty.expect_ty(), + coroutine_captures_by_ref_ty.expect_ty(), + borrow_region.expect_region(), + ); + + ecx.eq(goal.param_env, goal.predicate.term.ty().unwrap(), upvars_ty)?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + fn consider_builtin_tuple_candidate( _ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -378,6 +491,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let tcx = ecx.tcx(); + let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); + assert_eq!(metadata_def_id, goal.predicate.def_id()); ecx.probe_misc_candidate("builtin pointee").enter(|ecx| { let metadata_ty = match goal.predicate.self_ty().kind() { ty::Bool @@ -391,6 +506,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) | ty::Coroutine(..) | ty::CoroutineWitness(..) @@ -408,7 +524,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { - // FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints. + // This is the "fallback impl" for type parameters, unnormalizable projections + // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. + // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't + // exist. Instead, `Pointee` should be a supertrait of `Sized`. let sized_predicate = ty::TraitRef::from_lang_item( tcx, LangItem::Sized, @@ -422,30 +541,16 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() { None => tcx.types.unit, - Some(field_def) => { - let self_ty = field_def.ty(tcx, args); - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goal( - GoalSource::Misc, - goal.with(tcx, goal.predicate.with_self_ty(tcx, self_ty)), - ); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + Some(tail_def) => { + let tail_ty = tail_def.ty(tcx, args); + Ty::new_projection(tcx, metadata_def_id, [tail_ty]) } }, ty::Adt(_, _) => tcx.types.unit, ty::Tuple(elements) => match elements.last() { None => tcx.types.unit, - Some(&self_ty) => { - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goal( - GoalSource::Misc, - goal.with(tcx, goal.predicate.with_self_ty(tcx, self_ty)), - ); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); - } + Some(&tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]), }, ty::Infer( @@ -627,6 +732,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { | ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) | ty::Coroutine(..) | ty::CoroutineWitness(..) diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index b185e4e5f8eb0..044832224e5c1 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -303,6 +303,66 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { Self::consider_implied_clause(ecx, goal, pred, [goal.with(tcx, output_is_sized_pred)]) } + fn consider_builtin_async_fn_trait_candidates( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + goal_kind: ty::ClosureKind, + ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + + let tcx = ecx.tcx(); + let (tupled_inputs_and_output_and_coroutine, nested_preds) = + structural_traits::extract_tupled_inputs_and_output_from_async_callable( + tcx, + goal.predicate.self_ty(), + goal_kind, + // This region doesn't matter because we're throwing away the coroutine type + tcx.lifetimes.re_static, + )?; + let output_is_sized_pred = + tupled_inputs_and_output_and_coroutine.map_bound(|(_, output, _)| { + ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output]) + }); + + let pred = tupled_inputs_and_output_and_coroutine + .map_bound(|(inputs, _, _)| { + ty::TraitRef::new(tcx, goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]) + }) + .to_predicate(tcx); + // A built-in `AsyncFn` impl only holds if the output is sized. + // (FIXME: technically we only need to check this if the type is a fn ptr...) + Self::consider_implied_clause( + ecx, + goal, + pred, + [goal.with(tcx, output_is_sized_pred)] + .into_iter() + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + ) + } + + fn consider_builtin_async_fn_kind_helper_candidate( + ecx: &mut EvalCtxt<'_, 'tcx>, + goal: Goal<'tcx, Self>, + ) -> QueryResult<'tcx> { + let [closure_fn_kind_ty, goal_kind_ty] = **goal.predicate.trait_ref.args else { + bug!(); + }; + + let Some(closure_kind) = closure_fn_kind_ty.expect_ty().to_opt_closure_kind() else { + // We don't need to worry about the self type being an infer var. + return Err(NoSolution); + }; + let goal_kind = goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap(); + if closure_kind.extends(goal_kind) { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } else { + Err(NoSolution) + } + } + fn consider_builtin_tuple_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, @@ -950,7 +1010,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(_) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -988,14 +1049,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { fn probe_and_evaluate_goal_for_constituent_tys( &mut self, goal: Goal<'tcx, TraitPredicate<'tcx>>, - constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result>, NoSolution>, + constituent_tys: impl Fn( + &EvalCtxt<'_, 'tcx>, + Ty<'tcx>, + ) -> Result>>, NoSolution>, ) -> QueryResult<'tcx> { self.probe_misc_candidate("constituent tys").enter(|ecx| { ecx.add_goals( GoalSource::ImplWhereBound, constituent_tys(ecx, goal.predicate.self_ty())? .into_iter() - .map(|ty| goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty))) + .map(|ty| { + ecx.enter_forall(ty, |ty| { + goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty)) + }) + }) .collect::>(), ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c43447585746a..81c72fc4b7b03 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } let outlives_env = OutlivesEnvironment::new(full_env); - infcx.process_registered_region_obligations(&outlives_env); + let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty)); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); @@ -513,6 +513,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } while !vid_map.is_empty() { + #[allow(rustc::potential_query_instability)] let target = *vid_map.keys().next().expect("Keys somehow empty"); let deps = vid_map.remove(&target).expect("Entry somehow missing"); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ecbb92ca5b996..cbe9a238b1c28 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -6,6 +6,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; +use crate::regions::InferCtxtRegionExt; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::traits::engine::TraitEngineExt; @@ -862,7 +863,7 @@ where } } ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Closure(did, ..) | ty::Coroutine(did, ..) => { + ty::Closure(did, ..) | ty::CoroutineClosure(did, ..) | ty::Coroutine(did, ..) => { if self.def_id_is_local(did) { ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) } else { @@ -970,7 +971,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { let Goal { param_env, predicate } = goal.goal(); - // For bound predicates we simply call `infcx.instantiate_binder_with_placeholders` + // For bound predicates we simply call `infcx.enter_forall` // and then prove the resulting predicate as a nested goal. let trait_ref = match predicate.kind().no_bound_vars() { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 013a50f9fa1c8..caf950037fdfd 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use super::FulfillmentContext; use super::TraitEngine; +use crate::regions::InferCtxtRegionExt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::NormalizeExt; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index b246e476bedf9..c6f5af08013e6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -21,51 +21,62 @@ pub fn recompute_applicable_impls<'tcx>( let impl_may_apply = |impl_def_id| { let ocx = ObligationCtxt::new(infcx); - let placeholder_obligation = - infcx.instantiate_binder_with_placeholders(obligation.predicate); - let obligation_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); - - let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args); - let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); - - if let Err(_) = - ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) - { - return false; - } + infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + placeholder_obligation.trait_ref, + ); + + let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = + tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args); + let impl_trait_ref = + ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); + + if let Err(_) = + ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) + { + return false; + } - let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args); - ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { - Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) - })); + let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args); + ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { + Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) + })); - ocx.select_where_possible().is_empty() + ocx.select_where_possible().is_empty() + }) }; let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| { let ocx = ObligationCtxt::new(infcx); - let placeholder_obligation = - infcx.instantiate_binder_with_placeholders(obligation.predicate); - let obligation_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); - - let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - poly_trait_predicate, - ); - let param_env_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref); - - if let Err(_) = - ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref) - { - return false; - } + infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + placeholder_obligation.trait_ref, + ); + + let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + poly_trait_predicate, + ); + let param_env_trait_ref = + ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref); + + if let Err(_) = ocx.eq( + &ObligationCause::dummy(), + param_env, + obligation_trait_ref, + param_env_trait_ref, + ) { + return false; + } - ocx.select_where_possible().is_empty() + ocx.select_where_possible().is_empty() + }) }; let mut ambiguities = Vec::new(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 972da180a3365..ceff718764685 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -64,39 +64,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Option<(DefId, GenericArgsRef<'tcx>)> { let tcx = self.tcx; let param_env = obligation.param_env; - let trait_ref = self.instantiate_binder_with_placeholders(trait_ref); - let trait_self_ty = trait_ref.self_ty(); + self.enter_forall(trait_ref, |trait_ref| { + let trait_self_ty = trait_ref.self_ty(); - let mut self_match_impls = vec![]; - let mut fuzzy_match_impls = vec![]; + let mut self_match_impls = vec![]; + let mut fuzzy_match_impls = vec![]; - self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { - let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); - let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); + self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { + let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); + let impl_trait_ref = + tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); - let impl_self_ty = impl_trait_ref.self_ty(); + let impl_self_ty = impl_trait_ref.self_ty(); - if self.can_eq(param_env, trait_self_ty, impl_self_ty) { - self_match_impls.push((def_id, impl_args)); + if self.can_eq(param_env, trait_self_ty, impl_self_ty) { + self_match_impls.push((def_id, impl_args)); - if iter::zip(trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1)) + if iter::zip( + trait_ref.args.types().skip(1), + impl_trait_ref.args.types().skip(1), + ) .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some()) - { - fuzzy_match_impls.push((def_id, impl_args)); + { + fuzzy_match_impls.push((def_id, impl_args)); + } } - } - }); + }); - let impl_def_id_and_args = if self_match_impls.len() == 1 { - self_match_impls[0] - } else if fuzzy_match_impls.len() == 1 { - fuzzy_match_impls[0] - } else { - return None; - }; + let impl_def_id_and_args = if self_match_impls.len() == 1 { + self_match_impls[0] + } else if fuzzy_match_impls.len() == 1 { + fuzzy_match_impls[0] + } else { + return None; + }; - tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented) - .then_some(impl_def_id_and_args) + tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented) + .then_some(impl_def_id_and_args) + }) } /// Used to set on_unimplemented's `ItemContext` 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 cdf99870006e7..f68200b6f4d5e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -19,7 +19,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{Map, Visitor}; +use rustc_hir::intravisit::Visitor; use rustc_hir::is_range_literal; use rustc_hir::lang_items::LangItem; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node}; @@ -774,7 +774,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if steps > 0 { // Don't care about `&mut` because `DerefMut` is used less // often and user will not expect that an autoderef happens. - if let Some(hir::Node::Expr(hir::Expr { + if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf( hir::BorrowKind::Ref, @@ -782,7 +782,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { expr, ), .. - })) = self.tcx.opt_hir_node(*arg_hir_id) + }) = self.tcx.hir_node(*arg_hir_id) { let derefs = "*".repeat(steps); err.span_suggestion_verbose( @@ -1199,7 +1199,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let Res::Local(hir_id) = path.res else { return; }; - let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else { + let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else { return; }; let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) = @@ -1248,52 +1248,55 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); - let ty = self.instantiate_binder_with_placeholders(self_ty); - let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { - return false; - }; - let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; - let ty::Param(param) = inner_ty.kind() else { return false }; - let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = - obligation.cause.code() - else { - return false; - }; - let arg_node = self.tcx.hir_node(*arg_hir_id); - let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false }; + self.enter_forall(self_ty, |ty: Ty<'_>| { + let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { + return false; + }; + let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; + let ty::Param(param) = inner_ty.kind() else { return false }; + let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = + obligation.cause.code() + else { + return false; + }; + let arg_node = self.tcx.hir_node(*arg_hir_id); + let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { + return false; + }; - let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); - let has_clone = |ty| { - self.type_implements_trait(clone_trait, [ty], obligation.param_env) - .must_apply_modulo_regions() - }; + let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); + let has_clone = |ty| { + self.type_implements_trait(clone_trait, [ty], obligation.param_env) + .must_apply_modulo_regions() + }; - let new_obligation = self.mk_trait_obligation_with_new_self_ty( - obligation.param_env, - trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), - ); + let new_obligation = self.mk_trait_obligation_with_new_self_ty( + obligation.param_env, + trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), + ); - if self.predicate_may_hold(&new_obligation) && has_clone(ty) { - if !has_clone(param.to_ty(self.tcx)) { - suggest_constraining_type_param( - self.tcx, - generics, - err, - param.name.as_str(), - "Clone", - Some(clone_trait), - None, + if self.predicate_may_hold(&new_obligation) && has_clone(ty) { + if !has_clone(param.to_ty(self.tcx)) { + suggest_constraining_type_param( + self.tcx, + generics, + err, + param.name.as_str(), + "Clone", + Some(clone_trait), + None, + ); + } + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_hi(), + "consider using clone here", + ".clone()".to_string(), + Applicability::MaybeIncorrect, ); + return true; } - err.span_suggestion_verbose( - obligation.cause.span.shrink_to_hi(), - "consider using clone here", - ".clone()".to_string(), - Applicability::MaybeIncorrect, - ); - return true; - } - false + false + }) } /// Extracts information about a callable type for diagnostics. This is a @@ -1432,20 +1435,18 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> bool { let span = obligation.cause.span; - let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - obligation.cause.code() - { - parent_code - } else if let ObligationCauseCode::ItemObligation(_) - | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code() - { - obligation.cause.code() - } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) = - span.ctxt().outer_expn_data().kind - { - obligation.cause.code() - } else { - return false; + let code = match obligation.cause.code() { + ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => parent_code, + c @ ObligationCauseCode::ItemObligation(_) + | c @ ObligationCauseCode::ExprItemObligation(..) => c, + c if matches!( + span.ctxt().outer_expn_data().kind, + ExpnKind::Desugaring(DesugaringKind::ForLoop) + ) => + { + c + } + _ => return false, }; // List of traits for which it would be nonsensical to suggest borrowing. @@ -1788,7 +1789,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let Res::Local(hir_id) = path.res - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(hir_id) && let Some(hir::Node::Local(local)) = self.tcx.hir().find_parent(binding.hir_id) && let None = local.ty && let Some(binding_expr) = local.init @@ -2200,7 +2201,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let ty::FnPtr(found) = found.kind() else { return; }; - let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) else { + let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else { return; }; let hir::ExprKind::Path(path) = arg.kind else { @@ -2719,7 +2720,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let (trait_name, trait_verb) = if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; - err.clear_code(); + err.code = None; err.primary_message(format!( "{future_or_coroutine} cannot be {trait_verb} between threads safely" )); @@ -3011,35 +3012,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } } - let descr = format!("required by a bound in `{item_name}`"); - if span.is_visible(sm) { - let msg = format!("required by this bound in `{short_item_name}`"); - multispan.push_span_label(span, msg); - err.span_note(multispan, descr); - if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() - && let ty::ClauseKind::Trait(trait_pred) = clause - { - let def_id = trait_pred.def_id(); - let visible_item = if let Some(local) = def_id.as_local() { - // Check for local traits being reachable. - let vis = &tcx.resolutions(()).effective_visibilities; - // Account for non-`pub` traits in the root of the local crate. - let is_locally_reachable = tcx.parent(def_id).is_crate_root(); - vis.is_reachable(local) || is_locally_reachable - } else { - // Check for foreign traits being reachable. - tcx.visible_parent_map(()).get(&def_id).is_some() - }; - if Some(def_id) == tcx.lang_items().sized_trait() - && let Some(hir::Node::TraitItem(hir::TraitItem { - ident, - kind: hir::TraitItemKind::Type(bounds, None), - .. - })) = tcx.hir().get_if_local(item_def_id) - // Do not suggest relaxing if there is an explicit `Sized` obligation. - && !bounds.iter() - .filter_map(|bound| bound.trait_ref()) - .any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait()) + let mut a = "a"; + let mut this = "this bound"; + let mut note = None; + let mut help = None; + if let ty::PredicateKind::Clause(clause) = predicate.kind().skip_binder() + && let ty::ClauseKind::Trait(trait_pred) = clause + { + let def_id = trait_pred.def_id(); + let visible_item = if let Some(local) = def_id.as_local() { + // Check for local traits being reachable. + let vis = &tcx.resolutions(()).effective_visibilities; + // Account for non-`pub` traits in the root of the local crate. + let is_locally_reachable = tcx.parent(def_id).is_crate_root(); + vis.is_reachable(local) || is_locally_reachable + } else { + // Check for foreign traits being reachable. + tcx.visible_parent_map(()).get(&def_id).is_some() + }; + if Some(def_id) == tcx.lang_items().sized_trait() { + // Check if this is an implicit bound, even in foreign crates. + if tcx + .generics_of(item_def_id) + .params + .iter() + .any(|param| tcx.def_span(param.def_id) == span) + { + a = "an implicit `Sized`"; + this = "the implicit `Sized` requirement on this type parameter"; + } + if let Some(hir::Node::TraitItem(hir::TraitItem { + ident, + kind: hir::TraitItemKind::Type(bounds, None), + .. + })) = tcx.hir().get_if_local(item_def_id) + // Do not suggest relaxing if there is an explicit `Sized` obligation. + && !bounds.iter() + .filter_map(|bound| bound.trait_ref()) + .any(|tr| tr.trait_def_id() == tcx.lang_items().sized_trait()) { let (span, separator) = if let [.., last] = bounds { (last.span().shrink_to_hi(), " +") @@ -3053,52 +3063,64 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Applicability::MachineApplicable, ); } - if let DefKind::Trait = tcx.def_kind(item_def_id) - && !visible_item - { - err.note(format!( - "`{short_item_name}` is a \"sealed trait\", because to implement \ - it you also need to implement `{}`, which is not accessible; \ - this is usually done to force you to use one of the provided \ - types that already implement it", - with_no_trimmed_paths!(tcx.def_path_str(def_id)), - )); - let impls_of = tcx.trait_impls_of(def_id); - let impls = impls_of - .non_blanket_impls() - .values() - .flatten() - .chain(impls_of.blanket_impls().iter()) + } + if let DefKind::Trait = tcx.def_kind(item_def_id) + && !visible_item + { + note = Some(format!( + "`{short_item_name}` is a \"sealed trait\", because to implement it \ + you also need to implement `{}`, which is not accessible; this is \ + usually done to force you to use one of the provided types that \ + already implement it", + with_no_trimmed_paths!(tcx.def_path_str(def_id)), + )); + let impls_of = tcx.trait_impls_of(def_id); + let impls = impls_of + .non_blanket_impls() + .values() + .flatten() + .chain(impls_of.blanket_impls().iter()) + .collect::>(); + if !impls.is_empty() { + let len = impls.len(); + let mut types = impls + .iter() + .map(|t| { + with_no_trimmed_paths!(format!( + " {}", + tcx.type_of(*t).instantiate_identity(), + )) + }) .collect::>(); - if !impls.is_empty() { - let len = impls.len(); - let mut types = impls - .iter() - .map(|t| { - with_no_trimmed_paths!(format!( - " {}", - tcx.type_of(*t).instantiate_identity(), - )) - }) - .collect::>(); - let post = if types.len() > 9 { - types.truncate(8); - format!("\nand {} others", len - 8) - } else { - String::new() - }; - err.help(format!( - "the following type{} implement{} the trait:\n{}{post}", - pluralize!(len), - if len == 1 { "s" } else { "" }, - types.join("\n"), - )); - } + let post = if types.len() > 9 { + types.truncate(8); + format!("\nand {} others", len - 8) + } else { + String::new() + }; + help = Some(format!( + "the following type{} implement{} the trait:\n{}{post}", + pluralize!(len), + if len == 1 { "s" } else { "" }, + types.join("\n"), + )); } } + }; + let descr = format!("required by {a} bound in `{item_name}`"); + if span.is_visible(sm) { + let msg = format!("required by {this} in `{short_item_name}`"); + multispan.push_span_label(span, msg); + err.span_note(multispan, descr); } else { err.span_note(tcx.def_span(item_def_id), descr); } + if let Some(note) = note { + err.note(note); + } + if let Some(help) = help { + err.help(help); + } } ObligationCauseCode::Coercion { source, target } => { let mut file = None; @@ -3167,8 +3189,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::VariableType(hir_id) => { let parent_node = tcx.hir().parent_id(hir_id); - match tcx.opt_hir_node(parent_node) { - Some(Node::Local(hir::Local { ty: Some(ty), .. })) => { + match tcx.hir_node(parent_node) { + Node::Local(hir::Local { ty: Some(ty), .. }) => { err.span_suggestion_verbose( ty.span.shrink_to_lo(), "consider borrowing here", @@ -3177,10 +3199,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); err.note("all local variables must have a statically known size"); } - Some(Node::Local(hir::Local { + Node::Local(hir::Local { init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }), .. - })) => { + }) => { // When encountering an assignment of an unsized trait, like // `let x = ""[..];`, provide a suggestion to borrow the initializer in // order to use have a slice instead. @@ -3192,7 +3214,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); err.note("all local variables must have a statically known size"); } - Some(Node::Param(param)) => { + Node::Param(param) => { err.span_suggestion_verbose( param.ty_span.shrink_to_lo(), "function arguments must have a statically known size, borrowed types \ @@ -3214,7 +3236,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let borrowed_msg = "function arguments must have a statically known size, borrowed \ types always have a known size"; if let Some(hir_id) = hir_id - && let Some(hir::Node::Param(param)) = self.tcx.hir().find(hir_id) + && let hir::Node::Param(param) = self.tcx.hir_node(hir_id) && let Some(item) = self.tcx.hir().find_parent(hir_id) && let Some(decl) = item.fn_decl() && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span)) @@ -3228,7 +3250,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // param._ty_span ty = Some(t); } else if let Some(hir_id) = hir_id - && let Some(hir::Node::Ty(t)) = self.tcx.hir().find(hir_id) + && let hir::Node::Ty(t) = self.tcx.hir_node(hir_id) { ty = Some(t); } @@ -3247,7 +3269,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.span_suggestion_verbose( span, "you can use `impl Trait` as the argument type", - "impl ".to_string(), + "impl ", Applicability::MaybeIncorrect, ); let sugg = if !needs_parens { @@ -3292,7 +3314,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err.help("unsized fn params are gated as an unstable feature"); } } - ObligationCauseCode::SizedReturnType => { + ObligationCauseCode::SizedReturnType | ObligationCauseCode::SizedCallReturnType => { err.note("the return type of a function must have a statically known size"); } ObligationCauseCode::SizedYieldType => { @@ -3939,7 +3961,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { call_hir_id: HirId, ) { let tcx = self.tcx; - if let Some(Node::Expr(expr)) = tcx.opt_hir_node(arg_hir_id) + if let Node::Expr(expr) = tcx.hir_node(arg_hir_id) && let Some(typeck_results) = &self.typeck_results { if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr { @@ -4019,26 +4041,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(where_pred) = where_pred.as_trait_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() { - let where_pred = self.instantiate_binder_with_placeholders(where_pred); - let failed_pred = self.instantiate_binder_with_fresh_vars( - expr.span, - BoundRegionConversionTime::FnCall, - failed_pred, - ); + self.enter_forall(where_pred, |where_pred| { + let failed_pred = self.instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + failed_pred, + ); - let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); - for (expected, actual) in zipped { - self.probe(|_| { - match self.at(&ObligationCause::misc(expr.span, body_id), param_env).eq( - DefineOpaqueTypes::No, - expected, - actual, - ) { - Ok(_) => (), // We ignore nested obligations here for now. - Err(err) => type_diffs.push(err), - } - }) - } + let zipped = + iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); + for (expected, actual) in zipped { + self.probe(|_| { + match self + .at(&ObligationCause::misc(expr.span, body_id), param_env) + .eq(DefineOpaqueTypes::No, expected, actual) + { + Ok(_) => (), // We ignore nested obligations here for now. + Err(err) => type_diffs.push(err), + } + }) + } + }) } else if let Some(where_pred) = where_pred.as_projection_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred() && let Some(found) = failed_pred.skip_binder().term.ty() @@ -4055,9 +4078,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id) - && let Some(hir::Node::Local(local)) = self.tcx.opt_hir_node(parent_hir_id) + && let hir::Node::Local(local) = self.tcx.hir_node(parent_hir_id) && let Some(binding_expr) = local.init { // If the expression we're calling on is a binding, we want to point at the @@ -4068,17 +4091,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); } } - let call_node = tcx.opt_hir_node(call_hir_id); - if let Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. - })) = call_node + let call_node = tcx.hir_node(call_hir_id); + if let Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. }) = + call_node { if Some(rcvr.span) == err.span.primary_span() { err.replace_span_with(path.ident.span, true); } } - if let Some(Node::Expr(expr)) = tcx.opt_hir_node(call_hir_id) { + if let Node::Expr(expr) = tcx.hir_node(call_hir_id) { if let hir::ExprKind::Call(hir::Expr { span, .. }, _) | hir::ExprKind::MethodCall( hir::PathSegment { ident: Ident { span, .. }, .. }, @@ -4315,7 +4337,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id) { // We've reached the root of the method call chain... @@ -4596,14 +4618,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { self.probe(|_| { let ocx = ObligationCtxt::new(self); - let pred = self.instantiate_binder_with_placeholders(pred); - let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); - ocx.register_obligation(Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - pred, - )); + self.enter_forall(pred, |pred| { + let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); + ocx.register_obligation(Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + pred, + )); + }); if !ocx.select_where_possible().is_empty() { // encountered errors. return; @@ -4750,13 +4773,13 @@ fn hint_missing_borrow<'tcx>( } let found_args = match found.kind() { - ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(), + ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), kind => { span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind) } }; let expected_args = match expected.kind() { - ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(), + ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), kind => { span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind) } @@ -4978,16 +5001,27 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>( _ => None, }; + let pred = obligation.predicate; + let (_, base) = obligation.cause.code().peel_derives_with_predicate(); + let post = if let ty::PredicateKind::Clause(clause) = pred.kind().skip_binder() + && let ty::ClauseKind::Trait(pred) = clause + && let Some(base) = base + && base.skip_binder() != pred + { + format!(", which is required by `{base}`") + } else { + String::new() + }; match ty_desc { Some(desc) => format!( - "{}the trait `{}` is not implemented for {} `{}`", + "{}the trait `{}` is not implemented for {} `{}`{post}", pre_message, trait_predicate.print_modifiers_and_trait_path(), desc, tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None), ), None => format!( - "{}the trait `{}` is not implemented for `{}`", + "{}the trait `{}` is not implemented for `{}`{post}", pre_message, trait_predicate.print_modifiers_and_trait_path(), tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None), @@ -5194,7 +5228,7 @@ fn point_at_assoc_type_restriction( err.span_suggestion_verbose( path.span, "replace the associated type with the type specified in this `impl`", - tcx.type_of(new.def_id).skip_binder().to_string(), + tcx.type_of(new.def_id).skip_binder(), Applicability::MachineApplicable, ); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 2a09e95b2c55e..07e4fef9dd4f2 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -20,7 +20,7 @@ use crate::traits::{ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::{ codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, MultiSpan, StashKey, Style, + ErrorGuaranteed, MultiSpan, StashKey, StringPart, }; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; @@ -99,7 +99,7 @@ pub trait TypeErrCtxtExt<'tcx> { obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - ); + ) -> ErrorGuaranteed; fn emit_specialized_closure_kind_error( &self, @@ -107,7 +107,10 @@ pub trait TypeErrCtxtExt<'tcx> { trait_ref: ty::PolyTraitRef<'tcx>, ) -> Option; - fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool; + fn fn_arg_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> Result<(), ErrorGuaranteed>; fn try_conversion_context( &self, @@ -142,6 +145,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ( span, predicates + .0 .iter() .map(|&predicate| ErrorDescriptor { predicate, index: None }) .collect(), @@ -208,10 +212,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + let mut reported = None; + for from_expansion in [false, true] { for (error, suppressed) in iter::zip(&errors, &is_suppressed) { if !suppressed && error.obligation.cause.span.from_expansion() == from_expansion { - self.report_fulfillment_error(error); + let guar = self.report_fulfillment_error(error); + reported = Some(guar); // We want to ignore desugarings here: spans are equivalent even // if one is the result of a desugaring and the other is not. let mut span = error.obligation.cause.span; @@ -222,13 +229,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.reported_trait_errors .borrow_mut() .entry(span) - .or_default() + .or_insert_with(|| (vec![], guar)) + .0 .push(error.obligation.predicate); } } } - self.dcx().delayed_bug("expected fulfillment errors") + // It could be that we don't report an error because we have seen an `ErrorReported` from another source. + // We should probably be able to fix most of these, but some are delayed bugs that get a proper error + // after this function. + reported.unwrap_or_else(|| self.dcx().delayed_bug("failed to report fulfillment errors")) } /// Reports that an overflow has occurred and halts compilation. We @@ -374,7 +385,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { mut obligation: PredicateObligation<'tcx>, root_obligation: &PredicateObligation<'tcx>, error: &SelectionError<'tcx>, - ) { + ) -> ErrorGuaranteed { let tcx = self.tcx; if tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() @@ -384,10 +395,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } let mut span = obligation.cause.span; - // FIXME: statically guarantee this by tainting after the diagnostic is emitted - self.set_tainted_by_errors( - tcx.dcx().span_delayed_bug(span, "`report_selection_error` did not emit an error"), - ); let mut err = match *error { SelectionError::Unimplemented => { @@ -412,21 +419,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { kind: _, } = *obligation.cause.code() { - self.report_extra_impl_obligation( + return self.report_extra_impl_obligation( span, impl_item_def_id, trait_item_def_id, &format!("`{}`", obligation.predicate), ) - .emit(); - return; + .emit() } // Report a const-param specific error if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives() { - self.report_const_param_not_wf(ty, &obligation).emit(); - return; + return self.report_const_param_not_wf(ty, &obligation).emit(); } let bound_predicate = obligation.predicate.kind(); @@ -436,22 +441,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_predicate = self.resolve_vars_if_possible(trait_predicate); let trait_ref = trait_predicate.to_poly_trait_ref(); - if let Some(_guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) { - return; + if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) { + return guar; } // FIXME(effects) let predicate_is_const = false; - if self.dcx().has_errors().is_some() - && trait_predicate.references_error() + if let Err(guar) = trait_predicate.error_reported() { - return; + return guar; } - if self.fn_arg_obligation(&obligation) { - // Silence redundant errors on binding acccess that are already - // reported on the binding definition (#56607). - return; + // Silence redundant errors on binding acccess that are already + // reported on the binding definition (#56607). + if let Err(guar) = self.fn_arg_obligation(&obligation) { + return guar; } let mut file = None; let (post_message, pre_message, type_def) = self @@ -515,7 +519,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_ref, span, ) { - GetSafeTransmuteErrorAndReason::Silent => return, + GetSafeTransmuteErrorAndReason::Silent => return self.dcx().span_delayed_bug(span, "silent safe transmute error"), GetSafeTransmuteErrorAndReason::Error { err_msg, safe_transmute_explanation, @@ -576,8 +580,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { have_alt_message, ) { self.note_obligation_cause(&mut err, &obligation); - err.emit(); - return; + return err.emit(); } file_note.map(|note| err.note(note)); @@ -680,13 +683,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { - err.emit(); - return; + return err.emit(); } if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) { - err.emit(); - return; + return err.emit(); } if is_unsize { @@ -776,8 +777,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Some(sym::Debug | sym::Display) ) { - err.emit(); - return; + return err.emit(); } err @@ -912,8 +912,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { found_trait_ref, expected_trait_ref, ) { - Some(err) => err, - None => return, + Ok(err) => err, + Err(guar) => return guar, } } @@ -934,15 +934,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { match self.report_not_const_evaluatable_error(&obligation, span) { - Some(err) => err, - None => return, + Ok(err) => err, + Err(guar) => return guar, } } // Already reported in the query. - SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(_)) | + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) | // Already reported. - Overflow(OverflowError::Error(_)) => return, + Overflow(OverflowError::Error(guar)) => return guar, Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); @@ -951,7 +951,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); - err.emit(); + err.emit() } fn emit_specialized_closure_kind_error( @@ -959,9 +959,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligation: &PredicateObligation<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Option { - if let ty::Closure(closure_def_id, closure_args) = *trait_ref.self_ty().skip_binder().kind() + let self_ty = trait_ref.self_ty().skip_binder(); + if let ty::Closure(closure_def_id, closure_args) = *self_ty.kind() && let Some(expected_kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id()) - && let Some(found_kind) = self.closure_kind(closure_args) + && let Some(found_kind) = self.closure_kind(self_ty) && !found_kind.extends(expected_kind) && let sig = closure_args.as_closure().sig() && self.can_sub( @@ -986,22 +987,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } - fn fn_arg_obligation(&self, obligation: &PredicateObligation<'tcx>) -> bool { + fn fn_arg_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> Result<(), ErrorGuaranteed> { if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() - && let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) + && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) && let arg = arg.peel_borrows() && let hir::ExprKind::Path(hir::QPath::Resolved( None, hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) = arg.kind - && let Some(Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) - && let Some(preds) = self.reported_trait_errors.borrow().get(&pat.span) + && let Node::Pat(pat) = self.tcx.hir_node(*hir_id) + && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span) && preds.contains(&obligation.predicate) { - return true; + return Err(*guar); } - false + Ok(()) } /// When the `E` of the resulting `Result` in an expression `foo().bar().baz()?`, @@ -1033,10 +1037,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id); - let body_id = match self.tcx.opt_hir_node(hir_id) { - Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => { - body_id - } + let body_id = match self.tcx.hir_node(hir_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id, _ => return false, }; let mut v = V { search_span: span, found: None }; @@ -1159,7 +1161,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id) { // We've reached the root of the method call chain... @@ -1303,12 +1305,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut pred = obligation.predicate.to_opt_poly_trait_pred(); while let Some((next_code, next_pred)) = code.parent() { if let Some(pred) = pred { - let pred = self.instantiate_binder_with_placeholders(pred); - diag.note(format!( - "`{}` must implement `{}`, but it does not", - pred.self_ty(), - pred.print_modifiers_and_trait_path() - )); + self.enter_forall(pred, |pred| { + diag.note(format!( + "`{}` must implement `{}`, but it does not", + pred.self_ty(), + pred.print_modifiers_and_trait_path() + )); + }) } code = next_code; pred = next_pred; @@ -1323,13 +1326,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> { // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>); + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed; fn report_projection_error( &self, obligation: &PredicateObligation<'tcx>, error: &MismatchedProjectionTypes<'tcx>, - ); + ) -> ErrorGuaranteed; fn maybe_detailed_projection_msg( &self, @@ -1395,7 +1398,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> { trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, ) -> PredicateObligation<'tcx>; - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>); + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed; fn predicate_can_apply( &self, @@ -1512,13 +1515,13 @@ pub(super) trait InferCtxtPrivExt<'tcx> { span: Span, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option>; + ) -> Result, ErrorGuaranteed>; fn report_not_const_evaluatable_error( &self, obligation: &PredicateObligation<'tcx>, span: Span, - ) -> Option>; + ) -> Result, ErrorGuaranteed>; } impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { @@ -1564,7 +1567,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) { + fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed { if self.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() == DumpSolverProofTree::OnError { @@ -1572,31 +1575,29 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } match error.code { - FulfillmentErrorCode::SelectionError(ref selection_error) => { - self.report_selection_error( + FulfillmentErrorCode::SelectionError(ref selection_error) => self + .report_selection_error( error.obligation.clone(), &error.root_obligation, selection_error, - ); - } + ), FulfillmentErrorCode::ProjectionError(ref e) => { - self.report_projection_error(&error.obligation, e); + self.report_projection_error(&error.obligation, e) } FulfillmentErrorCode::Ambiguity { overflow: false } => { - self.maybe_report_ambiguity(&error.obligation); + self.maybe_report_ambiguity(&error.obligation) } FulfillmentErrorCode::Ambiguity { overflow: true } => { - self.report_overflow_no_abort(error.obligation.clone()); + self.report_overflow_no_abort(error.obligation.clone()) } - FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => { - self.report_mismatched_types( + FulfillmentErrorCode::SubtypeError(ref expected_found, ref err) => self + .report_mismatched_types( &error.obligation.cause, expected_found.expected, expected_found.found, *err, ) - .emit(); - } + .emit(), FulfillmentErrorCode::ConstEquateError(ref expected_found, ref err) => { let mut diag = self.report_mismatched_consts( &error.obligation.cause, @@ -1620,11 +1621,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &mut Default::default(), ); } - diag.emit(); - } - FulfillmentErrorCode::Cycle(ref cycle) => { - self.report_overflow_obligation_cycle(cycle); + diag.emit() } + FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle), } } @@ -1633,11 +1632,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, error: &MismatchedProjectionTypes<'tcx>, - ) { + ) -> ErrorGuaranteed { let predicate = self.resolve_vars_if_possible(obligation.predicate); - if predicate.references_error() { - return; + if let Err(e) = predicate.error_reported() { + return e; } self.probe(|_| { @@ -1802,8 +1801,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { false, ); self.note_obligation_cause(&mut diag, obligation); - diag.emit(); - }); + diag.emit() + }) } fn maybe_detailed_projection_msg( @@ -1876,6 +1875,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Coroutine(..) => Some(18), ty::Foreign(..) => Some(19), ty::CoroutineWitness(..) => Some(20), + ty::CoroutineClosure(..) => Some(21), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } @@ -1925,45 +1925,50 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str { match kind { hir::ClosureKind::Closure => "a closure", - hir::ClosureKind::Coroutine(kind) => match kind { - hir::CoroutineKind::Coroutine(_) => "a coroutine", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Block, - ) => "an async block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Fn, - ) => "an async function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Closure, - ) => "an async closure", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Block, - ) => "an async gen block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Fn, - ) => "an async gen function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::AsyncGen, - hir::CoroutineSource::Closure, - ) => "an async gen closure", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Block, - ) => "a gen block", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Fn, - ) => "a gen function", - hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Gen, - hir::CoroutineSource::Closure, - ) => "a gen closure", - }, + hir::ClosureKind::Coroutine(hir::CoroutineKind::Coroutine(_)) => "a coroutine", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Block, + )) => "an async block", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Fn, + )) => "an async function", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Closure, + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => { + "an async closure" + } + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Block, + )) => "an async gen block", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Fn, + )) => "an async gen function", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::AsyncGen, + hir::CoroutineSource::Closure, + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::AsyncGen) => { + "an async gen closure" + } + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Block, + )) => "a gen block", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Fn, + )) => "a gen function", + hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Gen, + hir::CoroutineSource::Closure, + )) + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => "a gen closure", } } @@ -2011,70 +2016,78 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let [single] = &impl_candidates { if self.probe(|_| { let ocx = ObligationCtxt::new(self); - let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref); - let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); - let impl_trait_ref = ocx.normalize( - &ObligationCause::dummy(), - param_env, - ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), - ); - ocx.register_obligations( - self.tcx - .predicates_of(single.impl_def_id) - .instantiate(self.tcx, impl_args) - .into_iter() - .map(|(clause, _)| { - Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause) - }), - ); - if !ocx.select_where_possible().is_empty() { - return false; - } + self.enter_forall(trait_ref, |obligation_trait_ref| { + let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); + let impl_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), + ); - let mut terrs = vec![]; - for (obligation_arg, impl_arg) in - std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) - { - if let Err(terr) = - ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) - { - terrs.push(terr); - } + ocx.register_obligations( + self.tcx + .predicates_of(single.impl_def_id) + .instantiate(self.tcx, impl_args) + .into_iter() + .map(|(clause, _)| { + Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + clause, + ) + }), + ); if !ocx.select_where_possible().is_empty() { return false; } - } - // Literally nothing unified, just give up. - if terrs.len() == impl_trait_ref.args.len() { - return false; - } + let mut terrs = vec![]; + for (obligation_arg, impl_arg) in + std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) + { + if let Err(terr) = + ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) + { + terrs.push(terr); + } + if !ocx.select_where_possible().is_empty() { + return false; + } + } - let cand = - self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder { - tcx: self.tcx, - ty_op: |ty| ty, - lt_op: |lt| lt, - ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), - }); - err.highlighted_help(vec![ - (format!("the trait `{}` ", cand.print_trait_sugared()), Style::NoStyle), - ("is".to_string(), Style::Highlight), - (" implemented for `".to_string(), Style::NoStyle), - (cand.self_ty().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - ]); + // Literally nothing unified, just give up. + if terrs.len() == impl_trait_ref.args.len() { + return false; + } - if let [TypeError::Sorts(exp_found)] = &terrs[..] { - let exp_found = self.resolve_vars_if_possible(*exp_found); - err.help(format!( - "for that trait implementation, expected `{}`, found `{}`", - exp_found.expected, exp_found.found - )); - } + let cand = self.resolve_vars_if_possible(impl_trait_ref).fold_with( + &mut BottomUpFolder { + tcx: self.tcx, + ty_op: |ty| ty, + lt_op: |lt| lt, + ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), + }, + ); + err.highlighted_help(vec![ + StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())), + StringPart::highlighted("is"), + StringPart::normal(" implemented for `"), + StringPart::highlighted(cand.self_ty().to_string()), + StringPart::normal("`"), + ]); + + if let [TypeError::Sorts(exp_found)] = &terrs[..] { + let exp_found = self.resolve_vars_if_possible(*exp_found); + err.help(format!( + "for that trait implementation, expected `{}`, found `{}`", + exp_found.expected, exp_found.found + )); + } - true + true + }) }) { return true; } @@ -2095,12 +2108,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { _ => (" implemented for `", ""), }; err.highlighted_help(vec![ - (format!("the trait `{}` ", cand.print_trait_sugared()), Style::NoStyle), - ("is".to_string(), Style::Highlight), - (desc.to_string(), Style::NoStyle), - (cand.self_ty().to_string(), Style::Highlight), - ("`".to_string(), Style::NoStyle), - (mention_castable.to_string(), Style::NoStyle), + StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())), + StringPart::highlighted("is"), + StringPart::normal(desc), + StringPart::highlighted(cand.self_ty().to_string()), + StringPart::normal("`"), + StringPart::normal(mention_castable), ]); return true; } @@ -2341,7 +2354,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { + fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a @@ -2361,8 +2374,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_ref = bound_predicate.rebind(data.trait_ref); debug!(?trait_ref); - if predicate.references_error() { - return; + if let Err(e) = predicate.error_reported() { + return e; + } + + if let Err(guar) = self.tcx.ensure().coherent_trait(trait_ref.def_id()) { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + return guar; } // This is kind of a hack: it frequently happens that some earlier @@ -2381,17 +2400,20 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // check upstream for type errors and don't add the obligations to // begin with in those cases. if self.tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) { - if let None = self.tainted_by_errors() { - let err = self.emit_inference_failure_err( - obligation.cause.body_id, - span, - trait_ref.self_ty().skip_binder().into(), - ErrorCode::E0282, - false, - ); - err.stash(span, StashKey::MaybeForgetReturn); + match self.tainted_by_errors() { + None => { + let err = self.emit_inference_failure_err( + obligation.cause.body_id, + span, + trait_ref.self_ty().skip_binder().into(), + ErrorCode::E0282, + false, + ); + err.stash(span, StashKey::MaybeForgetReturn); + return self.dcx().delayed_bug("stashed error never reported"); + } + Some(e) => return e, } - return; } // Typically, this ambiguity should only happen if @@ -2450,19 +2472,21 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } if ambiguities.len() > 1 && ambiguities.len() < 10 && has_non_region_infer { - if self.tainted_by_errors().is_some() && subst.is_none() { + if let Some(e) = self.tainted_by_errors() + && subst.is_none() + { // If `subst.is_none()`, then this is probably two param-env // candidates or impl candidates that are equal modulo lifetimes. // Therefore, if we've already emitted an error, just skip this // one, since it's not particularly actionable. err.cancel(); - return; + return e; } self.annotate_source_of_ambiguity(&mut err, &ambiguities, predicate); } else { - if self.tainted_by_errors().is_some() { + if let Some(e) = self.tainted_by_errors() { err.cancel(); - return; + return e; } err.note(format!("cannot satisfy `{predicate}`")); let impl_candidates = self @@ -2493,7 +2517,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { expr_finder.visit_expr(self.tcx.hir().body(body_id).value); if let Some(hir::Expr { - kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), + kind: + hir::ExprKind::Call( + hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), + .. + }, + _, + ) + | hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. }) = expr_finder.result && let [ @@ -2605,11 +2637,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { // Same hacky approach as above to avoid deluging user // with error messages. - if arg.references_error() - || self.dcx().has_errors().is_some() - || self.tainted_by_errors().is_some() - { - return; + + if let Err(e) = arg.error_reported() { + return e; + } + if let Some(e) = self.tainted_by_errors() { + return e; } self.emit_inference_failure_err( @@ -2622,12 +2655,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::Subtype(data) => { - if data.references_error() - || self.dcx().has_errors().is_some() - || self.tainted_by_errors().is_some() - { - // no need to overload user in such cases - return; + if let Err(e) = data.error_reported() { + return e; + } + if let Some(e) = self.tainted_by_errors() { + return e; } let SubtypePredicate { a_is_expected: _, a, b } = data; // both must be type variables, or the other would've been instantiated @@ -2641,8 +2673,19 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) } ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => { - if predicate.references_error() || self.tainted_by_errors().is_some() { - return; + if let Err(e) = predicate.error_reported() { + return e; + } + if let Some(e) = self.tainted_by_errors() { + return e; + } + + if let Err(guar) = + self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_ty.def_id)) + { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + return guar; } let subst = data .projection_ty @@ -2673,8 +2716,11 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(data)) => { - if predicate.references_error() || self.tainted_by_errors().is_some() { - return; + if let Err(e) = predicate.error_reported() { + return e; + } + if let Some(e) = self.tainted_by_errors() { + return e; } let subst = data.walk().find(|g| g.is_non_region_infer()); if let Some(subst) = subst { @@ -2699,8 +2745,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } _ => { - if self.dcx().has_errors().is_some() || self.tainted_by_errors().is_some() { - return; + if let Some(e) = self.tainted_by_errors() { + return e; } struct_span_code_err!( self.dcx(), @@ -2713,7 +2759,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } }; self.note_obligation_cause(&mut err, obligation); - err.emit(); + err.emit() } fn annotate_source_of_ambiguity( @@ -3433,16 +3479,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { span: Span, found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, - ) -> Option> { + ) -> Result, ErrorGuaranteed> { let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); - if expected_trait_ref.self_ty().references_error() { - return None; - } + expected_trait_ref.self_ty().error_reported()?; let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else { - return None; + return Err(self.dcx().delayed_bug("bound vars outside binder")); }; let found_did = match *found_trait_ty.kind() { @@ -3456,7 +3500,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if !self.reported_signature_mismatch.borrow_mut().insert((span, found_span)) { // We check closures twice, with obligations flowing in different directions, // but we want to complain about them only once. - return None; + return Err(self.dcx().span_delayed_bug(span, "already_reported")); } let mut not_tupled = false; @@ -3485,7 +3529,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // This shouldn't be common unless manually implementing one of the // traits manually, but don't make it more confusing when it does // happen. - Some( + Ok( if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().coroutine_trait() && not_tupled { @@ -3534,9 +3578,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, span: Span, - ) -> Option> { + ) -> Result, ErrorGuaranteed> { if !self.tcx.features().generic_const_exprs { - self.dcx() + let guar = self + .dcx() .struct_span_err(span, "constant expression depends on a generic parameter") // FIXME(const_generics): we should suggest to the user how they can resolve this // issue. However, this is currently not actually possible @@ -3546,7 +3591,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // be reachable. .with_note("this may fail depending on what value the parameter takes") .emit(); - return None; + return Err(guar); } match obligation.predicate.kind().skip_binder() { @@ -3561,13 +3606,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { )), _ => err.help("consider adding a `where` bound using this expression"), }; - Some(err) + Ok(err) } ty::ConstKind::Expr(_) => { let err = self .dcx() .struct_span_err(span, format!("unconstrained generic constant `{ct}`")); - Some(err) + Ok(err) } _ => { bug!("const evaluatable failed for non-unevaluated const `{ct:?}`"); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 0337672b3027e..5ef7a202a1253 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -358,8 +358,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::Coerce(_) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) => { - let pred = - ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder)); + let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder)); ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 0cd376fcbbdc8..93f9c2333f0c0 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -1,5 +1,6 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. +use crate::regions::InferCtxtRegionExt; use crate::traits::{self, ObligationCause, ObligationCtxt}; use hir::LangItem; diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 080ad7bd549c8..a7f6021d57a96 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -25,6 +25,7 @@ pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{InferCtxt, TyCtxtInferExt}; +use crate::regions::InferCtxtRegionExt; use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_errors::ErrorGuaranteed; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index abbc2066eac16..95f833372fb77 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -40,6 +40,7 @@ use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; use std::collections::BTreeMap; +use std::ops::ControlFlow; pub use rustc_middle::traits::Reveal; @@ -250,8 +251,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx; let r = infcx.commit_if_ok(|_snapshot| { let old_universe = infcx.universe(); - let placeholder_predicate = - infcx.instantiate_binder_with_placeholders(obligation.predicate); + let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate); let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); @@ -1615,32 +1615,44 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { debug!("assemble_candidates_from_trait_def(..)"); + let mut ambiguous = false; + selcx.for_each_item_bound( + obligation.predicate.self_ty(), + |selcx, clause, _| { + let Some(clause) = clause.as_projection_clause() else { + return ControlFlow::Continue(()); + }; - let tcx = selcx.tcx(); - // Check whether the self-type is itself a projection. - // If so, extract what we know from the trait and try to come up with a good answer. - let bounds = match *obligation.predicate.self_ty().kind() { - // Excluding IATs and type aliases here as they don't have meaningful item bounds. - ty::Alias(ty::Projection | ty::Opaque, ref data) => { - tcx.item_bounds(data.def_id).instantiate(tcx, data.args) - } - ty::Infer(ty::TyVar(_)) => { - // If the self-type is an inference variable, then it MAY wind up - // being a projected type, so induce an ambiguity. - candidate_set.mark_ambiguous(); - return; - } - _ => return, - }; + let is_match = + selcx.infcx.probe(|_| selcx.match_projection_projections(obligation, clause, true)); - assemble_candidates_from_predicates( - selcx, - obligation, - candidate_set, - ProjectionCandidate::TraitDef, - bounds.iter(), - true, + match is_match { + ProjectionMatchesProjection::Yes => { + candidate_set.push_candidate(ProjectionCandidate::TraitDef(clause)); + + if !obligation.predicate.has_non_region_infer() { + // HACK: Pick the first trait def candidate for a fully + // inferred predicate. This is to allow duplicates that + // differ only in normalization. + return ControlFlow::Break(()); + } + } + ProjectionMatchesProjection::Ambiguous => { + candidate_set.mark_ambiguous(); + } + ProjectionMatchesProjection::No => {} + } + + ControlFlow::Continue(()) + }, + // `ProjectionCandidateSet` is borrowed in the above closure, + // so just mark ambiguous outside of the closure. + || ambiguous = true, ); + + if ambiguous { + candidate_set.mark_ambiguous(); + } } /// In the case of a trait object like @@ -1833,10 +1845,28 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( lang_items.fn_trait(), lang_items.fn_mut_trait(), lang_items.fn_once_trait(), + lang_items.async_fn_trait(), + lang_items.async_fn_mut_trait(), + lang_items.async_fn_once_trait(), ].contains(&Some(trait_ref.def_id)) { true - }else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) { + } else if lang_items.async_fn_kind_helper() == Some(trait_ref.def_id) { + // FIXME(async_closures): Validity constraints here could be cleaned up. + if obligation.predicate.args.type_at(0).is_ty_var() + || obligation.predicate.args.type_at(4).is_ty_var() + || obligation.predicate.args.type_at(5).is_ty_var() + { + candidate_set.mark_ambiguous(); + true + } else if obligation.predicate.args.type_at(0).to_opt_closure_kind().is_some() + && obligation.predicate.args.type_at(1).to_opt_closure_kind().is_some() + { + true + } else { + false + } + } else if lang_items.discriminant_kind_trait() == Some(trait_ref.def_id) { match self_ty.kind() { ty::Bool | ty::Char @@ -1854,6 +1884,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::FnPtr(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never @@ -1903,6 +1934,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( | ty::FnPtr(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never @@ -1916,10 +1948,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats are always Sized, and so have unit type metadata. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, - // type parameters, opaques, and unnormalized projections have pointer - // metadata if they're known (e.g. by the param_env) to be sized + // We normalize from `Wrapper::Metadata` to `Tail::Metadata` if able. + // Otherwise, type parameters, opaques, and unnormalized projections have + // unit metadata if they're known (e.g. by the param_env) to be sized. ty::Param(_) | ty::Alias(..) - if selcx.infcx.predicate_must_hold_modulo_regions( + if self_ty != tail || selcx.infcx.predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]), @@ -2059,6 +2092,10 @@ fn confirm_select_candidate<'cx, 'tcx>( } else { confirm_fn_pointer_candidate(selcx, obligation, data) } + } else if selcx.tcx().async_fn_trait_kind_from_def_id(trait_def_id).is_some() { + confirm_async_closure_candidate(selcx, obligation, data) + } else if lang_items.async_fn_kind_helper() == Some(trait_def_id) { + confirm_async_fn_kind_helper_candidate(selcx, obligation, data) } else { confirm_builtin_candidate(selcx, obligation, data) } @@ -2289,7 +2326,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( assert_eq!(metadata_def_id, item_def_id); let mut obligations = Vec::new(); - let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| { + let normalize = |ty| { normalize_with_depth_to( selcx, obligation.param_env, @@ -2298,16 +2335,27 @@ fn confirm_builtin_candidate<'cx, 'tcx>( ty, &mut obligations, ) + }; + let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| { + if tail == self_ty { + // This is the "fallback impl" for type parameters, unnormalizable projections + // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. + // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't + // exist. Instead, `Pointee` should be a supertrait of `Sized`. + let sized_predicate = ty::TraitRef::from_lang_item( + tcx, + LangItem::Sized, + obligation.cause.span(), + [self_ty], + ); + obligations.push(obligation.with(tcx, sized_predicate)); + tcx.types.unit + } else { + // We know that `self_ty` has the same metadata as `tail`. This allows us + // to prove predicates like `Wrapper::Metadata == Tail::Metadata`. + Ty::new_projection(tcx, metadata_def_id, [tail]) + } }); - if check_is_sized { - let sized_predicate = ty::TraitRef::from_lang_item( - tcx, - LangItem::Sized, - obligation.cause.span(), - [self_ty], - ); - obligations.push(obligation.with(tcx, sized_predicate)); - } (metadata_ty.into(), obligations) } else { bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate); @@ -2419,6 +2467,173 @@ fn confirm_callable_candidate<'cx, 'tcx>( confirm_param_env_candidate(selcx, obligation, predicate, true) } +fn confirm_async_closure_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + mut nested: Vec>, +) -> Progress<'tcx> { + let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); + let ty::CoroutineClosure(def_id, args) = *self_ty.kind() else { + unreachable!( + "expected coroutine-closure self type for coroutine-closure candidate, found {self_ty}" + ) + }; + let args = args.as_coroutine_closure(); + let kind_ty = args.kind_ty(); + + let tcx = selcx.tcx(); + let goal_kind = + tcx.async_fn_trait_kind_from_def_id(obligation.predicate.trait_def_id(tcx)).unwrap(); + + let async_fn_kind_helper_trait_def_id = + tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); + nested.push(obligation.with( + tcx, + ty::TraitRef::new( + tcx, + async_fn_kind_helper_trait_def_id, + [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], + ), + )); + + let env_region = match goal_kind { + ty::ClosureKind::Fn | ty::ClosureKind::FnMut => obligation.predicate.args.region_at(2), + ty::ClosureKind::FnOnce => tcx.lifetimes.re_static, + }; + + let upvars_projection_def_id = tcx + .associated_items(async_fn_kind_helper_trait_def_id) + .filter_by_name_unhygienic(sym::Upvars) + .next() + .unwrap() + .def_id; + + // FIXME(async_closures): Confirmation is kind of a mess here. Ideally, + // we'd short-circuit when we know that the goal_kind >= closure_kind, and not + // register a nested predicate or create a new projection ty here. But I'm too + // lazy to make this more efficient atm, and we can always tweak it later, + // since all this does is make the solver do more work. + // + // The code duplication due to the different length args is kind of weird, too. + // + // See the logic in `structural_traits` in the new solver to understand a bit + // more clearly how this *should* look. + let poly_cache_entry = args.coroutine_closure_sig().map_bound(|sig| { + let (projection_ty, term) = match tcx.item_name(obligation.predicate.def_id) { + sym::CallOnceFuture => { + let tupled_upvars_ty = Ty::new_projection( + tcx, + upvars_projection_def_id, + [ + ty::GenericArg::from(kind_ty), + Ty::from_closure_kind(tcx, goal_kind).into(), + env_region.into(), + sig.tupled_inputs_ty.into(), + args.tupled_upvars_ty().into(), + args.coroutine_captures_by_ref_ty().into(), + ], + ); + let coroutine_ty = sig.to_coroutine( + tcx, + args.parent_args(), + Ty::from_closure_kind(tcx, goal_kind), + tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ); + ( + ty::AliasTy::new( + tcx, + obligation.predicate.def_id, + [self_ty, sig.tupled_inputs_ty], + ), + coroutine_ty.into(), + ) + } + sym::CallMutFuture | sym::CallFuture => { + let tupled_upvars_ty = Ty::new_projection( + tcx, + upvars_projection_def_id, + [ + ty::GenericArg::from(kind_ty), + Ty::from_closure_kind(tcx, goal_kind).into(), + env_region.into(), + sig.tupled_inputs_ty.into(), + args.tupled_upvars_ty().into(), + args.coroutine_captures_by_ref_ty().into(), + ], + ); + let coroutine_ty = sig.to_coroutine( + tcx, + args.parent_args(), + Ty::from_closure_kind(tcx, goal_kind), + tcx.coroutine_for_closure(def_id), + tupled_upvars_ty, + ); + ( + ty::AliasTy::new( + tcx, + obligation.predicate.def_id, + [ + ty::GenericArg::from(self_ty), + sig.tupled_inputs_ty.into(), + env_region.into(), + ], + ), + coroutine_ty.into(), + ) + } + sym::Output => ( + ty::AliasTy::new(tcx, obligation.predicate.def_id, [self_ty, sig.tupled_inputs_ty]), + sig.return_ty.into(), + ), + name => bug!("no such associated type: {name}"), + }; + ty::ProjectionPredicate { projection_ty, term } + }); + + confirm_param_env_candidate(selcx, obligation, poly_cache_entry, true) + .with_addl_obligations(nested) +} + +fn confirm_async_fn_kind_helper_candidate<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + obligation: &ProjectionTyObligation<'tcx>, + nested: Vec>, +) -> Progress<'tcx> { + let [ + // We already checked that the goal_kind >= closure_kind + _closure_kind_ty, + goal_kind_ty, + borrow_region, + tupled_inputs_ty, + tupled_upvars_ty, + coroutine_captures_by_ref_ty, + ] = **obligation.predicate.args + else { + bug!(); + }; + + let predicate = ty::ProjectionPredicate { + projection_ty: ty::AliasTy::new( + selcx.tcx(), + obligation.predicate.def_id, + obligation.predicate.args, + ), + term: ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind( + selcx.tcx(), + goal_kind_ty.expect_ty().to_opt_closure_kind().unwrap(), + tupled_inputs_ty.expect_ty(), + tupled_upvars_ty.expect_ty(), + coroutine_captures_by_ref_ty.expect_ty(), + borrow_region.expect_region(), + ) + .into(), + }; + + confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) + .with_addl_obligations(nested) +} + fn confirm_param_env_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 79f03242c5876..6c8834f11f1eb 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -48,7 +48,11 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { // (T1..Tn) and closures have same properties as T1..Tn -- // check if *all* of them are trivial. ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), + ty::Closure(_, args) => trivial_dropck_outlives(tcx, args.as_closure().tupled_upvars_ty()), + ty::CoroutineClosure(_, args) => { + trivial_dropck_outlives(tcx, args.as_coroutine_closure().tupled_upvars_ty()) + } ty::Adt(def, _) => { if Some(def.did()) == tcx.lang_items().manually_drop() { @@ -239,6 +243,22 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( Ok::<_, NoSolution>(()) })?, + ty::CoroutineClosure(_, args) => { + rustc_data_structures::stack::ensure_sufficient_stack(|| { + for ty in args.as_coroutine_closure().upvar_tys() { + dtorck_constraint_for_ty_inner( + tcx, + param_env, + span, + depth + 1, + ty, + constraints, + )?; + } + Ok::<_, NoSolution>(()) + })? + } + ty::Coroutine(_, args) => { // rust-lang/rust#49918: types can be constructed, stored // in the interior, and sit idle when coroutine yields diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 4c0c57377e02a..a050b30317a05 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -41,7 +41,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// not entirely accurate if inference variables are involved. /// /// This version may conservatively fail when outlives obligations - /// are required. + /// are required. Therefore, this version should only be used for + /// optimizations or diagnostics and be treated as if it can always + /// return `false`. + /// + /// # Example + /// + /// ``` + /// # #![allow(dead_code)] + /// trait Trait {} + /// + /// fn check() {} + /// + /// fn foo() + /// where + /// &'static T: Trait, + /// { + /// // Evaluating `&'?0 T: Trait` adds a `'?0: 'static` outlives obligation, + /// // which means that `predicate_must_hold_considering_regions` will return + /// // `false`. + /// check::<&'_ T>(); + /// } + /// ``` fn predicate_must_hold_considering_regions( &self, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 12aea88e9b6a2..27dbe0351da12 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -6,13 +6,16 @@ //! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly +use std::ops::ControlFlow; + use hir::def_id::DefId; use hir::LangItem; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; -use rustc_middle::ty::{self, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use crate::traits; use crate::traits::query::evaluate_obligation::InferCtxtExt; @@ -117,10 +120,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.assemble_iterator_candidates(obligation, &mut candidates); } else if lang_items.async_iterator_trait() == Some(def_id) { self.assemble_async_iterator_candidates(obligation, &mut candidates); + } else if lang_items.async_fn_kind_helper() == Some(def_id) { + self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates); } + // FIXME: Put these into `else if` blocks above, since they're built-in. self.assemble_closure_candidates(obligation, &mut candidates); + self.assemble_async_closure_candidates(obligation, &mut candidates); self.assemble_fn_pointer_candidates(obligation, &mut candidates); + self.assemble_candidates_from_impls(obligation, &mut candidates); self.assemble_candidates_from_object_ty(obligation, &mut candidates); } @@ -153,11 +161,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, } - let result = self - .infcx - .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); + self.infcx.probe(|_| { + let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let placeholder_trait_predicate = + self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); + debug!(?placeholder_trait_predicate); + + // The bounds returned by `item_bounds` may contain duplicates after + // normalization, so try to deduplicate when possible to avoid + // unnecessary ambiguity. + let mut distinct_normalized_bounds = FxHashSet::default(); + self.for_each_item_bound::( + placeholder_trait_predicate.self_ty(), + |selcx, bound, idx| { + let Some(bound) = bound.as_trait_clause() else { + return ControlFlow::Continue(()); + }; + if bound.polarity() != placeholder_trait_predicate.polarity { + return ControlFlow::Continue(()); + } + + selcx.infcx.probe(|_| { + match selcx.match_normalize_trait_ref( + obligation, + bound.to_poly_trait_ref(), + placeholder_trait_predicate.trait_ref, + ) { + Ok(None) => { + candidates.vec.push(ProjectionCandidate(idx)); + } + Ok(Some(normalized_trait)) + if distinct_normalized_bounds.insert(normalized_trait) => + { + candidates.vec.push(ProjectionCandidate(idx)); + } + _ => {} + } + }); - candidates.vec.extend(result.into_iter().map(|idx| ProjectionCandidate(idx))); + ControlFlow::Continue(()) + }, + // On ambiguity. + || candidates.ambiguous = true, + ); + }); } /// Given an obligation like ``, searches the obligations that the caller @@ -306,11 +353,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the args on closure types never // touch bound regions, they just capture the in-scope // type/region parameters - match *obligation.self_ty().skip_binder().kind() { - ty::Closure(def_id, closure_args) => { + let self_ty = obligation.self_ty().skip_binder(); + match *self_ty.kind() { + ty::Closure(def_id, _) => { let is_const = self.tcx().is_const_fn_raw(def_id); debug!(?kind, ?obligation, "assemble_unboxed_candidates"); - match self.infcx.closure_kind(closure_args) { + match self.infcx.closure_kind(self_ty) { Some(closure_kind) => { debug!(?closure_kind, "assemble_unboxed_candidates"); if closure_kind.extends(kind) { @@ -334,6 +382,61 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + fn assemble_async_closure_candidates( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + let Some(goal_kind) = + self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()) + else { + return; + }; + + match *obligation.self_ty().skip_binder().kind() { + ty::CoroutineClosure(_, args) => { + if let Some(closure_kind) = + args.as_coroutine_closure().kind_ty().to_opt_closure_kind() + && !closure_kind.extends(goal_kind) + { + return; + } + candidates.vec.push(AsyncClosureCandidate); + } + ty::Infer(ty::TyVar(_)) => { + candidates.ambiguous = true; + } + _ => {} + } + } + + fn assemble_async_fn_kind_helper_candidates( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + candidates: &mut SelectionCandidateSet<'tcx>, + ) { + let self_ty = obligation.self_ty().skip_binder(); + let target_kind_ty = obligation.predicate.skip_binder().trait_ref.args.type_at(1); + + // `to_opt_closure_kind` is kind of ICEy when it sees non-int types. + if !(self_ty.is_integral() || self_ty.is_ty_var()) { + return; + } + if !(target_kind_ty.is_integral() || self_ty.is_ty_var()) { + return; + } + + // Check that the self kind extends the goal kind. If it does, + // then there's nothing else to check. + if let Some(closure_kind) = self_ty.to_opt_closure_kind() + && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind() + { + if closure_kind.extends(goal_kind) { + candidates.vec.push(AsyncFnKindHelperCandidate); + } + } + } + /// Implements one of the `Fn()` family for a fn pointer. fn assemble_fn_pointer_candidates( &mut self, @@ -488,7 +591,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Slice(_) | ty::RawPtr(_) | ty::Ref(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -623,7 +727,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Ref(..) | ty::FnDef(..) | ty::FnPtr(_) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Never | ty::Tuple(_) @@ -665,64 +770,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|_snapshot| { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); - let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); - - let self_ty = placeholder_trait_predicate.self_ty(); - let principal_trait_ref = match self_ty.kind() { - ty::Dynamic(data, ..) => { - if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { - debug!( - "assemble_candidates_from_object_ty: matched builtin bound, \ + self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| { + let self_ty = placeholder_trait_predicate.self_ty(); + let principal_trait_ref = match self_ty.kind() { + ty::Dynamic(data, ..) => { + if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { + debug!( + "assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate" - ); - candidates.vec.push(BuiltinObjectCandidate); - return; - } + ); + candidates.vec.push(BuiltinObjectCandidate); + return; + } - if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { - principal.with_self_ty(self.tcx(), self_ty) - } else if self.tcx().check_is_object_safe(principal.def_id()) { - principal.with_self_ty(self.tcx(), self_ty) + if let Some(principal) = data.principal() { + if !self.infcx.tcx.features().object_safe_for_dispatch { + principal.with_self_ty(self.tcx(), self_ty) + } else if self.tcx().check_is_object_safe(principal.def_id()) { + principal.with_self_ty(self.tcx(), self_ty) + } else { + return; + } } else { + // Only auto trait bounds exist. return; } - } else { - // Only auto trait bounds exist. + } + ty::Infer(ty::TyVar(_)) => { + debug!("assemble_candidates_from_object_ty: ambiguous"); + candidates.ambiguous = true; // could wind up being an object type return; } - } - ty::Infer(ty::TyVar(_)) => { - debug!("assemble_candidates_from_object_ty: ambiguous"); - candidates.ambiguous = true; // could wind up being an object type - return; - } - _ => return, - }; - - debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); - - // Count only those upcast versions that match the trait-ref - // we are looking for. Specifically, do not only check for the - // correct trait, but also the correct type parameters. - // For example, we may be trying to upcast `Foo` to `Bar`, - // but `Foo` is declared as `trait Foo: Bar`. - let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) - .enumerate() - .filter(|&(_, upcast_trait_ref)| { - self.infcx.probe(|_| { - self.match_normalize_trait_ref( - obligation, - upcast_trait_ref, - placeholder_trait_predicate.trait_ref, - ) - .is_ok() + _ => return, + }; + + debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); + + // Count only those upcast versions that match the trait-ref + // we are looking for. Specifically, do not only check for the + // correct trait, but also the correct type parameters. + // For example, we may be trying to upcast `Foo` to `Bar`, + // but `Foo` is declared as `trait Foo: Bar`. + let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) + .enumerate() + .filter(|&(_, upcast_trait_ref)| { + self.infcx.probe(|_| { + self.match_normalize_trait_ref( + obligation, + upcast_trait_ref, + placeholder_trait_predicate.trait_ref, + ) + .is_ok() + }) }) - }) - .map(|(idx, _)| ObjectCandidate(idx)); + .map(|(idx, _)| ObjectCandidate(idx)); - candidates.vec.extend(candidate_supertraits); + candidates.vec.extend(candidate_supertraits); + }) }) } @@ -1000,6 +1104,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Array(..) | ty::Slice(_) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Tuple(_) | ty::CoroutineWitness(..) => { @@ -1076,7 +1181,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(_) | ty::Dynamic(_, _, _) - | ty::Closure(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never @@ -1139,6 +1245,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Placeholder(..) | ty::Dynamic(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Never diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 74f388e53a3c9..42074f4a079e2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -83,6 +83,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure) } + AsyncClosureCandidate => { + let vtable_closure = self.confirm_async_closure_candidate(obligation)?; + ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure) + } + + // No nested obligations or confirmation process. The checks that we do in + // candidate assembly are sufficient. + AsyncFnKindHelperCandidate => ImplSource::Builtin(BuiltinImplSource::Misc, vec![]), + CoroutineCandidate => { let vtable_coroutine = self.confirm_coroutine_candidate(obligation)?; ImplSource::Builtin(BuiltinImplSource::Misc, vtable_coroutine) @@ -150,23 +159,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref; + self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref; let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); - let (def_id, args) = match *placeholder_self_ty.kind() { - // Excluding IATs and type aliases here as they don't have meaningful item bounds. - ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => { - (def_id, args) - } - _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty), - }; - let candidate_predicate = - tcx.item_bounds(def_id).map_bound(|i| i[idx]).instantiate(tcx, args); + let candidate_predicate = self + .for_each_item_bound( + placeholder_self_ty, + |_, clause, clause_idx| { + if clause_idx == idx { + ControlFlow::Break(clause) + } else { + ControlFlow::Continue(()) + } + }, + || unreachable!(), + ) + .break_value() + .expect("expected to index into clause that exists"); let candidate = candidate_predicate .as_trait_clause() .expect("projection candidate is not a trait predicate") .map_bound(|t| t.trait_ref); + let mut obligations = Vec::new(); let candidate = normalize_with_depth_to( self, @@ -185,8 +200,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|_| Unimplemented) })?); - if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() { - let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args); + // FIXME(compiler-errors): I don't think this is needed. + if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() { + let predicates = tcx.predicates_of(alias_ty.def_id).instantiate_own(tcx, alias_ty.args); for (predicate, _) in predicates { let normalized = normalize_with_depth_to( self, @@ -393,7 +409,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref); + let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref); let trait_obligations: Vec> = self.impl_or_trait_obligations( &cause, obligation.recursion_depth + 1, @@ -484,7 +500,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); debug!(?obligation, ?index, "confirm_object_candidate"); - let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty()); let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref); let ty::Dynamic(data, ..) = *self_ty.kind() else { @@ -682,7 +698,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); // Confirm the `type Output: Sized;` bound that is present on `FnOnce` - let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output()); + let output_ty = self.infcx.enter_forall_and_leak_universe(sig.output()); let output_ty = normalize_with_depth_to( self, obligation.param_env, @@ -703,7 +719,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Vec> { debug!(?obligation, "confirm_trait_alias_candidate"); - let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let args = trait_ref.args; @@ -869,6 +885,49 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ok(nested) } + #[instrument(skip(self), level = "debug")] + fn confirm_async_closure_candidate( + &mut self, + obligation: &PolyTraitObligation<'tcx>, + ) -> Result>, SelectionError<'tcx>> { + // Okay to skip binder because the args on closure types never + // touch bound regions, they just capture the in-scope + // type/region parameters. + let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder()); + let ty::CoroutineClosure(closure_def_id, args) = *self_ty.kind() else { + bug!("async closure candidate for non-coroutine-closure {:?}", obligation); + }; + + let trait_ref = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| { + ty::TraitRef::new( + self.tcx(), + obligation.predicate.def_id(), + [self_ty, sig.tupled_inputs_ty], + ) + }); + + let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + + let goal_kind = + self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap(); + nested.push(obligation.with( + self.tcx(), + ty::TraitRef::from_lang_item( + self.tcx(), + LangItem::AsyncFnKindHelper, + obligation.cause.span, + [ + args.as_coroutine_closure().kind_ty(), + Ty::from_closure_kind(self.tcx(), goal_kind), + ], + ), + )); + + debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations"); + + Ok(nested) + } + /// In the case of closure types and fn pointers, /// we currently treat the input type parameters on the trait as /// outputs. This means that when we have a match we have only diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6a6adcbb680ea..ac6cfcdeb5950 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -52,6 +52,7 @@ use std::cell::{Cell, RefCell}; use std::cmp; use std::fmt::{self, Display}; use std::iter; +use std::ops::ControlFlow; pub use rustc_middle::traits::select::*; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -483,7 +484,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Instead, we select the right impl now but report "`Bar` does // not implement `Clone`". if candidates.len() == 1 { - return self.filter_reservation_impls(candidates.pop().unwrap(), stack.obligation); + return self.filter_reservation_impls(candidates.pop().unwrap()); } // Winnow, but record the exact outcome of evaluation, which @@ -557,7 +558,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // Just one candidate left. - self.filter_reservation_impls(candidates.pop().unwrap().candidate, stack.obligation) + self.filter_reservation_impls(candidates.pop().unwrap().candidate) } /////////////////////////////////////////////////////////////////////////// @@ -1436,7 +1437,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn filter_reservation_impls( &mut self, candidate: SelectionCandidate<'tcx>, - obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); // Treat reservation impls as ambiguity. @@ -1593,71 +1593,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.selection_cache.insert((param_env, pred), dep_node, candidate); } - /// Matches a predicate against the bounds of its self type. - /// - /// Given an obligation like `::Bar: Baz` where the self type is - /// a projection, look at the bounds of `T::Bar`, see if we can find a - /// `Baz` bound. We return indexes into the list returned by - /// `tcx.item_bounds` for any applicable bounds. - #[instrument(level = "debug", skip(self), ret)] - fn match_projection_obligation_against_definition_bounds( + /// Looks at the item bounds of the projection or opaque type. + /// If this is a nested rigid projection, such as + /// `<::Assoc as Tr2>::Assoc`, consider the item bounds + /// on both `Tr1::Assoc` and `Tr2::Assoc`, since we may encounter + /// relative bounds on both via the `associated_type_bounds` feature. + pub(super) fn for_each_item_bound( &mut self, - obligation: &PolyTraitObligation<'tcx>, - ) -> smallvec::SmallVec<[usize; 2]> { - let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); - let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); - debug!(?placeholder_trait_predicate); - - let tcx = self.infcx.tcx; - let (def_id, args) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { - ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => { - (def_id, args) - } - _ => { - span_bug!( - obligation.cause.span, - "match_projection_obligation_against_definition_bounds() called \ - but self-ty is not a projection: {:?}", - placeholder_trait_predicate.trait_ref.self_ty() - ); - } - }; - let bounds = tcx.item_bounds(def_id).instantiate(tcx, args); + mut self_ty: Ty<'tcx>, + mut for_each: impl FnMut(&mut Self, ty::Clause<'tcx>, usize) -> ControlFlow, + on_ambiguity: impl FnOnce(), + ) -> ControlFlow { + let mut idx = 0; + loop { + let (kind, alias_ty) = match *self_ty.kind() { + ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), + ty::Infer(ty::TyVar(_)) => { + on_ambiguity(); + return ControlFlow::Continue(()); + } + _ => return ControlFlow::Continue(()), + }; - // The bounds returned by `item_bounds` may contain duplicates after - // normalization, so try to deduplicate when possible to avoid - // unnecessary ambiguity. - let mut distinct_normalized_bounds = FxHashSet::default(); + for bound in + self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args) + { + for_each(self, bound, idx)?; + idx += 1; + } - bounds - .iter() - .enumerate() - .filter_map(|(idx, bound)| { - let bound_predicate = bound.kind(); - if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() { - let bound = bound_predicate.rebind(pred.trait_ref); - if self.infcx.probe(|_| { - match self.match_normalize_trait_ref( - obligation, - bound, - placeholder_trait_predicate.trait_ref, - ) { - Ok(None) => true, - Ok(Some(normalized_trait)) - if distinct_normalized_bounds.insert(normalized_trait) => - { - true - } - _ => false, - } - }) { - return Some(idx); - } - } - None - }) - .collect() + if kind == ty::Projection { + self_ty = alias_ty.self_ty(); + } else { + return ControlFlow::Continue(()); + } + } } /// Equates the trait in `obligation` with trait bound. If the two traits @@ -1864,6 +1834,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(..) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -1894,6 +1866,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(_) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -1930,6 +1904,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(..) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -1946,6 +1922,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ImplCandidate(..) | AutoImplCandidate | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -2054,6 +2032,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ( ImplCandidate(_) | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -2066,6 +2046,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TraitAliasCandidate, ImplCandidate(_) | ClosureCandidate { .. } + | AsyncClosureCandidate + | AsyncFnKindHelperCandidate | CoroutineCandidate | FutureCandidate | IteratorCandidate @@ -2106,6 +2088,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::CoroutineWitness(..) | ty::Array(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Dynamic(_, _, ty::DynStar) | ty::Error(_) => { @@ -2227,6 +2210,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } } + // FIXME(async_closures): These are never clone, for now. + ty::CoroutineClosure(_, _) => None, + ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => { // Fallback to whatever user-defined impls exist in this case. None @@ -2305,6 +2291,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> { t.rebind(vec![ty]) } + ty::CoroutineClosure(_, args) => { + let ty = self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty()); + t.rebind(vec![ty]) + } + ty::Coroutine(_, args) => { let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty()); let witness = args.as_coroutine().witness(); @@ -2365,7 +2356,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { .flat_map(|ty| { let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/ - let placeholder_ty = self.infcx.instantiate_binder_with_placeholders(ty); + let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty); let Normalized { value: normalized_ty, mut obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( @@ -2451,7 +2442,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation: &PolyTraitObligation<'tcx>, ) -> Result>, ()> { let placeholder_obligation = - self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + self.infcx.enter_forall_and_leak_universe(obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index d5a37e63d8765..89459f377dd2b 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -79,6 +79,9 @@ impl<'tcx> TypeVisitor> for Search<'tcx> { ty::Closure(..) => { return ControlFlow::Break(ty); } + ty::CoroutineClosure(..) => { + return ControlFlow::Break(ty); + } ty::Coroutine(..) | ty::CoroutineWitness(..) => { return ControlFlow::Break(ty); } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 0f8d9c6bf4bdb..b4f13ee95a652 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -727,6 +727,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.out.extend(obligations); } + ty::CoroutineClosure(did, args) => { + // See the above comments. The same apply to coroutine-closures. + walker.skip_current_subtree(); + self.compute(args.as_coroutine_closure().tupled_upvars_ty().into()); + let obligations = self.nominal_obligations(did, args); + self.out.extend(obligations); + } + ty::FnPtr(_) => { // let the loop iterate into the argument/return // types appearing in the fn signature diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index c7916ec60bba2..e73bbf6048ece 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -1,7 +1,5 @@ //! Queries that are independent from the main solver code. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index c80389a3a4d52..ac4f67d1b5565 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -1,8 +1,6 @@ #![feature(alloc_layout_extra)] #![feature(never_type)] #![allow(dead_code, unused_variables)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 333aec1d38d7f..0542ef4ecf902 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -101,6 +101,49 @@ fn fn_sig_for_fn_abi<'tcx>( bound_vars, ) } + ty::CoroutineClosure(def_id, args) => { + let sig = args.as_coroutine_closure().coroutine_closure_sig(); + let bound_vars = tcx.mk_bound_variable_kinds_from_iter( + sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))), + ); + let br = ty::BoundRegion { + var: ty::BoundVar::from_usize(bound_vars.len() - 1), + kind: ty::BoundRegionKind::BrEnv, + }; + let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br); + + // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`, + // make sure we respect the `target_kind` in that shim. + // FIXME(async_closures): This shouldn't be needed, and we should be populating + // a separate def-id for these bodies. + let mut kind = args.as_coroutine_closure().kind(); + if let InstanceDef::ConstructCoroutineInClosureShim { target_kind, .. } = instance.def { + kind = target_kind; + } + + let env_ty = + tcx.closure_env_ty(Ty::new_coroutine_closure(tcx, def_id, args), kind, env_region); + + let sig = sig.skip_binder(); + ty::Binder::bind_with_vars( + tcx.mk_fn_sig( + iter::once(env_ty).chain([sig.tupled_inputs_ty]), + sig.to_coroutine_given_kind_and_upvars( + tcx, + args.as_coroutine_closure().parent_args(), + tcx.coroutine_for_closure(def_id), + kind, + env_region, + args.as_coroutine_closure().tupled_upvars_ty(), + args.as_coroutine_closure().coroutine_captures_by_ref_ty(), + ), + sig.c_variadic, + sig.unsafety, + sig.abi, + ), + bound_vars, + ) + } ty::Coroutine(did, args) => { let coroutine_kind = tcx.coroutine_kind(did).unwrap(); let sig = args.as_coroutine().sig(); @@ -112,6 +155,40 @@ fn fn_sig_for_fn_abi<'tcx>( var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BoundRegionKind::BrEnv, }; + + let mut ty = ty; + // When this `Closure` comes from a `CoroutineKindShim`, + // make sure we respect the `target_kind` in that shim. + // FIXME(async_closures): This shouldn't be needed, and we should be populating + // a separate def-id for these bodies. + if let InstanceDef::CoroutineKindShim { target_kind, .. } = instance.def { + // Grab the parent coroutine-closure. It has the same args for the purposes + // of substitution, so this will be okay to do. + let ty::CoroutineClosure(_, coroutine_closure_args) = *tcx + .instantiate_and_normalize_erasing_regions( + args, + param_env, + tcx.type_of(tcx.parent(did)), + ) + .kind() + else { + bug!("CoroutineKindShim comes from calling a coroutine-closure"); + }; + let coroutine_closure_args = coroutine_closure_args.as_coroutine_closure(); + ty = tcx.instantiate_bound_regions_with_erased( + coroutine_closure_args.coroutine_closure_sig().map_bound(|sig| { + sig.to_coroutine_given_kind_and_upvars( + tcx, + coroutine_closure_args.parent_args(), + did, + target_kind, + tcx.lifetimes.re_erased, + coroutine_closure_args.tupled_upvars_ty(), + coroutine_closure_args.coroutine_captures_by_ref_ty(), + ) + }), + ); + } let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty); let pin_did = tcx.require_lang_item(LangItem::Pin, None); @@ -258,7 +335,6 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv { PtxKernel => Conv::PtxKernel, Msp430Interrupt => Conv::Msp430Intr, X86Interrupt => Conv::X86Intr, - AmdGpuKernel => Conv::AmdGpuKernel, AvrInterrupt => Conv::AvrInterrupt, AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, RiscvInterruptM => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine }, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 2d76cf994e437..9faad10dd14df 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -38,6 +38,7 @@ fn resolve_instance<'tcx>( debug!(" => nontrivial drop glue"); match *ty.kind() { ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::Tuple(..) | ty::Adt(..) @@ -215,6 +216,7 @@ fn resolve_associated_item<'tcx>( ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Tuple(..) => {} _ => return Ok(None), }; @@ -281,6 +283,34 @@ fn resolve_associated_item<'tcx>( tcx.item_name(trait_item_id) ), } + } else if let Some(target_kind) = tcx.async_fn_trait_kind_from_def_id(trait_ref.def_id) + { + match *rcvr_args.type_at(0).kind() { + ty::CoroutineClosure(coroutine_closure_def_id, args) => { + // If we're computing `AsyncFnOnce`/`AsyncFnMut` for a by-ref closure, + // or `AsyncFnOnce` for a by-mut closure, then construct a new body that + // has the right return types. + // + // Specifically, `AsyncFnMut` for a by-ref coroutine-closure just needs + // to have its input and output types fixed (`&mut self` and returning + // `i16` coroutine kind). + if target_kind > args.as_coroutine_closure().kind() { + Some(Instance { + def: ty::InstanceDef::ConstructCoroutineInClosureShim { + coroutine_closure_def_id, + target_kind, + }, + args, + }) + } else { + Some(Instance::new(coroutine_closure_def_id, args)) + } + } + _ => bug!( + "no built-in definition for `{trait_ref}::{}` for non-lending-closure type", + tcx.item_name(trait_item_id) + ), + } } else { Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 2fc4bfd4aa31c..f20ded355b1cd 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -328,6 +328,17 @@ fn layout_of_uncached<'tcx>( )? } + ty::CoroutineClosure(_, args) => { + let tys = args.as_coroutine_closure().upvar_tys(); + univariant( + &tys.iter() + .map(|ty| Ok(cx.layout_of(ty)?.layout)) + .try_collect::>()?, + &ReprOptions::default(), + StructKind::AlwaysSized, + )? + } + ty::Tuple(tys) => { let kind = if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 51acb99d29b58..fd392d11e8317 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -15,8 +15,6 @@ #![feature(iterator_try_collect)] #![feature(let_chains)] #![feature(never_type)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; @@ -37,7 +35,7 @@ mod layout_sanity_check; mod needs_drop; mod opaque_types; mod representability; -mod sig_types; +pub mod sig_types; mod structural_match; mod ty; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 08e5476ae43b7..7b3d2ab22cfa4 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -172,6 +172,12 @@ where } } + ty::CoroutineClosure(_, args) => { + for upvar in args.as_coroutine_closure().upvar_tys() { + queue_type(self, upvar); + } + } + // Check for a `Drop` impl and whether this is a union or // `ManuallyDrop`. If it's a struct or enum without a `Drop` // impl then check whether the field types need `Drop`. diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 3aaa2e73bb805..70f1f099688b8 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -1,5 +1,3 @@ -#![allow(rustc::untranslatable_diagnostic, rustc::diagnostic_outside_of_impl)] - use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::query::Providers; diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index b155a4ac87b9f..38cc558380cd8 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -4,11 +4,11 @@ use std::ops::ControlFlow; use rustc_hir::{def::DefKind, def_id::LocalDefId}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; -pub(crate) trait SpannedTypeVisitor<'tcx> { +pub trait SpannedTypeVisitor<'tcx> { type BreakTy = !; fn visit( &mut self, @@ -17,7 +17,7 @@ pub(crate) trait SpannedTypeVisitor<'tcx> { ) -> ControlFlow; } -pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( +pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( tcx: TyCtxt<'tcx>, item: LocalDefId, visitor: &mut V, @@ -42,11 +42,10 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::TyAlias {..} | DefKind::AssocTy | // Walk over the type of the item DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { - let span = match tcx.hir_node_by_def_id(item).ty() { - Some(ty) => ty.span, - _ => tcx.def_span(item), - }; - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { + // Associated types in traits don't necessarily have a type that we can visit + visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())?; + } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } @@ -59,7 +58,16 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Look at field types DefKind::Struct | DefKind::Union | DefKind::Enum => { let span = tcx.def_ident_span(item).unwrap(); - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + let ty = tcx.type_of(item).instantiate_identity(); + visitor.visit(span, ty); + let ty::Adt(def, args) = ty.kind() else { + span_bug!(span, "invalid type for {kind:?}: {:#?}", ty.kind()) + }; + for field in def.all_fields() { + let span = tcx.def_ident_span(field.did).unwrap(); + let ty = field.ty(tcx, args); + visitor.visit(span, ty); + } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } @@ -89,7 +97,6 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( } } | DefKind::Variant - | DefKind::ForeignTy | DefKind::TyParam | DefKind::ConstParam | DefKind::Ctor(_, _) @@ -103,6 +110,7 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // These don't have any types. | DefKind::ExternCrate | DefKind::ForeignMod + | DefKind::ForeignTy | DefKind::Macro(_) | DefKind::GlobalAsm | DefKind::Mod diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2158aacab03d8..60b1bbe8c2a5f 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -18,7 +18,9 @@ fn sized_constraint_for_ty<'tcx>( let result = match ty.kind() { Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..) - | FnPtr(_) | Array(..) | Closure(..) | Coroutine(..) | Never => vec![], + | FnPtr(_) | Array(..) | Closure(..) | CoroutineClosure(..) | Coroutine(..) | Never => { + vec![] + } Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | CoroutineWitness(..) => { // these are never sized - return the target type diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 83efbfb855f91..f498c5531fcff 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -2,8 +2,6 @@ feature = "nightly", feature(associated_type_defaults, min_specialization, never_type, rustc_attrs) )] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(rustc::usage_of_ty_tykind)] #![cfg_attr(feature = "nightly", allow(internal_features))] diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 3b5e41e8d850e..777c649fabd68 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -163,8 +163,7 @@ pub enum RegionKind { /// A placeholder region -- the higher-ranked version of `ReLateParam`. /// Should not exist outside of type inference. /// - /// Used when instantiating a `forall` binder via - /// `infcx.instantiate_binder_with_placeholders`. + /// Used when instantiating a `forall` binder via `infcx.enter_forall`. RePlaceholder(I::PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 859000fb6cb18..a4fe572067b03 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -202,6 +202,13 @@ pub enum TyKind { /// `ClosureArgs` for more details. Closure(I::DefId, I::GenericArgs), + /// The anonymous type of a closure. Used to represent the type of `async |a| a`. + /// + /// Coroutine-closure args contain both the - potentially substituted - generic + /// parameters of its parent and some synthetic parameters. See the documentation + /// for `CoroutineClosureArgs` for more details. + CoroutineClosure(I::DefId, I::GenericArgs), + /// The anonymous type of a coroutine. Used to represent the type of /// `|a| yield a`. /// @@ -317,16 +324,17 @@ const fn tykind_discriminant(value: &TyKind) -> usize { FnPtr(_) => 13, Dynamic(..) => 14, Closure(_, _) => 15, - Coroutine(_, _) => 16, - CoroutineWitness(_, _) => 17, - Never => 18, - Tuple(_) => 19, - Alias(_, _) => 20, - Param(_) => 21, - Bound(_, _) => 22, - Placeholder(_) => 23, - Infer(_) => 24, - Error(_) => 25, + CoroutineClosure(_, _) => 16, + Coroutine(_, _) => 17, + CoroutineWitness(_, _) => 18, + Never => 19, + Tuple(_) => 20, + Alias(_, _) => 21, + Param(_) => 22, + Bound(_, _) => 23, + Placeholder(_) => 24, + Infer(_) => 25, + Error(_) => 26, } } @@ -356,6 +364,7 @@ impl PartialEq for TyKind { a_p == b_p && a_r == b_r && a_repr == b_repr } (Closure(a_d, a_s), Closure(b_d, b_s)) => a_d == b_d && a_s == b_s, + (CoroutineClosure(a_d, a_s), CoroutineClosure(b_d, b_s)) => a_d == b_d && a_s == b_s, (Coroutine(a_d, a_s), Coroutine(b_d, b_s)) => a_d == b_d && a_s == b_s, (CoroutineWitness(a_d, a_s), CoroutineWitness(b_d, b_s)) => a_d == b_d && a_s == b_s, (Tuple(a_t), Tuple(b_t)) => a_t == b_t, @@ -430,6 +439,9 @@ impl DebugWithInfcx for TyKind { } }, Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(), + CoroutineClosure(d, s) => { + f.debug_tuple("CoroutineClosure").field(d).field(&this.wrap(s)).finish() + } Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).finish(), CoroutineWitness(d, s) => { f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish() diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 53dac6abefb30..a15fd3e0999bd 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -275,7 +275,6 @@ pub enum CallConvention { X86_64SysV, X86_64Win64, - AmdGpuKernel, AvrInterrupt, AvrNonBlockingInterrupt, diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 38877f7a77fc4..be727f024c609 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -639,6 +639,7 @@ impl Rvalue { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { Ok(Ty::usize_ty()) } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => Ok(Ty::bool_ty()), Rvalue::Aggregate(ak, ops) => match *ak { AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), AggregateKind::Tuple => Ok(Ty::new_tuple( @@ -1005,6 +1006,8 @@ pub enum NullOp { AlignOf, /// Returns the offset of a field. OffsetOf(Vec<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but at codegen time + DebugAssertions, } impl Operand { diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index b0a08cd9b792c..bdda929534705 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -864,7 +864,6 @@ pub enum Abi { PtxKernel, Msp430Interrupt, X86Interrupt, - AmdGpuKernel, EfiApi, AvrInterrupt, AvrNonBlockingInterrupt, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 2e32101840780..953041b8c202b 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2284,7 +2284,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { +impl<'a> From for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// # Examples @@ -2299,7 +2299,7 @@ impl From for Box { /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` #[inline] - fn from(err: String) -> Box { + fn from(err: String) -> Box { struct StringError(String); impl Error for StringError { @@ -2328,7 +2328,7 @@ impl From for Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_box_error", since = "1.6.0")] -impl From for Box { +impl<'a> From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. /// /// # Examples @@ -2341,7 +2341,7 @@ impl From for Box { /// let a_boxed_error = Box::::from(a_string_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(str_err: String) -> Box { + fn from(str_err: String) -> Box { let err1: Box = From::from(str_err); let err2: Box = err1; err2 @@ -2374,7 +2374,7 @@ impl<'a> From<&str> for Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "string_box_error", since = "1.6.0")] -impl From<&str> for Box { +impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// /// [`str`]: prim@str @@ -2389,7 +2389,7 @@ impl From<&str> for Box { /// let a_boxed_error = Box::::from(a_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: &str) -> Box { + fn from(err: &str) -> Box { From::from(String::from(err)) } } @@ -2418,7 +2418,7 @@ impl<'a, 'b> From> for Box { #[cfg(not(no_global_oom_handling))] #[stable(feature = "cow_box_error", since = "1.22.0")] -impl<'a> From> for Box { +impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. /// /// # Examples @@ -2432,7 +2432,7 @@ impl<'a> From> for Box { /// let a_boxed_error = Box::::from(a_cow_str_error); /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` - fn from(err: Cow<'a, str>) -> Box { + fn from(err: Cow<'b, str>) -> Box { From::from(String::from(err)) } } diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 4a4a3abd47f39..9419b0cfb24fa 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -1024,6 +1024,8 @@ impl ToOwned for CStr { #[stable(feature = "cstring_asref", since = "1.7.0")] impl From<&CStr> for CString { + /// Converts a &[CStr] into a [`CString`] + /// by copying the contents into a new allocation. fn from(s: &CStr) -> CString { s.to_owned() } diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index ab08b483367af..96d43e11dc6b1 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -135,6 +135,7 @@ #![feature(iter_next_chunk)] #![feature(iter_repeat_n)] #![feature(layout_for_ptr)] +#![feature(local_waker)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_uninit_array_transpose)] @@ -252,7 +253,7 @@ pub mod str; pub mod string; #[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))] pub mod sync; -#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync), target_has_atomic = "ptr"))] +#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))] pub mod task; #[cfg(test)] mod tests; diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 94e6924f41a75..49f5f53f9b30a 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -207,11 +207,7 @@ impl RawVec { // Allocators currently return a `NonNull<[u8]>` whose length // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / mem::size_of::()`. - Self { - ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: unsafe { Cap(capacity) }, - alloc, - } + Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc } } } @@ -239,6 +235,11 @@ impl RawVec { self.ptr.as_ptr() } + #[inline] + pub fn non_null(&self) -> NonNull { + NonNull::from(self.ptr) + } + /// Gets the capacity of the allocation. /// /// This will always be `usize::MAX` if `T` is zero-sized. @@ -398,7 +399,7 @@ impl RawVec { // Allocators currently return a `NonNull<[u8]>` whose length matches // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / mem::size_of::()`. - self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; + self.ptr = Unique::from(ptr.cast()); self.cap = unsafe { Cap(cap) }; } diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 4033f4eb068c6..f4e392760c8e4 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -51,7 +51,7 @@ pub use core::slice::{from_mut, from_ref}; pub use core::slice::{from_mut_ptr_range, from_ptr_range}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{from_raw_parts, from_raw_parts_mut}; -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] pub use core::slice::{ChunkBy, ChunkByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Chunks, Windows}; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index d0f98f9c7db41..e16574f3d8066 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -279,6 +279,12 @@ impl Arc { } impl Arc { + #[inline] + fn internal_into_inner_with_allocator(self) -> (NonNull>, A) { + let this = mem::ManuallyDrop::new(self); + (this.ptr, unsafe { ptr::read(&this.alloc) }) + } + #[inline] unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { Self { ptr, phantom: PhantomData, alloc } @@ -1275,12 +1281,9 @@ impl Arc, A> { #[unstable(feature = "new_uninit", issue = "63291")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] - pub unsafe fn assume_init(self) -> Arc - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Arc::from_inner_in(md_self.ptr.cast(), md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Arc { + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + unsafe { Arc::from_inner_in(ptr.cast(), alloc) } } } @@ -1320,12 +1323,9 @@ impl Arc<[mem::MaybeUninit], A> { #[unstable(feature = "new_uninit", issue = "63291")] #[must_use = "`self` will be dropped if the result is not used"] #[inline] - pub unsafe fn assume_init(self) -> Arc<[T], A> - where - A: Clone, - { - let md_self = mem::ManuallyDrop::new(self); - unsafe { Arc::from_ptr_in(md_self.ptr.as_ptr() as _, md_self.alloc.clone()) } + pub unsafe fn assume_init(self) -> Arc<[T], A> { + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -2413,7 +2413,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { } } -impl Arc { +impl Arc { /// Attempt to downcast the `Arc` to a concrete type. /// /// # Examples @@ -2440,10 +2440,8 @@ impl Arc { { if (*self).is::() { unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Ok(Arc::from_inner_in(ptr, alloc)) + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + Ok(Arc::from_inner_in(ptr.cast(), alloc)) } } else { Err(self) @@ -2483,10 +2481,8 @@ impl Arc { T: Any + Send + Sync, { unsafe { - let ptr = self.ptr.cast::>(); - let alloc = self.alloc.clone(); - mem::forget(self); - Arc::from_inner_in(ptr, alloc) + let (ptr, alloc) = self.internal_into_inner_with_allocator(); + Arc::from_inner_in(ptr.cast(), alloc) } } } @@ -3442,13 +3438,13 @@ impl From> for Arc<[u8]> { } #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Arc<[T; N], A> { +impl TryFrom> for Arc<[T; N], A> { type Error = Arc<[T], A>; fn try_from(boxed_slice: Arc<[T], A>) -> Result { if boxed_slice.len() == N { - let alloc = boxed_slice.alloc.clone(); - Ok(unsafe { Arc::from_raw_in(Arc::into_raw(boxed_slice) as *mut [T; N], alloc) }) + let (ptr, alloc) = boxed_slice.internal_into_inner_with_allocator(); + Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) } diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs index d37e45569cf0f..49eae718c1690 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/src/sync/tests.rs @@ -1,13 +1,15 @@ use super::*; use std::clone::Clone; +use std::mem::MaybeUninit; use std::option::Option::None; +use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::SeqCst; use std::sync::mpsc::channel; use std::sync::Mutex; use std::thread; -struct Canary(*mut atomic::AtomicUsize); +struct Canary(*mut AtomicUsize); impl Drop for Canary { fn drop(&mut self) { @@ -21,6 +23,37 @@ impl Drop for Canary { } } +struct AllocCanary<'a>(&'a AtomicUsize); + +impl<'a> AllocCanary<'a> { + fn new(counter: &'a AtomicUsize) -> Self { + counter.fetch_add(1, SeqCst); + Self(counter) + } +} + +unsafe impl Allocator for AllocCanary<'_> { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + std::alloc::Global.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + unsafe { std::alloc::Global.deallocate(ptr, layout) } + } +} + +impl Clone for AllocCanary<'_> { + fn clone(&self) -> Self { + Self::new(self.0) + } +} + +impl Drop for AllocCanary<'_> { + fn drop(&mut self) { + self.0.fetch_sub(1, SeqCst); + } +} + #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn manually_share_arc() { @@ -295,16 +328,16 @@ fn weak_self_cyclic() { #[test] fn drop_arc() { - let mut canary = atomic::AtomicUsize::new(0); - let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + let mut canary = AtomicUsize::new(0); + let x = Arc::new(Canary(&mut canary as *mut AtomicUsize)); drop(x); assert!(canary.load(Acquire) == 1); } #[test] fn drop_arc_weak() { - let mut canary = atomic::AtomicUsize::new(0); - let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + let mut canary = AtomicUsize::new(0); + let arc = Arc::new(Canary(&mut canary as *mut AtomicUsize)); let arc_weak = Arc::downgrade(&arc); assert!(canary.load(Acquire) == 0); drop(arc); @@ -660,3 +693,25 @@ fn arc_drop_dereferenceable_race() { thread.join().unwrap(); } } + +#[test] +fn arc_doesnt_leak_allocator() { + let counter = AtomicUsize::new(0); + + { + let arc: Arc = Arc::new_in(5usize, AllocCanary::new(&counter)); + drop(arc.downcast::().unwrap()); + + let arc: Arc = Arc::new_in(5usize, AllocCanary::new(&counter)); + drop(unsafe { arc.downcast_unchecked::() }); + + let arc = Arc::new_in(MaybeUninit::::new(5usize), AllocCanary::new(&counter)); + drop(unsafe { arc.assume_init() }); + + let arc: Arc<[MaybeUninit], _> = + Arc::new_zeroed_slice_in(5, AllocCanary::new(&counter)); + drop(unsafe { arc.assume_init() }); + } + + assert_eq!(counter.load(SeqCst), 0); +} diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 5d9772b878b03..87db8629ad09a 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -2,14 +2,19 @@ //! Types and Traits for working with asynchronous tasks. //! -//! **Note**: This module is only available on platforms that support atomic -//! loads and stores of pointers. This may be detected at compile time using +//! **Note**: Some of the types in this module are only available +//! on platforms that support atomic loads and stores of pointers. +//! This may be detected at compile time using //! `#[cfg(target_has_atomic = "ptr")]`. +use crate::rc::Rc; use core::mem::ManuallyDrop; -use core::task::{RawWaker, RawWakerVTable, Waker}; +use core::task::{LocalWaker, RawWaker, RawWakerVTable}; +#[cfg(target_has_atomic = "ptr")] use crate::sync::Arc; +#[cfg(target_has_atomic = "ptr")] +use core::task::Waker; /// The implementation of waking a task on an executor. /// @@ -73,6 +78,7 @@ use crate::sync::Arc; /// println!("Hi from inside a future!"); /// }); /// ``` +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "wake_trait", since = "1.51.0")] pub trait Wake { /// Wake this task. @@ -91,7 +97,7 @@ pub trait Wake { self.clone().wake(); } } - +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "wake_trait", since = "1.51.0")] impl From> for Waker { /// Use a `Wake`-able type as a `Waker`. @@ -103,7 +109,7 @@ impl From> for Waker { unsafe { Waker::from_raw(raw_waker(waker)) } } } - +#[cfg(target_has_atomic = "ptr")] #[stable(feature = "wake_trait", since = "1.51.0")] impl From> for RawWaker { /// Use a `Wake`-able type as a `RawWaker`. @@ -119,6 +125,7 @@ impl From> for RawWaker { // the safety of `From> for Waker` does not depend on the correct // trait dispatch - instead both impls call this function directly and // explicitly. +#[cfg(target_has_atomic = "ptr")] #[inline(always)] fn raw_waker(waker: Arc) -> RawWaker { // Increment the reference count of the arc to clone it. @@ -152,3 +159,171 @@ fn raw_waker(waker: Arc) -> RawWaker { &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), ) } + +/// An analogous trait to `Wake` but used to construct a `LocalWaker`. This API +/// works in exactly the same way as `Wake`, except that it uses an `Rc` instead +/// of an `Arc`, and the result is a `LocalWaker` instead of a `Waker`. +/// +/// The benefits of using `LocalWaker` over `Waker` are that it allows the local waker +/// to hold data that does not implement `Send` and `Sync`. Additionally, it saves calls +/// to `Arc::clone`, which requires atomic synchronization. +/// +/// +/// # Examples +/// +/// This is a simplified example of a `spawn` and a `block_on` function. The `spawn` function +/// is used to push new tasks onto the run queue, while the block on function will remove them +/// and poll them. When a task is woken, it will put itself back on the run queue to be polled +/// by the executor. +/// +/// **Note:** This example trades correctness for simplicity. A real world example would interleave +/// poll calls with calls to an io reactor to wait for events instead of spinning on a loop. +/// +/// ```rust +/// #![feature(local_waker)] +/// #![feature(noop_waker)] +/// use std::task::{LocalWake, ContextBuilder, LocalWaker, Waker}; +/// use std::future::Future; +/// use std::pin::Pin; +/// use std::rc::Rc; +/// use std::cell::RefCell; +/// use std::collections::VecDeque; +/// +/// +/// thread_local! { +/// // A queue containing all tasks ready to do progress +/// static RUN_QUEUE: RefCell>> = RefCell::default(); +/// } +/// +/// type BoxedFuture = Pin>>; +/// +/// struct Task(RefCell); +/// +/// impl LocalWake for Task { +/// fn wake(self: Rc) { +/// RUN_QUEUE.with_borrow_mut(|queue| { +/// queue.push_back(self) +/// }) +/// } +/// } +/// +/// fn spawn(future: F) +/// where +/// F: Future + 'static + Send + Sync +/// { +/// let task = RefCell::new(Box::pin(future)); +/// RUN_QUEUE.with_borrow_mut(|queue| { +/// queue.push_back(Rc::new(Task(task))); +/// }); +/// } +/// +/// fn block_on(future: F) +/// where +/// F: Future + 'static + Sync + Send +/// { +/// spawn(future); +/// loop { +/// let Some(task) = RUN_QUEUE.with_borrow_mut(|queue| queue.pop_front()) else { +/// // we exit, since there are no more tasks remaining on the queue +/// return; +/// }; +/// +/// // cast the Rc into a `LocalWaker` +/// let local_waker: LocalWaker = task.clone().into(); +/// // Build the context using `ContextBuilder` +/// let mut cx = ContextBuilder::from_waker(Waker::noop()) +/// .local_waker(&local_waker) +/// .build(); +/// +/// // Poll the task +/// let _ = task.0 +/// .borrow_mut() +/// .as_mut() +/// .poll(&mut cx); +/// } +/// } +/// +/// block_on(async { +/// println!("hello world"); +/// }); +/// ``` +/// +#[unstable(feature = "local_waker", issue = "118959")] +pub trait LocalWake { + /// Wake this task. + #[unstable(feature = "local_waker", issue = "118959")] + fn wake(self: Rc); + + /// Wake this task without consuming the local waker. + /// + /// If an executor supports a cheaper way to wake without consuming the + /// waker, it should override this method. By default, it clones the + /// [`Rc`] and calls [`wake`] on the clone. + /// + /// [`wake`]: LocalWaker::wake + #[unstable(feature = "local_waker", issue = "118959")] + fn wake_by_ref(self: &Rc) { + self.clone().wake(); + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl From> for LocalWaker { + /// Use a `Wake`-able type as a `LocalWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Rc) -> LocalWaker { + // SAFETY: This is safe because raw_waker safely constructs + // a RawWaker from Rc. + unsafe { LocalWaker::from_raw(local_raw_waker(waker)) } + } +} +#[allow(ineffective_unstable_trait_impl)] +#[unstable(feature = "local_waker", issue = "118959")] +impl From> for RawWaker { + /// Use a `Wake`-able type as a `RawWaker`. + /// + /// No heap allocations or atomic operations are used for this conversion. + fn from(waker: Rc) -> RawWaker { + local_raw_waker(waker) + } +} + +// NB: This private function for constructing a RawWaker is used, rather than +// inlining this into the `From> for RawWaker` impl, to ensure that +// the safety of `From> for Waker` does not depend on the correct +// trait dispatch - instead both impls call this function directly and +// explicitly. +#[inline(always)] +fn local_raw_waker(waker: Rc) -> RawWaker { + // Increment the reference count of the Rc to clone it. + unsafe fn clone_waker(waker: *const ()) -> RawWaker { + unsafe { Rc::increment_strong_count(waker as *const W) }; + RawWaker::new( + waker as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) + } + + // Wake by value, moving the Rc into the LocalWake::wake function + unsafe fn wake(waker: *const ()) { + let waker = unsafe { Rc::from_raw(waker as *const W) }; + ::wake(waker); + } + + // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it + unsafe fn wake_by_ref(waker: *const ()) { + let waker = unsafe { ManuallyDrop::new(Rc::from_raw(waker as *const W)) }; + ::wake_by_ref(&waker); + } + + // Decrement the reference count of the Rc on drop + unsafe fn drop_waker(waker: *const ()) { + unsafe { Rc::decrement_strong_count(waker as *const W) }; + } + + RawWaker::new( + Rc::into_raw(waker) as *const (), + &RawWakerVTable::new(clone_waker::, wake::, wake_by_ref::, drop_waker::), + ) +} diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index b12910f3690b5..3fe83242a30ad 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -15,7 +15,7 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { } } -#[stable(feature = "cow_from_array_ref", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "cow_from_array_ref", since = "1.77.0")] impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> { /// Creates a [`Borrowed`] variant of [`Cow`] /// from a reference to an array. diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 654ce09afcd30..7800560da94f9 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -136,7 +136,7 @@ impl IntoIter { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.buf = RawVec::NEW.non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a360c43094666..08e3cdedc666b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2784,6 +2784,50 @@ impl, A: Allocator> IndexMut for Vec { } } +/// Collects an iterator into a Vec, commonly called via [`Iterator::collect()`] +/// +/// # Allocation behavior +/// +/// In general `Vec` does not guarantee any particular growth or allocation strategy. +/// That also applies to this trait impl. +/// +/// **Note:** This section covers implementation details and is therefore exempt from +/// stability guarantees. +/// +/// Vec may use any or none of the following strategies, +/// depending on the supplied iterator: +/// +/// * preallocate based on [`Iterator::size_hint()`] +/// * and panic if the number of items is outside the provided lower/upper bounds +/// * use an amortized growth strategy similar to `pushing` one item at a time +/// * perform the iteration in-place on the original allocation backing the iterator +/// +/// The last case warrants some attention. It is an optimization that in many cases reduces peak memory +/// consumption and improves cache locality. But when big, short-lived allocations are created, +/// only a small fraction of their items get collected, no further use is made of the spare capacity +/// and the resulting `Vec` is moved into a longer-lived structure, then this can lead to the large +/// allocations having their lifetimes unnecessarily extended which can result in increased memory +/// footprint. +/// +/// In cases where this is an issue, the excess capacity can be discarded with [`Vec::shrink_to()`], +/// [`Vec::shrink_to_fit()`] or by collecting into [`Box<[T]>`][owned slice] instead, which additionally reduces +/// the size of the long-lived struct. +/// +/// [owned slice]: Box +/// +/// ```rust +/// # use std::sync::Mutex; +/// static LONG_LIVED: Mutex>> = Mutex::new(Vec::new()); +/// +/// for i in 0..10 { +/// let big_temporary: Vec = (0..1024).collect(); +/// // discard most items +/// let mut result: Vec<_> = big_temporary.into_iter().filter(|i| i % 100 == 0).collect(); +/// // without this a lot of unused capacity might be moved into the global +/// result.shrink_to_fit(); +/// LONG_LIVED.lock().unwrap().push(result); +/// } +/// ``` #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { @@ -2817,16 +2861,16 @@ impl IntoIterator for Vec { #[inline] fn into_iter(self) -> Self::IntoIter { unsafe { - let mut me = ManuallyDrop::new(self); + let me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); - let begin = me.as_mut_ptr(); + let buf = me.buf.non_null(); + let begin = buf.as_ptr(); let end = if T::IS_ZST { begin.wrapping_byte_add(me.len()) } else { begin.add(me.len()) as *const T }; let cap = me.buf.capacity(); - let buf = NonNull::new_unchecked(begin); IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end } } } diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index d749865f76f51..bdb6599abf549 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -2,36 +2,36 @@ use crate::cmp::BytewiseEq; use crate::convert::TryInto; #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[B; N]> for [A; N] +impl PartialEq<[U; N]> for [T; N] where - A: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[B; N]) -> bool { + fn eq(&self, other: &[U; N]) -> bool { SpecArrayEq::spec_eq(self, other) } #[inline] - fn ne(&self, other: &[B; N]) -> bool { + fn ne(&self, other: &[U; N]) -> bool { SpecArrayEq::spec_ne(self, other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[B]> for [A; N] +impl PartialEq<[U]> for [T; N] where - A: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[B]) -> bool { - let b: Result<&[B; N], _> = other.try_into(); + fn eq(&self, other: &[U]) -> bool { + let b: Result<&[U; N], _> = other.try_into(); match b { Ok(b) => *self == *b, Err(_) => false, } } #[inline] - fn ne(&self, other: &[B]) -> bool { - let b: Result<&[B; N], _> = other.try_into(); + fn ne(&self, other: &[U]) -> bool { + let b: Result<&[U; N], _> = other.try_into(); match b { Ok(b) => *self != *b, Err(_) => true, @@ -40,21 +40,21 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for [B] +impl PartialEq<[U; N]> for [T] where - B: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[A; N]) -> bool { - let b: Result<&[B; N], _> = self.try_into(); + fn eq(&self, other: &[U; N]) -> bool { + let b: Result<&[T; N], _> = self.try_into(); match b { Ok(b) => *b == *other, Err(_) => false, } } #[inline] - fn ne(&self, other: &[A; N]) -> bool { - let b: Result<&[B; N], _> = self.try_into(); + fn ne(&self, other: &[U; N]) -> bool { + let b: Result<&[T; N], _> = self.try_into(); match b { Ok(b) => *b != *other, Err(_) => true, @@ -63,61 +63,61 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&[B]> for [A; N] +impl PartialEq<&[U]> for [T; N] where - A: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &&[B]) -> bool { + fn eq(&self, other: &&[U]) -> bool { *self == **other } #[inline] - fn ne(&self, other: &&[B]) -> bool { + fn ne(&self, other: &&[U]) -> bool { *self != **other } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for &[B] +impl PartialEq<[U; N]> for &[T] where - B: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[A; N]) -> bool { + fn eq(&self, other: &[U; N]) -> bool { **self == *other } #[inline] - fn ne(&self, other: &[A; N]) -> bool { + fn ne(&self, other: &[U; N]) -> bool { **self != *other } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<&mut [B]> for [A; N] +impl PartialEq<&mut [U]> for [T; N] where - A: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &&mut [B]) -> bool { + fn eq(&self, other: &&mut [U]) -> bool { *self == **other } #[inline] - fn ne(&self, other: &&mut [B]) -> bool { + fn ne(&self, other: &&mut [U]) -> bool { *self != **other } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[A; N]> for &mut [B] +impl PartialEq<[U; N]> for &mut [T] where - B: PartialEq, + T: PartialEq, { #[inline] - fn eq(&self, other: &[A; N]) -> bool { + fn eq(&self, other: &[U; N]) -> bool { **self == *other } #[inline] - fn ne(&self, other: &[A; N]) -> bool { + fn ne(&self, other: &[U; N]) -> bool { **self != *other } } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 85cce81f2c122..743f07644e354 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -576,7 +576,7 @@ impl [T; N] { /// // We can still access the original array: it has not been moved. /// assert_eq!(strings.len(), 3); /// ``` - #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "array_methods", since = "1.77.0")] pub fn each_ref(&self) -> [&T; N] { from_trusted_iterator(self.iter()) } @@ -595,7 +595,7 @@ impl [T; N] { /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]); /// assert_eq!(floats, [0.0, 2.7, -1.0]); /// ``` - #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "array_methods", since = "1.77.0")] pub fn each_mut(&mut self) -> [&mut T; N] { from_trusted_iterator(self.iter_mut()) } diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs index db71a286b6dd0..489f95bbf101d 100644 --- a/library/core/src/async_iter/async_iter.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -47,7 +47,7 @@ pub trait AsyncIterator { /// Rust's usual rules apply: calls must never cause undefined behavior /// (memory corruption, incorrect use of `unsafe` functions, or the like), /// regardless of the async iterator's state. - #[cfg_attr(not(bootstrap), lang = "async_iterator_poll_next")] + #[lang = "async_iterator_poll_next"] fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>; /// Returns the bounds on the remaining length of the async iterator. @@ -145,7 +145,7 @@ pub trait IntoAsyncIterator { type IntoAsyncIter: AsyncIterator; /// Converts `self` into an async iterator - #[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")] + #[lang = "into_async_iter_into_iter"] fn into_async_iter(self) -> Self::IntoAsyncIter; } diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 177f39b59aed7..7bd592492a5c3 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char { unsafe { assert_unsafe_precondition!( "invalid value for `char`", - (i: u32) => char_try_from_u32(i).is_ok() + (i: u32 = i) => char_try_from_u32(i).is_ok() ); transmute(i) } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index dd0d59f6035a8..a2f07814726ac 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -61,11 +61,13 @@ use self::Ordering::*; /// The equality relation `==` must satisfy the following conditions /// (for all `a`, `b`, `c` of type `A`, `B`, `C`): /// -/// - **Symmetric**: if `A: PartialEq` and `B: PartialEq`, then **`a == b` +/// - **Symmetry**: if `A: PartialEq` and `B: PartialEq`, then **`a == b` /// implies `b == a`**; and /// -/// - **Transitive**: if `A: PartialEq` and `B: PartialEq` and `A: +/// - **Transitivity**: if `A: PartialEq` and `B: PartialEq` and `A: /// PartialEq`, then **`a == b` and `b == c` implies `a == c`**. +/// This must also work for longer chains, such as when `A: PartialEq`, `B: PartialEq`, +/// `C: PartialEq`, and `A: PartialEq` all exist. /// /// Note that the `B: PartialEq` (symmetric) and `A: PartialEq` /// (transitive) impls are not forced to exist, but these requirements apply @@ -76,6 +78,25 @@ use self::Ordering::*; /// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these /// methods. /// +/// ## Cross-crate considerations +/// +/// Upholding the requirements stated above can become tricky when one crate implements `PartialEq` +/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the +/// standard library). The recommendation is to never implement this trait for a foreign type. In +/// other words, such a crate should do `impl PartialEq for LocalType`, but it should +/// *not* do `impl PartialEq for ForeignType`. +/// +/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local +/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T == U`. In +/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 == ... +/// == T == V1 == ...`, then all the types that appear to the right of `T` must be types that the +/// crate defining `T` already knows about. This rules out transitive chains where downstream crates +/// can add new `impl`s that "stitch together" comparisons of foreign types in ways that violate +/// transitivity. +/// +/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding +/// more `PartialEq` implementations can cause build failures in downstream crates. +/// /// ## Derivable /// /// This trait can be used with `#[derive]`. When `derive`d on structs, two @@ -920,20 +941,43 @@ pub macro Ord($item:item) { /// easy to accidentally make them disagree by deriving some of the traits and manually /// implementing others. /// -/// The comparison must satisfy, for all `a`, `b` and `c`: +/// The comparison relations must satisfy the following conditions +/// (for all `a`, `b`, `c` of type `A`, `B`, `C`): /// -/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. -/// - duality: `a < b` if and only if `b > a`. +/// - **Transitivity**: if `A: PartialOrd` and `B: PartialOrd` and `A: +/// PartialOrd`, then `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`. +/// This must also work for longer chains, such as when `A: PartialOrd`, `B: PartialOrd`, +/// `C: PartialOrd`, and `A: PartialOrd` all exist. +/// - **Duality**: if `A: PartialOrd` and `B: PartialOrd`, then `a < b` if and only if `b > a`. /// -/// Note that these requirements mean that the trait itself must be implemented symmetrically and -/// transitively: if `T: PartialOrd` and `U: PartialOrd` then `U: PartialOrd` and `T: -/// PartialOrd`. +/// Note that the `B: PartialOrd` (dual) and `A: PartialOrd` +/// (transitive) impls are not forced to exist, but these requirements apply +/// whenever they do exist. /// /// Violating these requirements is a logic error. The behavior resulting from a logic error is not /// specified, but users of the trait must ensure that such logic errors do *not* result in /// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these /// methods. /// +/// ## Cross-crate considerations +/// +/// Upholding the requirements stated above can become tricky when one crate implements `PartialOrd` +/// for a type of another crate (i.e., to allow comparing one of its own types with a type from the +/// standard library). The recommendation is to never implement this trait for a foreign type. In +/// other words, such a crate should do `impl PartialOrd for LocalType`, but it should +/// *not* do `impl PartialOrd for ForeignType`. +/// +/// This avoids the problem of transitive chains that criss-cross crate boundaries: for all local +/// types `T`, you may assume that no other crate will add `impl`s that allow comparing `T < U`. In +/// other words, if other crates add `impl`s that allow building longer transitive chains `U1 < ... +/// < T < V1 < ...`, then all the types that appear to the right of `T` must be types that the crate +/// defining `T` already knows about. This rules out transitive chains where downstream crates can +/// add new `impl`s that "stitch together" comparisons of foreign types in ways that violate +/// transitivity. +/// +/// Not having such foreign `impl`s also avoids forward compatibility issues where one crate adding +/// more `PartialOrd` implementations can cause build failures in downstream crates. +/// /// ## Corollaries /// /// The following corollaries follow from the above requirements: diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 7340ad90da509..44200926a32eb 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -11,7 +11,6 @@ use crate::fmt; use crate::marker::PhantomData; -use crate::num::*; use crate::ops::{Deref, DerefMut}; #[stable(feature = "core_c_str", since = "1.64.0")] @@ -19,7 +18,7 @@ pub use self::c_str::{CStr, FromBytesUntilNulError, FromBytesWithNulError}; mod c_str; -macro_rules! type_alias_no_nz { +macro_rules! type_alias { { $Docfile:tt, $Alias:ident = $Real:ty; $( $Cfg:tt )* @@ -31,49 +30,24 @@ macro_rules! type_alias_no_nz { } } -// To verify that the NonZero types in this file's macro invocations correspond -// -// perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2' -// -// NB this does not check that the main c_* types are right. - -macro_rules! type_alias { - { - $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty; - $( $Cfg:tt )* - } => { - type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* } - - #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")] - #[unstable(feature = "raw_os_nonzero", issue = "82363")] - $( $Cfg )* - pub type $NZAlias = $NZReal; - } -} - -type_alias! { "c_char.md", c_char = c_char_definition::c_char, NonZero_c_char = c_char_definition::NonZero_c_char; -#[doc(cfg(all()))] } +type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] } -type_alias! { "c_schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; } -type_alias! { "c_uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; } -type_alias! { "c_short.md", c_short = i16, NonZero_c_short = NonZeroI16; } -type_alias! { "c_ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; } +type_alias! { "c_schar.md", c_schar = i8; } +type_alias! { "c_uchar.md", c_uchar = u8; } +type_alias! { "c_short.md", c_short = i16; } +type_alias! { "c_ushort.md", c_ushort = u16; } -type_alias! { "c_int.md", c_int = c_int_definition::c_int, NonZero_c_int = c_int_definition::NonZero_c_int; -#[doc(cfg(all()))] } -type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint, NonZero_c_uint = c_int_definition::NonZero_c_uint; -#[doc(cfg(all()))] } +type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] } +type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] } -type_alias! { "c_long.md", c_long = c_long_definition::c_long, NonZero_c_long = c_long_definition::NonZero_c_long; -#[doc(cfg(all()))] } -type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong, NonZero_c_ulong = c_long_definition::NonZero_c_ulong; -#[doc(cfg(all()))] } +type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] } +type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] } -type_alias! { "c_longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; } -type_alias! { "c_ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; } +type_alias! { "c_longlong.md", c_longlong = i64; } +type_alias! { "c_ulonglong.md", c_ulonglong = u64; } -type_alias_no_nz! { "c_float.md", c_float = f32; } -type_alias_no_nz! { "c_double.md", c_double = f64; } +type_alias! { "c_float.md", c_float = f32; } +type_alias! { "c_double.md", c_double = f64; } /// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++). /// @@ -152,11 +126,9 @@ mod c_char_definition { target_os = "horizon" ))] { pub type c_char = u8; - pub type NonZero_c_char = crate::num::NonZeroU8; } else { // On every other target, c_char is signed. pub type c_char = i8; - pub type NonZero_c_char = crate::num::NonZeroI8; } } } @@ -165,14 +137,10 @@ mod c_int_definition { cfg_if! { if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { pub type c_int = i16; - pub type NonZero_c_int = crate::num::NonZeroI16; pub type c_uint = u16; - pub type NonZero_c_uint = crate::num::NonZeroU16; } else { pub type c_int = i32; - pub type NonZero_c_int = crate::num::NonZeroI32; pub type c_uint = u32; - pub type NonZero_c_uint = crate::num::NonZeroU32; } } } @@ -181,15 +149,11 @@ mod c_long_definition { cfg_if! { if #[cfg(all(target_pointer_width = "64", not(windows)))] { pub type c_long = i64; - pub type NonZero_c_long = crate::num::NonZeroI64; pub type c_ulong = u64; - pub type NonZero_c_ulong = crate::num::NonZeroU64; } else { // The minimal size of `long` in the C standard is 32 bits pub type c_long = i32; - pub type NonZero_c_long = crate::num::NonZeroI32; pub type c_ulong = u32; - pub type NonZero_c_ulong = crate::num::NonZeroU32; } } } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 5c44ca69451dd..97c3c9e6fae95 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) { unsafe { intrinsics::assert_unsafe_precondition!( "hint::assert_unchecked must never be called when the condition is false", - (cond: bool) => cond, + (cond: bool = cond) => cond, ); crate::intrinsics::assume(cond); } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 43124535ab5d8..18c82f97c28e9 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -56,7 +56,7 @@ use crate::marker::DiscriminantKind; use crate::marker::Tuple; -use crate::mem; +use crate::mem::{self, align_of}; pub mod mir; pub mod simd; @@ -947,7 +947,7 @@ extern "rust-intrinsic" { /// own, or if it does not enable any significant optimizations. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_stable(feature = "const_assume", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_assume", since = "1.77.0")] #[rustc_nounwind] pub fn assume(b: bool); @@ -2567,16 +2567,18 @@ extern "rust-intrinsic" { /// matter what*. #[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")] #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn is_val_statically_known(arg: T) -> bool; + + #[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] + #[rustc_safe_intrinsic] + #[cfg(not(bootstrap))] + pub(crate) fn debug_assertions() -> bool; } -// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable` -// and thus compiling stage0 core doesn't work. -#[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")] #[cfg(bootstrap)] -pub const unsafe fn is_val_statically_known(_arg: T) -> bool { - false +#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] +pub(crate) const fn debug_assertions() -> bool { + cfg!(debug_assertions) } // Some functions are defined here because they accidentally got made @@ -2587,10 +2589,27 @@ pub const unsafe fn is_val_statically_known(_arg: T) -> bool { /// Check that the preconditions of an unsafe function are followed, if debug_assertions are on, /// and only at runtime. /// -/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)` -/// where the names specified will be moved into the macro as captured variables, and defines an item -/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics -/// for the function declarations and can be omitted if there is no generics. +/// This macro should be called as +/// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)` +/// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all +/// those arguments are passed to a function via [`const_eval_select`]. +/// +/// These checks are behind a condition which is evaluated at codegen time, not expansion time like +/// [`debug_assert`]. This means that a standard library built with optimizations and debug +/// assertions disabled will have these checks optimized out of its monomorphizations, but if a +/// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of +/// this macro, that monomorphization will contain the check. +/// +/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and +/// implementation to mitigate their compile-time overhead. The runtime function that we +/// [`const_eval_select`] to is monomorphic, `#[inline(never)]`, and `#[rustc_nounwind]`. That +/// combination of properties ensures that the code for the checks is only compiled once, and has a +/// minimal impact on the caller's code size. +/// +/// Caller should also introducing any other `let` bindings or any code outside this macro in order +/// to call it. Since the precompiled standard library is built with full debuginfo and these +/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough +/// debuginfo to have a measurable compile-time impact on debug builds. /// /// # Safety /// @@ -2604,26 +2623,24 @@ pub const unsafe fn is_val_statically_known(_arg: T) -> bool { /// /// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make /// the occasional mistake, and this check should help them figure things out. -#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn +#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn macro_rules! assert_unsafe_precondition { - ($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => { - if cfg!(debug_assertions) { - // allow non_snake_case to allow capturing const generics - #[allow(non_snake_case)] - #[inline(always)] - fn runtime$(<$($tt)*>)?($($i:$ty),*) { + ($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => { + { + #[inline(never)] + #[rustc_nounwind] + fn precondition_check($($name:$ty),*) { if !$e { - // don't unwind to reduce impact on code size ::core::panicking::panic_nounwind( - concat!("unsafe precondition(s) violated: ", $name) + concat!("unsafe precondition(s) violated: ", $message) ); } } - #[allow(non_snake_case)] - #[inline] - const fn comptime$(<$($tt)*>)?($(_:$ty),*) {} + const fn comptime($(_:$ty),*) {} - ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime); + if ::core::intrinsics::debug_assertions() { + ::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check); + } } }; } @@ -2632,30 +2649,47 @@ pub(crate) use assert_unsafe_precondition; /// Checks whether `ptr` is properly aligned with respect to /// `align_of::()`. #[inline] -pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { - !ptr.is_null() && ptr.is_aligned() +pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool { + !ptr.is_null() && ptr.is_aligned_to(align) } -/// Checks whether an allocation of `len` instances of `T` exceeds -/// the maximum allowed allocation size. #[inline] -pub(crate) fn is_valid_allocation_size(len: usize) -> bool { - let max_len = const { - let size = crate::mem::size_of::(); - if size == 0 { usize::MAX } else { isize::MAX as usize / size } - }; +pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool { + let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size }; len <= max_len } +pub(crate) fn is_nonoverlapping_mono( + src: *const (), + dst: *const (), + size: usize, + count: usize, +) -> bool { + let src_usize = src.addr(); + let dst_usize = dst.addr(); + let Some(size) = size.checked_mul(count) else { + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::() * count` overflows a usize", + ) + }; + let diff = src_usize.abs_diff(dst_usize); + // If the absolute distance between the ptrs is at least as big as the size of the buffer, + // they do not overlap. + diff >= size +} + /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size_of::()` do *not* overlap. #[inline] pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { let src_usize = src.addr(); let dst_usize = dst.addr(); - let size = mem::size_of::() - .checked_mul(count) - .expect("is_nonoverlapping: `size_of::() * count` overflows a usize"); + let Some(size) = mem::size_of::().checked_mul(count) else { + // Use panic_nounwind instead of Option::expect, so that this function is nounwind. + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::() * count` overflows a usize", + ) + }; let diff = src_usize.abs_diff(dst_usize); // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. @@ -2749,13 +2783,13 @@ pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) - #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[rustc_nounwind] pub fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize); } @@ -2766,10 +2800,16 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us assert_unsafe_precondition!( "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](src: *const T, dst: *mut T, count: usize) => - is_aligned_and_not_null(src) - && is_aligned_and_not_null(dst) - && is_nonoverlapping(src, dst, count) + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) + && is_nonoverlapping_mono(src, dst, size, count) ); copy_nonoverlapping(src, dst, count) } @@ -2845,13 +2885,13 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[rustc_nounwind] fn copy(src: *const T, dst: *mut T, count: usize); } @@ -2859,9 +2899,15 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { assert_unsafe_precondition!( - "ptr::copy requires that both pointer arguments are aligned and non-null", - [T](src: *const T, dst: *mut T) => - is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) + "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) ); copy(src, dst, count) } @@ -2934,7 +2980,10 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { unsafe { assert_unsafe_precondition!( "ptr::write_bytes requires that the destination pointer is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); write_bytes(dst, val, count) } diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index d348e31609d48..02665b2676cc1 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -105,7 +105,6 @@ //! } //! //! #[custom_mir(dialect = "runtime", phase = "optimized")] -#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set //! fn push_and_pop(v: &mut Vec, value: T) { //! mir!( //! let _unused; @@ -357,7 +356,6 @@ define!("mir_unwind_resume", define!("mir_storage_live", fn StorageLive(local: T)); define!("mir_storage_dead", fn StorageDead(local: T)); -#[cfg(not(bootstrap))] define!("mir_assume", fn Assume(operand: bool)); define!("mir_deinit", fn Deinit(place: T)); define!("mir_checked", fn Checked(binop: T) -> (T, bool)); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2af242d4b5071..b54680a61b4d8 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -111,7 +111,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] @@ -135,6 +134,7 @@ #![feature(const_hint_assert_unchecked)] #![feature(const_index_range_slice_index)] #![feature(const_int_unchecked_arith)] +#![feature(const_intrinsic_copy)] #![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] @@ -180,6 +180,7 @@ #![feature(maybe_uninit_uninit_array)] #![feature(non_null_convenience)] #![feature(offset_of_enum)] +#![feature(offset_of_nested)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] @@ -200,7 +201,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), feature(is_val_statically_known))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -429,10 +429,6 @@ pub mod primitive; deprecated_in_future )] #[allow(rustdoc::bare_urls)] -// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is -// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet. -#[allow(clashing_extern_declarations)] -#[unstable(feature = "stdsimd", issue = "48556")] mod core_arch; #[stable(feature = "simd_arch", since = "1.27.0")] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d6e0e1895cdff..2e22129d7b64d 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -225,77 +225,6 @@ marker_impls! { {T: ?Sized} &T, } -/// Required trait for constants used in pattern matches. -/// -/// Any type that derives `Eq` automatically implements this trait, *regardless* -/// of whether its type parameters implement `Eq`. -/// -/// This is a hack to work around a limitation in our type system. -/// -/// # Background -/// -/// We want to require that types of consts used in pattern matches -/// have the attribute `#[derive(PartialEq, Eq)]`. -/// -/// In a more ideal world, we could check that requirement by just checking that -/// the given type implements both the `StructuralPartialEq` trait *and* -/// the `Eq` trait. However, you can have ADTs that *do* `derive(PartialEq, Eq)`, -/// and be a case that we want the compiler to accept, and yet the constant's -/// type fails to implement `Eq`. -/// -/// Namely, a case like this: -/// -/// ```rust -/// #[derive(PartialEq, Eq)] -/// struct Wrap(X); -/// -/// fn higher_order(_: &()) { } -/// -/// const CFN: Wrap = Wrap(higher_order); -/// -/// #[allow(pointer_structural_match)] -/// fn main() { -/// match CFN { -/// CFN => {} -/// _ => {} -/// } -/// } -/// ``` -/// -/// (The problem in the above code is that `Wrap` does not implement -/// `PartialEq`, nor `Eq`, because `for<'a> fn(&'a _)` does not implement those -/// traits.) -/// -/// Therefore, we cannot rely on naive check for `StructuralPartialEq` and -/// mere `Eq`. -/// -/// As a hack to work around this, we use two separate traits injected by each -/// of the two derives (`#[derive(PartialEq)]` and `#[derive(Eq)]`) and check -/// that both of them are present as part of structural-match checking. -#[unstable(feature = "structural_match", issue = "31434")] -#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] -#[lang = "structural_teq"] -#[cfg(bootstrap)] -pub trait StructuralEq { - // Empty. -} - -// FIXME: Remove special cases of these types from the compiler pattern checking code and always check `T: StructuralEq` instead -marker_impls! { - #[unstable(feature = "structural_match", issue = "31434")] - #[cfg(bootstrap)] - StructuralEq for - usize, u8, u16, u32, u64, u128, - isize, i8, i16, i32, i64, i128, - bool, - char, - str /* Technically requires `[u8]: StructuralEq` */, - (), - {T, const N: usize} [T; N], - {T} [T], - {T: ?Sized} &T, -} - /// Types whose values can be duplicated simply by copying bits. /// /// By default, variable bindings have 'move semantics.' In other @@ -860,10 +789,6 @@ impl Default for PhantomData { #[unstable(feature = "structural_match", issue = "31434")] impl StructuralPartialEq for PhantomData {} -#[unstable(feature = "structural_match", issue = "31434")] -#[cfg(bootstrap)] -impl StructuralEq for PhantomData {} - /// Compiler-internal trait used to indicate the type of enum discriminants. /// /// This trait is automatically implemented for every type and does not add any @@ -1041,22 +966,8 @@ pub trait PointerLike {} #[unstable(feature = "adt_const_params", issue = "95174")] #[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] #[allow(multiple_supertrait_upcastable)] -#[cfg(not(bootstrap))] pub trait ConstParamTy: StructuralPartialEq + Eq {} -/// A marker for types which can be used as types of `const` generic parameters. -/// -/// These types must have a proper equivalence relation (`Eq`) and it must be automatically -/// derived (`StructuralPartialEq`). There's a hard-coded check in the compiler ensuring -/// that all fields are also `ConstParamTy`, which implies that recursively, all fields -/// are `StructuralPartialEq`. -#[lang = "const_param_ty"] -#[unstable(feature = "adt_const_params", issue = "95174")] -#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] -#[allow(multiple_supertrait_upcastable)] -#[cfg(bootstrap)] -pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {} - /// Derive macro generating an impl of the trait `ConstParamTy`. #[rustc_builtin_macro] #[unstable(feature = "adt_const_params", issue = "95174")] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 318a99e23ec64..e247b9ed83df5 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1393,19 +1393,9 @@ impl SizedTypeProperties for T {} /// /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` -#[cfg(not(bootstrap))] -#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "offset_of", since = "1.77.0")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { // The `{}` is for better error messages crate::hint::must_use({builtin # offset_of($Container, $($fields)+)}) } - -#[cfg(bootstrap)] -#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] -#[allow_internal_unstable(builtin_syntax, hint_must_use)] -#[allow(missing_docs)] -pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { - // The `{}` is for better error messages - crate::hint::must_use({builtin # offset_of($Container, $($fields).+)}) -} diff --git a/library/core/src/net/mod.rs b/library/core/src/net/mod.rs index 5bae4d2f0c4ca..0786165fe9e76 100644 --- a/library/core/src/net/mod.rs +++ b/library/core/src/net/mod.rs @@ -9,7 +9,7 @@ //! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`] //! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses -#![stable(feature = "ip_in_core", since = "CURRENT_RUSTC_VERSION")] +#![stable(feature = "ip_in_core", since = "1.77.0")] #[stable(feature = "rust1", since = "1.0.0")] pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index bb35b6128ea5a..d052dcc3e6ee6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1374,59 +1374,26 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return Some(1); - } - if self == -1 { // Avoid divide by zero - return Some(if exp & 1 != 0 { -1 } else { 1 }); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { return None; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - if !sign && res == Self::MIN { - None - } else if sign { - Some(res.wrapping_neg()) - } else { - Some(res) - } - } else { - if exp == 0 { - return Some(1); - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - exp /= 2; - base = try_opt!(base.checked_mul(base)); + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.checked_mul(base) + exp /= 2; + base = try_opt!(base.checked_mul(base)); } + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.checked_mul(base) } /// Strict exponentiation. Computes `self.pow(exp)`, panicking if @@ -2091,58 +2058,27 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - if self == -1 { // Avoid divide by zero - return if exp & 1 != 0 { -1 } else { 1 }; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { return 0; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - if sign { - res.wrapping_neg() - } else { - res - } - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.wrapping_mul(base) } /// Calculates `self` + `rhs` @@ -2625,68 +2561,36 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return (1, false); - } - if self == -1 { // Avoid divide by zero - return (if exp & 1 != 0 { -1 } else { 1 }, false); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - let overflow = res == Self::MIN; - if sign { - (res.wrapping_neg(), overflow) - } else { - (res, overflow) - } - } else { - if exp == 0 { - return (1,false); - } - let mut base = self; - let mut acc: Self = 1; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; + if exp == 0 { + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; overflown |= r.1; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; - r + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + r = acc.overflowing_mul(base); + r.1 |= overflown; + r } /// Raises self to the power of `exp`, using exponentiation by squaring. @@ -2704,68 +2608,28 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] #[rustc_inherit_overflow_checks] - #[track_caller] // Hides the hackish overflow check for powers of two. pub const fn pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.unsigned_abs().is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - if self == -1 { // Avoid divide by zero - return if exp & 1 != 0 { -1 } else { 1 }; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 }; - if exp > Self::BITS / power_used { // Division of constants is free - #[allow(arithmetic_overflow)] - return Self::MAX * Self::MAX * 0; - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc = 1; - // SAFETY: exp <= Self::BITS / power_used - let res = unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )}; - // LLVM doesn't always optimize out the checks - // at the ir level. - - let sign = self.is_negative() && exp & 1 != 0; - #[allow(arithmetic_overflow)] - if !sign && res == Self::MIN { - // So it panics. - _ = Self::MAX * Self::MAX; - } - if sign { - res.wrapping_neg() - } else { - res - } - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc * base; - } - exp /= 2; - base = base * base; + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base + exp /= 2; + base = base * base; } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base } /// Returns the square root of the number, rounded down. diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1124719fc8df1..288ad8e8d8784 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -3,15 +3,13 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash::{Hash, Hasher}; -#[cfg(bootstrap)] -use crate::marker::StructuralEq; +use crate::intrinsics; use crate::marker::StructuralPartialEq; use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem}; use crate::str::FromStr; use super::from_str_radix; use super::{IntErrorKind, ParseIntError}; -use crate::intrinsics; mod private { #[unstable( @@ -35,7 +33,7 @@ mod private { pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {} macro_rules! impl_zeroable_primitive { - ($NonZero:ident ( $primitive:ty )) => { + ($primitive:ty) => { #[unstable( feature = "nonzero_internals", reason = "implementation detail which may disappear or be replaced at any time", @@ -52,18 +50,18 @@ macro_rules! impl_zeroable_primitive { }; } -impl_zeroable_primitive!(NonZeroU8(u8)); -impl_zeroable_primitive!(NonZeroU16(u16)); -impl_zeroable_primitive!(NonZeroU32(u32)); -impl_zeroable_primitive!(NonZeroU64(u64)); -impl_zeroable_primitive!(NonZeroU128(u128)); -impl_zeroable_primitive!(NonZeroUsize(usize)); -impl_zeroable_primitive!(NonZeroI8(i8)); -impl_zeroable_primitive!(NonZeroI16(i16)); -impl_zeroable_primitive!(NonZeroI32(i32)); -impl_zeroable_primitive!(NonZeroI64(i64)); -impl_zeroable_primitive!(NonZeroI128(i128)); -impl_zeroable_primitive!(NonZeroIsize(isize)); +impl_zeroable_primitive!(u8); +impl_zeroable_primitive!(u16); +impl_zeroable_primitive!(u32); +impl_zeroable_primitive!(u64); +impl_zeroable_primitive!(u128); +impl_zeroable_primitive!(usize); +impl_zeroable_primitive!(i8); +impl_zeroable_primitive!(i16); +impl_zeroable_primitive!(i32); +impl_zeroable_primitive!(i64); +impl_zeroable_primitive!(i128); +impl_zeroable_primitive!(isize); /// A value that is known not to equal zero. /// @@ -83,6 +81,87 @@ impl_zeroable_primitive!(NonZeroIsize(isize)); #[rustc_diagnostic_item = "NonZero"] pub struct NonZero(T); +impl NonZero +where + T: ZeroablePrimitive, +{ + /// Creates a non-zero if the given value is not zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[must_use] + #[inline] + pub const fn new(n: T) -> Option { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + unsafe { intrinsics::transmute_unchecked(n) } + } + + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behaviour if the value is zero. + /// + /// # Safety + /// + /// The value must not be zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] + #[must_use] + #[inline] + pub const unsafe fn new_unchecked(n: T) -> Self { + match Self::new(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` is non-zero, so this is unreachable. + unsafe { + intrinsics::assert_unsafe_precondition!( + "NonZero::new_unchecked requires the argument to be non-zero", + () => false, + ); + intrinsics::unreachable() + } + } + } + } + + /// Converts a reference to a non-zero mutable reference + /// if the referenced value is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut T) -> Option<&mut Self> { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + let opt_n = unsafe { &mut *(n as *mut T as *mut Option) }; + + opt_n.as_mut() + } + + /// Converts a mutable reference to a non-zero mutable reference + /// without checking whether the referenced value is non-zero. + /// This results in undefined behavior if the referenced value is zero. + /// + /// # Safety + /// + /// The referenced value must not be zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub unsafe fn from_mut_unchecked(n: &mut T) -> &mut Self { + match Self::from_mut(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` references a value that is non-zero, so this is unreachable. + unsafe { + intrinsics::assert_unsafe_precondition!( + "NonZero::from_mut_unchecked requires the argument to dereference as non-zero", + () => false, + ); + intrinsics::unreachable() + } + } + } + } +} + macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( @@ -100,7 +179,6 @@ macro_rules! impl_nonzero_fmt { macro_rules! nonzero_integer { ( #[$stability:meta] - #[$const_new_unchecked_stability:meta] Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, $(UnsignedNonZero = $UnsignedNonZero:ident,)? @@ -143,74 +221,6 @@ macro_rules! nonzero_integer { pub type $Ty = NonZero<$Int>; impl $Ty { - /// Creates a non-zero without checking whether the value is non-zero. - /// This results in undefined behaviour if the value is zero. - /// - /// # Safety - /// - /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] - #[must_use] - #[inline] - pub const unsafe fn new_unchecked(n: $Int) -> Self { - crate::panic::debug_assert_nounwind!( - n != 0, - concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") - ); - // SAFETY: this is guaranteed to be safe by the caller. - unsafe { - Self(n) - } - } - - /// Creates a non-zero if the given value is not zero. - #[$stability] - #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] - #[must_use] - #[inline] - pub const fn new(n: $Int) -> Option { - if n != 0 { - // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) - } else { - None - } - } - - /// Converts a primitive mutable reference to a non-zero mutable reference - /// without checking whether the referenced value is non-zero. - /// This results in undefined behavior if `*n` is zero. - /// - /// # Safety - /// The referenced value must not be currently zero. - #[unstable(feature = "nonzero_from_mut", issue = "106290")] - #[must_use] - #[inline] - pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { - // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero. - unsafe { - let n_alias = &mut *n; - core::intrinsics::assert_unsafe_precondition!( - concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"), - (n_alias: &mut $Int) => *n_alias != 0 - ); - &mut *(n as *mut $Int as *mut Self) - } - } - - /// Converts a primitive mutable reference to a non-zero mutable reference - /// if the referenced integer is not zero. - #[unstable(feature = "nonzero_from_mut", issue = "106290")] - #[must_use] - #[inline] - pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { - // SAFETY: Self is repr(transparent), and the value is non-zero. - // As long as the returned reference is alive, - // the user cannot `*n = 0` directly. - (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) - } - /// Returns the value as a primitive type. #[$stability] #[inline] @@ -569,10 +579,6 @@ macro_rules! nonzero_integer { #[$stability] impl Eq for $Ty {} - #[unstable(feature = "structural_match", issue = "31434")] - #[cfg(bootstrap)] - impl StructuralEq for $Ty {} - #[$stability] impl PartialOrd for $Ty { #[inline] @@ -724,7 +730,6 @@ macro_rules! nonzero_integer { (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => { nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] - #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] Self = $Ty, Primitive = unsigned $Int, UnsignedPrimitive = $Int, @@ -735,7 +740,6 @@ macro_rules! nonzero_integer { (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => { nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] - #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] Self = $Ty, Primitive = signed $Int, $($rest)* @@ -757,7 +761,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { fn div(self, other: $Ty) -> $Int { // SAFETY: div by zero is checked because `other` is a nonzero, // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_div(self, other.get()) } + unsafe { intrinsics::unchecked_div(self, other.get()) } } } @@ -770,7 +774,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { fn rem(self, other: $Ty) -> $Int { // SAFETY: rem by zero is checked because `other` is a nonzero, // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } + unsafe { intrinsics::unchecked_rem(self, other.get()) } } } }; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d450c68a5b230..a217c2e259d2b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1364,49 +1364,28 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn checked_pow(self, mut exp: u32) -> Option { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return Some(1); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { return None; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - unsafe { Some(intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )) } - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0 { - return Some(1); - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = try_opt!(acc.checked_mul(base)); - } - exp /= 2; - base = try_opt!(base.checked_mul(base)); + if exp == 0 { + return Some(1); + } + let mut base = self; + let mut acc: Self = 1; + + while exp > 1 { + if (exp & 1) == 1 { + acc = try_opt!(acc.checked_mul(base)); } + exp /= 2; + base = try_opt!(base.checked_mul(base)); + } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. - acc.checked_mul(base) - } + acc.checked_mul(base) } /// Strict exponentiation. Computes `self.pow(exp)`, panicking if @@ -1908,48 +1887,27 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn wrapping_pow(self, mut exp: u32) -> Self { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { return 0; } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )} - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc: Self = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc.wrapping_mul(base); - } - exp /= 2; - base = base.wrapping_mul(base); - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc: Self = 1; - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc.wrapping_mul(base) + while exp > 1 { + if (exp & 1) == 1 { + acc = acc.wrapping_mul(base); + } + exp /= 2; + base = base.wrapping_mul(base); } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc.wrapping_mul(base) } /// Calculates `self` + `rhs` @@ -2383,58 +2341,37 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return (1, false); - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free - - // SAFETY: exp <= Self::BITS / power_used - unsafe { (intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - ), false) } - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0{ - return (1,false); - } - let mut base = self; - let mut acc: Self = 1; - let mut overflown = false; - // Scratch space for storing results of overflowing_mul. - let mut r; - - while exp > 1 { - if (exp & 1) == 1 { - r = acc.overflowing_mul(base); - acc = r.0; - overflown |= r.1; - } - exp /= 2; - r = base.overflowing_mul(base); - base = r.0; + if exp == 0{ + return (1,false); + } + let mut base = self; + let mut acc: Self = 1; + let mut overflown = false; + // Scratch space for storing results of overflowing_mul. + let mut r; + + while exp > 1 { + if (exp & 1) == 1 { + r = acc.overflowing_mul(base); + acc = r.0; overflown |= r.1; } + exp /= 2; + r = base.overflowing_mul(base); + base = r.0; + overflown |= r.1; + } - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - r = acc.overflowing_mul(base); - r.1 |= overflown; + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + r = acc.overflowing_mul(base); + r.1 |= overflown; - r - } + r } /// Raises self to the power of `exp`, using exponentiation by squaring. @@ -2450,64 +2387,28 @@ macro_rules! uint_impl { #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)] #[inline] #[rustc_inherit_overflow_checks] - #[track_caller] // Hides the hackish overflow check for powers of two. pub const fn pow(self, mut exp: u32) -> Self { - // LLVM now knows that `self` is a constant value, but not a - // constant in Rust. This allows us to compute the power used at - // compile-time. - // - // This will likely add a branch in debug builds, but this should - // be ok. - // - // This is a massive performance boost in release builds as you can - // get the power of a power of two and the exponent through a `shl` - // instruction, but we must add a couple more checks for parity with - // our own `pow`. - // SAFETY: This path has the same behavior as the other. - if unsafe { intrinsics::is_val_statically_known(self) } - && self.is_power_of_two() - { - if self == 1 { // Avoid divide by zero - return 1; - } - // SAFETY: We just checked this is a power of two. and above zero. - let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 }; - if exp > Self::BITS / power_used { // Division of constants is free - #[allow(arithmetic_overflow)] - return Self::MAX * Self::MAX * 0; - } + if exp == 0 { + return 1; + } + let mut base = self; + let mut acc = 1; - // SAFETY: exp <= Self::BITS / power_used - unsafe { intrinsics::unchecked_shl( - 1 as Self, - intrinsics::unchecked_mul(power_used, exp) as Self - )} - // LLVM doesn't always optimize out the checks - // at the ir level. - } else { - if exp == 0 { - return 1; - } - let mut base = self; - let mut acc = 1; - - while exp > 1 { - if (exp & 1) == 1 { - acc = acc * base; - } - exp /= 2; - base = base * base; + while exp > 1 { + if (exp & 1) == 1 { + acc = acc * base; } - - // since exp!=0, finally the exp must be 1. - // Deal with the final bit of the exponent separately, since - // squaring the base afterwards is not necessary and may cause a - // needless overflow. - acc * base + exp /= 2; + base = base * base; } + + // since exp!=0, finally the exp must be 1. + // Deal with the final bit of the exponent separately, since + // squaring the base afterwards is not necessary and may cause a + // needless overflow. + acc * base } /// Returns the square root of the number, rounded down. diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index bb3cdde66d173..fd50f80474833 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -73,6 +73,7 @@ append_const_msg )] #[doc(alias = "+")] +#[const_trait] pub trait Add { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -94,7 +95,8 @@ pub trait Add { macro_rules! add_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Add for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Add for $t { type Output = $t; #[inline] diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs index 965873f163eff..c5a8303a75cd6 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -8,7 +8,7 @@ use crate::marker::Tuple; #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), lang = "async_fn")] +#[lang = "async_fn"] pub trait AsyncFn: AsyncFnMut { /// Future returned by [`AsyncFn::async_call`]. #[unstable(feature = "async_fn_traits", issue = "none")] @@ -28,7 +28,7 @@ pub trait AsyncFn: AsyncFnMut { #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), lang = "async_fn_mut")] +#[lang = "async_fn_mut"] pub trait AsyncFnMut: AsyncFnOnce { /// Future returned by [`AsyncFnMut::async_call_mut`]. #[unstable(feature = "async_fn_traits", issue = "none")] @@ -48,7 +48,7 @@ pub trait AsyncFnMut: AsyncFnOnce { #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), lang = "async_fn_once")] +#[lang = "async_fn_once"] pub trait AsyncFnOnce { /// Future returned by [`AsyncFnOnce::async_call_once`]. #[unstable(feature = "async_fn_traits", issue = "none")] @@ -106,3 +106,28 @@ mod impls { } } } + +mod internal_implementation_detail { + /// A helper trait that is used to enforce that the `ClosureKind` of a goal + /// is within the capabilities of a `CoroutineClosure`, and which allows us + /// to delay the projection of the tupled upvar types until after upvar + /// analysis is complete. + /// + /// The `Self` type is expected to be the `kind_ty` of the coroutine-closure, + /// and thus either `?0` or `i8`/`i16`/`i32` (see docs for `ClosureKind` + /// for an explanation of that). The `GoalKind` is also the same type, but + /// representing the kind of the trait that the closure is being called with. + #[cfg_attr(not(bootstrap), lang = "async_fn_kind_helper")] + trait AsyncFnKindHelper { + // Projects a set of closure inputs (arguments), a region, and a set of upvars + // (by move and by ref) to the upvars that we expect the coroutine to have + // according to the `GoalKind` parameter above. + // + // The `Upvars` parameter should be the upvars of the parent coroutine-closure, + // and the `BorrowedUpvarsAsFnPtr` will be a function pointer that has the shape + // `for<'env> fn() -> (&'env T, ...)`. This allows us to represent the binder + // of the closure's self-capture, and these upvar types will be instantiated with + // the `'closure_env` region provided to the associated type. + type Upvars<'closure_env, Inputs, Upvars, BorrowedUpvarsAsFnPtr>; + } +} diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index 6faded76a4a49..6e067f95da92d 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -111,7 +111,7 @@ pub trait Coroutine { /// been returned previously. While coroutine literals in the language are /// guaranteed to panic on resuming after `Complete`, this is not guaranteed /// for all implementations of the `Coroutine` trait. - #[cfg_attr(not(bootstrap), lang = "coroutine_resume")] + #[lang = "coroutine_resume"] fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState; } diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index e809273c9ed93..727a22e454d3d 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -726,7 +726,7 @@ impl Bound { /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); /// ``` #[inline] - #[stable(feature = "bound_map", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "bound_map", since = "1.77.0")] pub fn map U>(self, f: F) -> Bound { match self { Unbounded => Unbounded, diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c94e7d73a2ae6..d4c40c49934ed 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1033,7 +1033,6 @@ impl Option { #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const unsafe fn unwrap_unchecked(self) -> T { - debug_assert!(self.is_some()); match self { Some(val) => val, // SAFETY: the safety contract must be upheld by the caller. @@ -1074,18 +1073,23 @@ impl Option { } } - /// Calls the provided closure with a reference to the contained value (if [`Some`]). + /// Calls a function with a reference to the contained value if [`Some`]. + /// + /// Returns the original option. /// /// # Examples /// /// ``` - /// let v = vec![1, 2, 3, 4, 5]; + /// let list = vec![1, 2, 3]; /// - /// // prints "got: 4" - /// let x: Option<&usize> = v.get(3).inspect(|x| println!("got: {x}")); + /// // prints "got: 2" + /// let x = list + /// .get(1) + /// .inspect(|x| println!("got: {x}")) + /// .expect("list should be long enough"); /// /// // prints nothing - /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {x}")); + /// list.get(5).inspect(|x| println!("got: {x}")); /// ``` #[inline] #[stable(feature = "result_option_inspect", since = "1.76.0")] @@ -2155,7 +2159,6 @@ impl PartialEq for Option { /// /// Once that's fixed, `Option` should go back to deriving `PartialEq`, as /// it used to do before . -/// The comment regarding this trait on the `newtype_index` macro should be removed if this is done. #[unstable(feature = "spec_option_partial_eq", issue = "none", reason = "exposed only for rustc")] #[doc(hidden)] pub trait SpecOptionPartialEq: Sized { diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bf47d767a9277..85595b059ad9a 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -448,22 +448,6 @@ mod prim_unit {} #[doc(hidden)] impl () {} -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for () { - fn clone(&self) -> Self { - loop {} - } -} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Copy for () { - // empty -} - #[rustc_doc_primitive = "pointer"] #[doc(alias = "ptr")] #[doc(alias = "*")] @@ -1690,23 +1674,3 @@ mod prim_fn {} // See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] impl fn(T) -> Ret {} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(fake_variadic)] -/// This trait is implemented on function pointers with any number of arguments. -impl Clone for fn(T) -> Ret { - fn clone(&self) -> Self { - loop {} - } -} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(fake_variadic)] -/// This trait is implemented on function pointers with any number of arguments. -impl Copy for fn(T) -> Ret { - // empty -} diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index f3ceadee24c2f..c5e3df07a1cf7 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -806,13 +806,15 @@ impl *const T { where T: Sized, { - let this = self; // SAFETY: The comparison has no side-effects, and the intrinsic // does this check internally in the CTFE implementation. unsafe { assert_unsafe_precondition!( - "ptr::sub_ptr requires `this >= origin`", - [T](this: *const T, origin: *const T) => this >= origin + "ptr::sub_ptr requires `self >= origin`", + ( + this: *const () = self as *const (), + origin: *const () = origin as *const (), + ) => this >= origin ) }; @@ -1284,7 +1286,7 @@ impl *const T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1304,7 +1306,7 @@ impl *const T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index dce7e035fc73a..0fb9017e6d941 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -381,11 +381,11 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash; use crate::intrinsics::{ - self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping, + self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping_mono, }; use crate::marker::FnPtr; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, align_of, size_of, MaybeUninit}; mod alignment; #[unstable(feature = "ptr_alignment_type", issue = "102070")] @@ -967,10 +967,16 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { assert_unsafe_precondition!( "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](x: *mut T, y: *mut T, count: usize) => - is_aligned_and_not_null(x) - && is_aligned_and_not_null(y) - && is_nonoverlapping(x, y, count) + ( + x: *mut () = x as *mut (), + y: *mut () = y as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + count: usize = count, + ) => + is_aligned_and_not_null(x, align) + && is_aligned_and_not_null(y, align) + && is_nonoverlapping_mono(x, y, size, count) ); } @@ -1061,7 +1067,10 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { unsafe { assert_unsafe_precondition!( "ptr::replace requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); mem::swap(&mut *dst, &mut src); // cannot overlap } @@ -1176,7 +1185,6 @@ pub const unsafe fn replace(dst: *mut T, mut src: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read"] pub const unsafe fn read(src: *const T) -> T { @@ -1208,9 +1216,13 @@ pub const unsafe fn read(src: *const T) -> T { // SAFETY: the caller must guarantee that `src` is valid for reads. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::read requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); crate::intrinsics::read_via_copy(src) } @@ -1294,7 +1306,11 @@ pub const unsafe fn read(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] +#[rustc_allow_const_fn_unstable( + const_mut_refs, + const_maybe_uninit_as_mut_ptr, + const_intrinsic_copy +)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read_unaligned"] pub const unsafe fn read_unaligned(src: *const T) -> T { @@ -1408,9 +1424,13 @@ pub const unsafe fn write(dst: *mut T, src: T) { // `dst` cannot overlap `src` because the caller has mutable access // to `dst` while `src` is owned by this function. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::write requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::write_via_move(dst, src) } @@ -1578,7 +1598,10 @@ pub unsafe fn read_volatile(src: *const T) -> T { unsafe { assert_unsafe_precondition!( "ptr::read_volatile requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_load(src) } @@ -1653,7 +1676,10 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { unsafe { assert_unsafe_precondition!( "ptr::write_volatile requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 3e47c4f440a44..376673d67c10b 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1385,7 +1385,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1405,7 +1405,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1425,7 +1425,7 @@ impl *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1445,7 +1445,7 @@ impl *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d18082c3048f1..320cd5eb3b2ae 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -218,7 +218,10 @@ impl NonNull { pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. unsafe { - assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null()); + assert_unsafe_precondition!( + "NonNull::new_unchecked requires that the pointer is non-null", + (ptr: *mut () = ptr as *mut ()) => !ptr.is_null() + ); NonNull { pointer: ptr as _ } } } @@ -470,7 +473,7 @@ impl NonNull { #[inline] pub const fn cast(self) -> NonNull { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null - unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } + unsafe { NonNull { pointer: self.as_ptr() as *mut U } } } /// Calculates the offset from a pointer. @@ -1588,8 +1591,7 @@ impl NonNull<[T]> { #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_non_null_ptr(self) -> NonNull { - // SAFETY: We know `self` is non-null. - unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) } + self.cast() } /// Returns a raw pointer to the slice's buffer. @@ -1825,9 +1827,7 @@ impl hash::Hash for NonNull { impl From> for NonNull { #[inline] fn from(unique: Unique) -> Self { - // SAFETY: A Unique pointer cannot be null, so the conditions for - // new_unchecked() are respected. - unsafe { NonNull::new_unchecked(unique.as_ptr()) } + unique.as_non_null_ptr() } } @@ -1850,8 +1850,7 @@ impl From<&T> for NonNull { /// This conversion is safe and infallible since references cannot be null. #[inline] fn from(reference: &T) -> Self { - // SAFETY: A reference cannot be null, so the conditions for - // new_unchecked() are respected. + // SAFETY: A reference cannot be null. unsafe { NonNull { pointer: reference as *const T } } } } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 067f1541e31ae..b74d691e45427 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -106,6 +106,13 @@ impl Unique { self.pointer.as_ptr() } + /// Acquires the underlying `*mut` pointer. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub const fn as_non_null_ptr(self) -> NonNull { + self.pointer + } + /// Dereferences the content. /// /// The resulting lifetime is bound to self so this behaves "as if" @@ -138,7 +145,7 @@ impl Unique { pub const fn cast(self) -> Unique { // FIXME(const-hack): replace with `From` // SAFETY: is `NonNull` - unsafe { Unique::new_unchecked(self.pointer.cast().as_ptr()) } + Unique { pointer: self.pointer.cast(), _marker: PhantomData } } } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 1f448984e531c..80f7fe75e8230 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -830,7 +830,9 @@ impl Result { } } - /// Calls the provided closure with a reference to the contained value (if [`Ok`]). + /// Calls a function with a reference to the contained value if [`Ok`]. + /// + /// Returns the original result. /// /// # Examples /// @@ -851,7 +853,9 @@ impl Result { self } - /// Calls the provided closure with a reference to the contained error (if [`Err`]). + /// Calls a function with a reference to the contained value if [`Err`]. + /// + /// Returns the original result. /// /// # Examples /// diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 8a8d634c0072a..e8b0010ba1574 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -8,15 +8,15 @@ use super::from_raw_parts; use super::memchr; #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq<[B]> for [A] +impl PartialEq<[U]> for [T] where - A: PartialEq, + T: PartialEq, { - fn eq(&self, other: &[B]) -> bool { + fn eq(&self, other: &[U]) -> bool { SlicePartialEq::equal(self, other) } - fn ne(&self, other: &[B]) -> bool { + fn ne(&self, other: &[U]) -> bool { SlicePartialEq::not_equal(self, other) } } diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 2d4c7e78aea17..1429313c89064 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -87,12 +87,13 @@ unsafe impl Send for Iter<'_, T> {} impl<'a, T> Iter<'a, T> { #[inline] pub(super) fn new(slice: &'a [T]) -> Self { - let ptr = slice.as_ptr(); + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); // SAFETY: Similar to `IterMut::new`. unsafe { - let end_or_len = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr as *mut T), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } @@ -208,7 +209,8 @@ unsafe impl Send for IterMut<'_, T> {} impl<'a, T> IterMut<'a, T> { #[inline] pub(super) fn new(slice: &'a mut [T]) -> Self { - let ptr = slice.as_mut_ptr(); + let len = slice.len(); + let ptr: NonNull = NonNull::from(slice).cast(); // SAFETY: There are several things here: // // `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid @@ -226,10 +228,9 @@ impl<'a, T> IterMut<'a, T> { // See the `next_unchecked!` and `is_empty!` macros as well as the // `post_inc_start` method for more information. unsafe { - let end_or_len = - if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid_mut(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } @@ -3252,21 +3253,21 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> { /// /// [`chunk_by`]: slice::chunk_by /// [slices]: slice -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunkBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> ChunkBy<'a, T, P> { pub(super) fn new(slice: &'a [T], predicate: P) -> Self { ChunkBy { slice, predicate } } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> Iterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3300,7 +3301,7 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> DoubleEndedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3322,10 +3323,10 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> FusedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkBy<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ChunkBy").field("slice", &self.slice).finish() @@ -3339,21 +3340,21 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkBy<'a, T, P> { /// /// [`chunk_by_mut`]: slice::chunk_by_mut /// [slices]: slice -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunkByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> ChunkByMut<'a, T, P> { pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { ChunkByMut { slice, predicate } } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> Iterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3388,7 +3389,7 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> DoubleEndedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3411,10 +3412,10 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> FusedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkByMut<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ChunkByMut").field("slice", &self.slice).finish() diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 2d93ef6fbeb34..73e92ed1dad63 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -68,7 +68,7 @@ pub use iter::{ArrayChunks, ArrayChunksMut}; #[unstable(feature = "array_windows", issue = "75027")] pub use iter::ArrayWindows; -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] pub use iter::{ChunkBy, ChunkByMut}; #[stable(feature = "split_inclusive", since = "1.51.0")] @@ -334,8 +334,8 @@ impl [T] { /// assert_eq!(Some(&[]), w.first_chunk::<0>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn first_chunk(&self) -> Option<&[T; N]> { if self.len() < N { None @@ -364,7 +364,7 @@ impl [T] { /// assert_eq!(None, x.first_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn first_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -394,8 +394,8 @@ impl [T] { /// assert_eq!(None, x.split_first_chunk::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_first_chunk(&self) -> Option<(&[T; N], &[T])> { if self.len() < N { None @@ -429,7 +429,7 @@ impl [T] { /// assert_eq!(None, x.split_first_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_first_chunk_mut( &mut self, @@ -464,8 +464,8 @@ impl [T] { /// assert_eq!(None, x.split_last_chunk::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_last_chunk(&self) -> Option<(&[T], &[T; N])> { if self.len() < N { None @@ -499,7 +499,7 @@ impl [T] { /// assert_eq!(None, x.split_last_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_last_chunk_mut( &mut self, @@ -534,7 +534,7 @@ impl [T] { /// assert_eq!(Some(&[]), w.last_chunk::<0>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk(&self) -> Option<&[T; N]> { if self.len() < N { @@ -568,7 +568,7 @@ impl [T] { /// assert_eq!(None, x.last_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk_mut(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -1777,7 +1777,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&[2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_group_by", since = "1.77.0")] #[inline] pub fn chunk_by(&self, pred: F) -> ChunkBy<'_, T, F> where @@ -1818,7 +1818,7 @@ impl [T] { /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_group_by", since = "1.77.0")] #[inline] pub fn chunk_by_mut(&mut self, pred: F) -> ChunkByMut<'_, T, F> where @@ -1951,10 +1951,7 @@ impl [T] { /// } /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] - #[rustc_const_stable( - feature = "const_slice_split_at_unchecked", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_slice_split_at_unchecked", since = "1.77.0")] #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { @@ -2989,7 +2986,7 @@ impl [T] { sort::quicksort(self, |a, b| f(a).lt(&f(b))); } - /// Reorder the slice such that the element at `index` is at its final sorted position. + /// Reorder the slice such that the element at `index` after the reordering is at its final sorted position. /// /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index`. Additionally, this reordering is @@ -3017,7 +3014,7 @@ impl [T] { /// # Examples /// /// ``` - /// let mut v = [-5i32, 4, 1, -3, 2]; + /// let mut v = [-5i32, 4, 2, -3, 1]; /// /// // Find the median /// v.select_nth_unstable(2); @@ -3038,8 +3035,8 @@ impl [T] { select::partition_at_index(self, index, T::lt) } - /// Reorder the slice with a comparator function such that the element at `index` is at its - /// final sorted position. + /// Reorder the slice with a comparator function such that the element at `index` after the reordering is at + /// its final sorted position. /// /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the comparator function. @@ -3068,7 +3065,7 @@ impl [T] { /// # Examples /// /// ``` - /// let mut v = [-5i32, 4, 1, -3, 2]; + /// let mut v = [-5i32, 4, 2, -3, 1]; /// /// // Find the median as if the slice were sorted in descending order. /// v.select_nth_unstable_by(2, |a, b| b.cmp(a)); @@ -3093,8 +3090,8 @@ impl [T] { select::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less) } - /// Reorder the slice with a key extraction function such that the element at `index` is at its - /// final sorted position. + /// Reorder the slice with a key extraction function such that the element at `index` after the reordering is + /// at its final sorted position. /// /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the key extraction function. diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 9cdf9b68afb72..571abc3e99907 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -4,6 +4,7 @@ use crate::array; use crate::intrinsics::{ assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size, }; +use crate::mem::{align_of, size_of}; use crate::ops::Range; use crate::ptr; @@ -96,8 +97,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] unsafe { assert_unsafe_precondition!( "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *const T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -143,8 +150,14 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m unsafe { assert_unsafe_precondition!( "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *mut T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::(), + align: usize = align_of::(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) } diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 3f0080e3832e1..f1a789e32a7a7 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -8,7 +8,7 @@ pub use self::poll::Poll; mod wake; #[stable(feature = "futures_api", since = "1.36.0")] -pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; +pub use self::wake::{Context, ContextBuilder, LocalWaker, RawWaker, RawWakerVTable, Waker}; mod ready; #[stable(feature = "ready_macro", since = "1.64.0")] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 077852b0120c4..9ad71e394eacf 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -1,11 +1,13 @@ #![stable(feature = "futures_api", since = "1.36.0")] +use crate::mem::transmute; + use crate::fmt; use crate::marker::PhantomData; use crate::ptr; /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`] -/// which provides customized wakeup behavior. +/// or a [`LocalWaker`] which provides customized wakeup behavior. /// /// [vtable]: https://en.wikipedia.org/wiki/Virtual_method_table /// @@ -33,9 +35,18 @@ impl RawWaker { /// The value of this pointer will get passed to all functions that are part /// of the `vtable` as the first parameter. /// + /// It is important to consider that the `data` pointer must point to a + /// thread safe type such as an `[Arc]` + /// when used to construct a [`Waker`]. This restriction is lifted when + /// constructing a [`LocalWaker`], which allows using types that do not implement + /// [Send] + [Sync] like `[Rc]`. + /// /// The `vtable` customizes the behavior of a `Waker` which gets created /// from a `RawWaker`. For each operation on the `Waker`, the associated /// function in the `vtable` of the underlying `RawWaker` will be called. + /// + /// [`Arc`]: std::sync::Arc + /// [`Rc`]: std::rc::Rc #[inline] #[rustc_promotable] #[stable(feature = "futures_api", since = "1.36.0")] @@ -60,6 +71,21 @@ impl RawWaker { pub fn vtable(&self) -> &'static RawWakerVTable { self.vtable } + + #[unstable(feature = "noop_waker", issue = "98286")] + const NOOP: RawWaker = { + const VTABLE: RawWakerVTable = RawWakerVTable::new( + // Cloning just returns a new no-op raw waker + |_| RawWaker::NOOP, + // `wake` does nothing + |_| {}, + // `wake_by_ref` does nothing + |_| {}, + // Dropping does nothing as we don't allocate anything + |_| {}, + ); + RawWaker::new(ptr::null(), &VTABLE) + }; } /// A virtual function pointer table (vtable) that specifies the behavior @@ -73,11 +99,19 @@ impl RawWaker { /// [`RawWaker`] implementation. Calling one of the contained functions using /// any other `data` pointer will cause undefined behavior. /// -/// These functions must all be thread-safe (even though [`RawWaker`] is -/// \![Send] + \![Sync]) -/// because [`Waker`] is [Send] + [Sync], and thus wakers may be moved to -/// arbitrary threads or invoked by `&` reference. For example, this means that if the -/// `clone` and `drop` functions manage a reference count, they must do so atomically. +/// # Thread safety +/// If the [`RawWaker`] will be used to construct a [`Waker`] then +/// these functions must all be thread-safe (even though [`RawWaker`] is +/// \![Send] + \![Sync]). This is because [`Waker`] is [Send] + [Sync], +/// and it may be moved to arbitrary threads or invoked by `&` reference. For example, +/// this means that if the `clone` and `drop` functions manage a reference count, +/// they must do so atomically. +/// +/// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then +/// these functions don't need to be thread safe. This means that \![Send] + \![Sync] +/// data can be stored in the data pointer, and reference counting does not need any atomic +/// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot +/// be sent across threads. #[stable(feature = "futures_api", since = "1.36.0")] #[derive(PartialEq, Copy, Clone, Debug)] pub struct RawWakerVTable { @@ -117,16 +151,22 @@ impl RawWakerVTable { /// Creates a new `RawWakerVTable` from the provided `clone`, `wake`, /// `wake_by_ref`, and `drop` functions. /// - /// These functions must all be thread-safe (even though [`RawWaker`] is - /// \![Send] + \![Sync]) - /// because [`Waker`] is [Send] + [Sync], and thus wakers may be moved to - /// arbitrary threads or invoked by `&` reference. For example, this means that if the - /// `clone` and `drop` functions manage a reference count, they must do so atomically. - /// + /// If the [`RawWaker`] will be used to construct a [`Waker`] then + /// these functions must all be thread-safe (even though [`RawWaker`] is + /// \![Send] + \![Sync]). This is because [`Waker`] is [Send] + [Sync], + /// and it may be moved to arbitrary threads or invoked by `&` reference. For example, + /// this means that if the `clone` and `drop` functions manage a reference count, + /// they must do so atomically. + /// + /// However, if the [`RawWaker`] will be used to construct a [`LocalWaker`] instead, then + /// these functions don't need to be thread safe. This means that \![Send] + \![Sync] + /// data can be stored in the data pointer, and reference counting does not need any atomic + /// synchronization. This is because [`LocalWaker`] is not thread safe itself, so it cannot + /// be sent across threads. /// # `clone` /// /// This function will be called when the [`RawWaker`] gets cloned, e.g. when - /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. + /// the [`Waker`]/[`LocalWaker`] in which the [`RawWaker`] is stored gets cloned. /// /// The implementation of this function must retain all resources that are /// required for this additional instance of a [`RawWaker`] and associated @@ -152,7 +192,7 @@ impl RawWakerVTable { /// /// # `drop` /// - /// This function gets called when a [`Waker`] gets dropped. + /// This function gets called when a [`Waker`]/[`LocalWaker`] gets dropped. /// /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and @@ -178,6 +218,7 @@ impl RawWakerVTable { #[lang = "Context"] pub struct Context<'a> { waker: &'a Waker, + local_waker: &'a LocalWaker, // Ensure we future-proof against variance changes by forcing // the lifetime to be invariant (argument-position lifetimes // are contravariant while return-position lifetimes are @@ -195,17 +236,24 @@ impl<'a> Context<'a> { #[must_use] #[inline] pub const fn from_waker(waker: &'a Waker) -> Self { - Context { waker, _marker: PhantomData, _marker2: PhantomData } + ContextBuilder::from_waker(waker).build() } /// Returns a reference to the [`Waker`] for the current task. + #[inline] + #[must_use] #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_unstable(feature = "const_waker", issue = "102012")] - #[must_use] - #[inline] pub const fn waker(&self) -> &'a Waker { &self.waker } + /// Returns a reference to the [`LocalWaker`] for the current task. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const fn local_waker(&self) -> &'a LocalWaker { + &self.local_waker + } } #[stable(feature = "futures_api", since = "1.36.0")] @@ -215,6 +263,72 @@ impl fmt::Debug for Context<'_> { } } +/// A Builder used to construct a `Context` instance +/// with support for `LocalWaker`. +/// +/// # Examples +/// ``` +/// #![feature(local_waker)] +/// #![feature(noop_waker)] +/// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; +/// use std::future::Future; +/// +/// let local_waker = LocalWaker::noop(); +/// let waker = Waker::noop(); +/// +/// let mut cx = ContextBuilder::from_waker(&waker) +/// .local_waker(&local_waker) +/// .build(); +/// +/// let mut future = std::pin::pin!(async { 20 }); +/// let poll = future.as_mut().poll(&mut cx); +/// assert_eq!(poll, Poll::Ready(20)); +/// +/// ``` +#[unstable(feature = "local_waker", issue = "118959")] +#[derive(Debug)] +pub struct ContextBuilder<'a> { + waker: &'a Waker, + local_waker: &'a LocalWaker, + // Ensure we future-proof against variance changes by forcing + // the lifetime to be invariant (argument-position lifetimes + // are contravariant while return-position lifetimes are + // covariant). + _marker: PhantomData &'a ()>, + // Ensure `Context` is `!Send` and `!Sync` in order to allow + // for future `!Send` and / or `!Sync` fields. + _marker2: PhantomData<*mut ()>, +} + +impl<'a> ContextBuilder<'a> { + /// Create a ContextBuilder from a Waker. + #[inline] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + #[unstable(feature = "local_waker", issue = "118959")] + pub const fn from_waker(waker: &'a Waker) -> Self { + // SAFETY: LocalWaker is just Waker without thread safety + let local_waker = unsafe { transmute(waker) }; + Self { waker: waker, local_waker, _marker: PhantomData, _marker2: PhantomData } + } + + /// This method is used to set the value for the local waker on `Context`. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const fn local_waker(self, local_waker: &'a LocalWaker) -> Self { + Self { local_waker, ..self } + } + + /// Builds the `Context`. + #[inline] + #[unstable(feature = "local_waker", issue = "118959")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const fn build(self) -> Context<'a> { + let ContextBuilder { waker, local_waker, _marker, _marker2 } = self; + Context { waker, local_waker, _marker, _marker2 } + } +} + /// A `Waker` is a handle for waking up a task by notifying its executor that it /// is ready to be run. /// @@ -354,25 +468,8 @@ impl Waker { #[must_use] #[unstable(feature = "noop_waker", issue = "98286")] pub const fn noop() -> &'static Waker { - // Ideally all this data would be explicitly `static` because it is used by reference and - // only ever needs one copy. But `const fn`s (and `const` items) cannot refer to statics, - // even though their values can be promoted to static. (That might change; see #119618.) - // An alternative would be a `pub static NOOP: &Waker`, but associated static items are not - // currently allowed either, and making it non-associated would be unergonomic. - const VTABLE: RawWakerVTable = RawWakerVTable::new( - // Cloning just returns a new no-op raw waker - |_| RAW, - // `wake` does nothing - |_| {}, - // `wake_by_ref` does nothing - |_| {}, - // Dropping does nothing as we don't allocate anything - |_| {}, - ); - const RAW: RawWaker = RawWaker::new(ptr::null(), &VTABLE); - const WAKER_REF: &Waker = &Waker { waker: RAW }; - - WAKER_REF + const WAKER: &Waker = &Waker { waker: RawWaker::NOOP }; + WAKER } /// Get a reference to the underlying [`RawWaker`]. @@ -425,3 +522,222 @@ impl fmt::Debug for Waker { .finish() } } + +/// A `LocalWaker` is analogous to a [`Waker`], but it does not implement [`Send`] or [`Sync`]. +/// +/// This handle encapsulates a [`RawWaker`] instance, which defines the +/// executor-specific wakeup behavior. +/// +/// Local wakers can be requested from a `Context` with the [`local_waker`] method. +/// +/// The typical life of a `LocalWaker` is that it is constructed by an executor, wrapped in a +/// [`Context`] using [`ContextBuilder`], then passed to [`Future::poll()`]. Then, if the future chooses to return +/// [`Poll::Pending`], it must also store the waker somehow and call [`LocalWaker::wake()`] when +/// the future should be polled again. +/// +/// Implements [`Clone`], but neither [`Send`] nor [`Sync`]; therefore, a local waker may +/// not be moved to other threads. In general, when deciding to use wakers or local wakers, +/// local wakers are preferable unless the waker needs to be sent across threads. This is because +/// wakers can incur in additional cost related to memory synchronization. +/// +/// Note that it is preferable to use `local_waker.clone_from(&new_waker)` instead +/// of `*local_waker = new_waker.clone()`, as the former will avoid cloning the waker +/// unnecessarily if the two wakers [wake the same task](Self::will_wake). +/// +/// # Examples +/// Usage of a local waker to implement a future analogous to `std::thread::yield_now()`. +/// ``` +/// #![feature(local_waker)] +/// use std::future::{Future, poll_fn}; +/// use std::task::Poll; +/// +/// // a future that returns pending once. +/// fn yield_now() -> impl Future + Unpin { +/// let mut yielded = false; +/// poll_fn(move |cx| { +/// if !yielded { +/// yielded = true; +/// cx.local_waker().wake_by_ref(); +/// return Poll::Pending; +/// } +/// return Poll::Ready(()) +/// }) +/// } +/// +/// # async fn __() { +/// yield_now().await; +/// # } +/// ``` +/// +/// [`Future::poll()`]: core::future::Future::poll +/// [`Poll::Pending`]: core::task::Poll::Pending +/// [`local_waker`]: core::task::Context::local_waker +#[unstable(feature = "local_waker", issue = "118959")] +#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401 +pub struct LocalWaker { + waker: RawWaker, +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl Unpin for LocalWaker {} + +impl LocalWaker { + /// Wake up the task associated with this `LocalWaker`. + /// + /// As long as the executor keeps running and the task is not finished, it is + /// guaranteed that each invocation of [`wake()`](Self::wake) (or + /// [`wake_by_ref()`](Self::wake_by_ref)) will be followed by at least one + /// [`poll()`] of the task to which this `LocalWaker` belongs. This makes + /// it possible to temporarily yield to other tasks while running potentially + /// unbounded processing loops. + /// + /// Note that the above implies that multiple wake-ups may be coalesced into a + /// single [`poll()`] invocation by the runtime. + /// + /// Also note that yielding to competing tasks is not guaranteed: it is the + /// executor’s choice which task to run and the executor may choose to run the + /// current task again. + /// + /// [`poll()`]: crate::future::Future::poll + #[inline] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn wake(self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + let wake = self.waker.vtable.wake; + let data = self.waker.data; + + // Don't call `drop` -- the waker will be consumed by `wake`. + crate::mem::forget(self); + + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `wake` and `data` requiring the user to acknowledge + // that the contract of `RawWaker` is upheld. + unsafe { (wake)(data) }; + } + + /// Wake up the task associated with this `LocalWaker` without consuming the `LocalWaker`. + /// + /// This is similar to [`wake()`](Self::wake), but may be slightly less efficient in + /// the case where an owned `Waker` is available. This method should be preferred to + /// calling `waker.clone().wake()`. + #[inline] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn wake_by_ref(&self) { + // The actual wakeup call is delegated through a virtual function call + // to the implementation which is defined by the executor. + + // SAFETY: see `wake` + unsafe { (self.waker.vtable.wake_by_ref)(self.waker.data) } + } + + /// Returns `true` if this `LocalWaker` and another `LocalWaker` would awake the same task. + /// + /// This function works on a best-effort basis, and may return false even + /// when the `Waker`s would awaken the same task. However, if this function + /// returns `true`, it is guaranteed that the `Waker`s will awaken the same task. + /// + /// This function is primarily used for optimization purposes — for example, + /// this type's [`clone_from`](Self::clone_from) implementation uses it to + /// avoid cloning the waker when they would wake the same task anyway. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + pub fn will_wake(&self, other: &LocalWaker) -> bool { + self.waker == other.waker + } + + /// Creates a new `LocalWaker` from [`RawWaker`]. + /// + /// The behavior of the returned `LocalWaker` is undefined if the contract defined + /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. + /// Therefore this method is unsafe. + #[inline] + #[must_use] + #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_const_unstable(feature = "const_waker", issue = "102012")] + pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker { + Self { waker } + } + + /// Creates a new `LocalWaker` that does nothing when `wake` is called. + /// + /// This is mostly useful for writing tests that need a [`Context`] to poll + /// some futures, but are not expecting those futures to wake the waker or + /// do not need to do anything specific if it happens. + /// + /// # Examples + /// + /// ``` + /// #![feature(local_waker)] + /// #![feature(noop_waker)] + /// + /// use std::future::Future; + /// use std::task::{ContextBuilder, LocalWaker, Waker, Poll}; + /// + /// let mut cx = ContextBuilder::from_waker(Waker::noop()) + /// .local_waker(LocalWaker::noop()) + /// .build(); + /// + /// let mut future = Box::pin(async { 10 }); + /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(10)); + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "noop_waker", issue = "98286")] + pub const fn noop() -> &'static LocalWaker { + const WAKER: &LocalWaker = &LocalWaker { waker: RawWaker::NOOP }; + WAKER + } + + /// Get a reference to the underlying [`RawWaker`]. + #[inline] + #[must_use] + #[unstable(feature = "waker_getters", issue = "96992")] + pub fn as_raw(&self) -> &RawWaker { + &self.waker + } +} +#[unstable(feature = "local_waker", issue = "118959")] +impl Clone for LocalWaker { + #[inline] + fn clone(&self) -> Self { + LocalWaker { + // SAFETY: This is safe because `Waker::from_raw` is the only way + // to initialize `clone` and `data` requiring the user to acknowledge + // that the contract of [`RawWaker`] is upheld. + waker: unsafe { (self.waker.vtable.clone)(self.waker.data) }, + } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + if !self.will_wake(source) { + *self = source.clone(); + } + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl AsRef for Waker { + fn as_ref(&self) -> &LocalWaker { + // SAFETY: LocalWaker is just Waker without thread safety + unsafe { transmute(self) } + } +} + +#[stable(feature = "futures_api", since = "1.36.0")] +impl fmt::Debug for LocalWaker { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let vtable_ptr = self.waker.vtable as *const RawWakerVTable; + f.debug_struct("LocalWaker") + .field("data", &self.waker.data) + .field("vtable", &vtable_ptr) + .finish() + } +} + +#[unstable(feature = "local_waker", issue = "118959")] +impl !Send for LocalWaker {} +#[unstable(feature = "local_waker", issue = "118959")] +impl !Sync for LocalWaker {} diff --git a/library/core/src/time.rs b/library/core/src/time.rs index b677776443fe0..e4f2994296607 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -197,13 +197,18 @@ impl Duration { #[must_use] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn new(secs: u64, nanos: u32) -> Duration { - let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { - Some(secs) => secs, - None => panic!("overflow in Duration::new"), - }; - let nanos = nanos % NANOS_PER_SEC; - // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range - Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + if nanos < NANOS_PER_SEC { + // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } else { + let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { + Some(secs) => secs, + None => panic!("overflow in Duration::new"), + }; + let nanos = nanos % NANOS_PER_SEC; + // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } } /// Creates a new `Duration` from the specified number of whole seconds. diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 47e27bdc73533..44fac589d4c53 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -61,14 +61,6 @@ macro_rules! tuple_impls { {} } - maybe_tuple_doc! { - $($T)+ @ - #[unstable(feature = "structural_match", issue = "31434")] - #[cfg(bootstrap)] - impl<$($T),+> crate::marker::StructuralEq for ($($T,)+) - {} - } - maybe_tuple_doc! { $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 9a3b477c2d159..6deebc0d2637c 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -14,6 +14,7 @@ #![feature(const_cell_into_inner)] #![feature(const_hash)] #![feature(const_heap)] +#![feature(const_intrinsic_copy)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_nonnull_new)] #![feature(const_pointer_is_aligned)] @@ -58,7 +59,7 @@ #![feature(noop_waker)] #![feature(numfmt)] #![feature(num_midpoint)] -#![cfg_attr(not(bootstrap), feature(offset_of_nested))] +#![feature(offset_of_nested)] #![feature(isqrt)] #![feature(step_trait)] #![feature(str_internals)] @@ -111,7 +112,7 @@ #![feature(slice_flatten)] #![feature(error_generic_member_access)] #![feature(error_in_core)] -#![cfg_attr(not(bootstrap), feature(trait_upcasting))] +#![feature(trait_upcasting)] #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] diff --git a/library/core/tests/macros.rs b/library/core/tests/macros.rs index eb886def164ac..09994fbcbdb78 100644 --- a/library/core/tests/macros.rs +++ b/library/core/tests/macros.rs @@ -1,3 +1,4 @@ +#[allow(dead_code)] trait Trait { fn blah(&self); } diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index ccae406cc286c..d3ba546d730d4 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -262,7 +262,7 @@ cfg_if::cfg_if! { } // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[cfg_attr(not(bootstrap), allow(static_mut_ref))] +#[allow(static_mut_ref)] pub unsafe fn panic(data: Box) -> u32 { use core::intrinsics::atomic_store_seqcst; @@ -325,7 +325,7 @@ pub unsafe fn panic(data: Box) -> u32 { } // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[cfg_attr(not(bootstrap), allow(static_mut_ref))] +#[allow(static_mut_ref)] pub unsafe fn cleanup(payload: *mut u8) -> Box { // A null payload here means that we got here from the catch (...) of // __rust_try. This happens when a non-Rust foreign exception is caught. diff --git a/library/portable-simd/crates/core_simd/src/vendor/arm.rs b/library/portable-simd/crates/core_simd/src/vendor/arm.rs index ff3b69ccf9592..ee5c642137367 100644 --- a/library/portable-simd/crates/core_simd/src/vendor/arm.rs +++ b/library/portable-simd/crates/core_simd/src/vendor/arm.rs @@ -7,9 +7,12 @@ use core::arch::arm::*; #[cfg(target_arch = "aarch64")] use core::arch::aarch64::*; -#[cfg(any( - target_arch = "aarch64", - all(target_arch = "arm", target_feature = "v7"), +#[cfg(all( + any( + target_arch = "aarch64", + all(target_arch = "arm", target_feature = "v7"), + ), + target_endian = "little" ))] mod neon { use super::*; diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 52a08cad9110f..9255c3abc8a02 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -3,6 +3,7 @@ use super::*; use std::marker::PhantomData; +use std::sync::atomic::AtomicU32; macro_rules! define_handles { ( @@ -12,8 +13,8 @@ macro_rules! define_handles { #[repr(C)] #[allow(non_snake_case)] pub struct HandleCounters { - $($oty: AtomicUsize,)* - $($ity: AtomicUsize,)* + $($oty: AtomicU32,)* + $($ity: AtomicU32,)* } impl HandleCounters { @@ -21,8 +22,8 @@ macro_rules! define_handles { // a wrapper `fn` pointer, once `const fn` can reference `static`s. extern "C" fn get() -> &'static Self { static COUNTERS: HandleCounters = HandleCounters { - $($oty: AtomicUsize::new(1),)* - $($ity: AtomicUsize::new(1),)* + $($oty: AtomicU32::new(1),)* + $($ity: AtomicU32::new(1),)* }; &COUNTERS } diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs index 00954107b7769..b3a763069974f 100644 --- a/library/proc_macro/src/bridge/handle.rs +++ b/library/proc_macro/src/bridge/handle.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use std::hash::Hash; use std::num::NonZeroU32; use std::ops::{Index, IndexMut}; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicU32, Ordering}; use super::fxhash::FxHashMap; @@ -13,12 +13,12 @@ pub(super) type Handle = NonZeroU32; /// A store that associates values of type `T` with numeric handles. A value can /// be looked up using its handle. pub(super) struct OwnedStore { - counter: &'static AtomicUsize, + counter: &'static AtomicU32, data: BTreeMap, } impl OwnedStore { - pub(super) fn new(counter: &'static AtomicUsize) -> Self { + pub(super) fn new(counter: &'static AtomicU32) -> Self { // Ensure the handle counter isn't 0, which would panic later, // when `NonZeroU32::new` (aka `Handle::new`) is called in `alloc`. assert_ne!(counter.load(Ordering::SeqCst), 0); @@ -30,7 +30,7 @@ impl OwnedStore { impl OwnedStore { pub(super) fn alloc(&mut self, x: T) -> Handle { let counter = self.counter.fetch_add(1, Ordering::SeqCst); - let handle = Handle::new(counter as u32).expect("`proc_macro` handle counter overflowed"); + let handle = Handle::new(counter).expect("`proc_macro` handle counter overflowed"); assert!(self.data.insert(handle, x).is_none()); handle } @@ -60,7 +60,7 @@ pub(super) struct InternedStore { } impl InternedStore { - pub(super) fn new(counter: &'static AtomicUsize) -> Self { + pub(super) fn new(counter: &'static AtomicU32) -> Self { InternedStore { owned: OwnedStore::new(counter), interner: FxHashMap::default() } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 75bf3329786a4..55e24b6491c79 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -16,7 +16,6 @@ use std::mem; use std::ops::Bound; use std::ops::Range; use std::panic; -use std::sync::atomic::AtomicUsize; use std::sync::Once; use std::thread; diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 5b32bc5117c0c..20f4310603a05 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -libc = { version = "0.2.150", default-features = false, features = ['rustc-dep-of-std'], public = true } +libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true } compiler_builtins = { version = "0.1.105" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index fc27b6a67bfcb..0d4c1fa05cc87 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -356,6 +356,7 @@ impl HashMap { /// /// In the current implementation, iterating over keys takes O(capacity) time /// instead of O(len) because it internally visits empty buckets too. + #[rustc_lint_query_instability] #[stable(feature = "rust1", since = "1.0.0")] pub fn keys(&self) -> Keys<'_, K, V> { Keys { inner: self.iter() } @@ -417,6 +418,7 @@ impl HashMap { /// /// In the current implementation, iterating over values takes O(capacity) time /// instead of O(len) because it internally visits empty buckets too. + #[rustc_lint_query_instability] #[stable(feature = "rust1", since = "1.0.0")] pub fn values(&self) -> Values<'_, K, V> { Values { inner: self.iter() } @@ -449,6 +451,7 @@ impl HashMap { /// /// In the current implementation, iterating over values takes O(capacity) time /// instead of O(len) because it internally visits empty buckets too. + #[rustc_lint_query_instability] #[stable(feature = "map_values_mut", since = "1.10.0")] pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { ValuesMut { inner: self.iter_mut() } diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 1b38ba721147c..b60d7a724112d 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -114,7 +114,7 @@ impl f32 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f32 { unsafe { intrinsics::rintf32(self) } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index f8fc84440ae5c..88f992b3957af 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -114,7 +114,7 @@ impl f64 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f64 { unsafe { intrinsics::rintf64(self) } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 80d369eb067d4..3383a8cfa41ef 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -428,7 +428,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_create_new", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_create_new", since = "1.77.0")] pub fn create_new>(path: P) -> io::Result { OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref()) } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8fca66fa17c5e..a238e74ed95cf 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -578,8 +578,13 @@ where F: FnOnce(&mut [u8]) -> Result, { let n = read(cursor.ensure_init().init_mut())?; + assert!( + n <= cursor.capacity(), + "read should not return more bytes than there is capacity for in the read buffer" + ); unsafe { - // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to. + // SAFETY: we initialised using `ensure_init` so there is no uninit data to advance to + // and we have checked that the read amount is not over capacity (see #120603) cursor.advance(n); } Ok(()) @@ -994,7 +999,10 @@ pub trait Read { } if cursor.written() == prev_written { - return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer")); + return Err(error::const_io_error!( + ErrorKind::UnexpectedEof, + "failed to fill whole buffer" + )); } } diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index bda5b721adc63..33e9d8efed511 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -1,6 +1,6 @@ use super::{repeat, BorrowedBuf, Cursor, SeekFrom}; use crate::cmp::{self, min}; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut, DEFAULT_BUF_SIZE}; use crate::io::{BufRead, BufReader, Read, Seek, Write}; use crate::mem::MaybeUninit; use crate::ops::Deref; @@ -652,3 +652,32 @@ fn bench_take_read_buf(b: &mut test::Bencher) { [255; 128].take(64).read_buf(buf.unfilled()).unwrap(); }); } + +// Issue #120603 +#[test] +#[should_panic = "read should not return more bytes than there is capacity for in the read buffer"] +fn read_buf_broken_read() { + struct MalformedRead; + + impl Read for MalformedRead { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + // broken length calculation + Ok(buf.len() + 1) + } + } + + let _ = BufReader::new(MalformedRead).fill_buf(); +} + +#[test] +fn read_buf_full_read() { + struct FullRead; + + impl Read for FullRead { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + Ok(buf.len()) + } + } + + assert_eq!(BufReader::new(FullRead).fill_buf().unwrap().len(), DEFAULT_BUF_SIZE); +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2e458562744bf..571e475c33672 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -262,15 +262,16 @@ )] #![cfg_attr(any(windows, target_os = "uefi"), feature(round_char_boundary))] #![cfg_attr(target_os = "xous", feature(slice_ptr_len))] +#![cfg_attr(target_family = "wasm", feature(stdarch_wasm_atomic_wait))] // // Language features: // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), feature(cfg_sanitizer_cfi))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] #![feature(c_unwind)] +#![feature(cfg_sanitizer_cfi)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] #![feature(concat_idents)] @@ -338,7 +339,6 @@ #![feature(portable_simd)] #![feature(prelude_2024)] #![feature(ptr_as_uninit)] -#![feature(raw_os_nonzero)] #![feature(slice_internals)] #![feature(slice_ptr_get)] #![feature(slice_range)] @@ -365,6 +365,11 @@ #![feature(panic_unwind)] // tidy-alphabetical-end // +// Library features (std_detect): +// tidy-alphabetical-start +#![feature(stdarch_internal)] +// tidy-alphabetical-end +// // Only for re-exporting: // tidy-alphabetical-start #![feature(assert_matches)] @@ -380,7 +385,6 @@ #![feature(get_many_mut)] #![feature(lazy_cell)] #![feature(log_syntax)] -#![feature(stdsimd)] #![feature(test)] #![feature(trace_macros)] // tidy-alphabetical-end @@ -619,13 +623,16 @@ pub mod arch { #[stable(feature = "simd_aarch64", since = "1.60.0")] pub use std_detect::is_aarch64_feature_detected; + #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] + pub use std_detect::is_arm_feature_detected; + #[unstable(feature = "is_riscv_feature_detected", issue = "111192")] + pub use std_detect::is_riscv_feature_detected; #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; - #[unstable(feature = "stdsimd", issue = "48556")] - pub use std_detect::{ - is_arm_feature_detected, is_mips64_feature_detected, is_mips_feature_detected, - is_powerpc64_feature_detected, is_powerpc_feature_detected, is_riscv_feature_detected, - }; + #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] + pub use std_detect::{is_mips64_feature_detected, is_mips_feature_detected}; + #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] + pub use std_detect::{is_powerpc64_feature_detected, is_powerpc_feature_detected}; } // This was stabilized in the crate root so we have to keep it there. diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index f03e079030503..6e11b92b618a3 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -85,9 +85,6 @@ pub mod linux; #[cfg(any(target_os = "wasi", doc))] pub mod wasi; -#[cfg(any(all(target_os = "wasi", target_env = "preview2"), doc))] -pub mod wasi_preview2; - // windows #[cfg(not(all( doc, diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index 05c8d30073f42..bbaf328f457e4 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -28,8 +28,7 @@ //! [`OsStr`]: crate::ffi::OsStr //! [`OsString`]: crate::ffi::OsString -#![cfg_attr(not(target_env = "preview2"), stable(feature = "rust1", since = "1.0.0"))] -#![cfg_attr(target_env = "preview2", unstable(feature = "wasm_preview2", issue = "none"))] +#![stable(feature = "rust1", since = "1.0.0")] #![deny(unsafe_op_in_unsafe_fn)] #![doc(cfg(target_os = "wasi"))] diff --git a/library/std/src/os/wasi_preview2/mod.rs b/library/std/src/os/wasi_preview2/mod.rs deleted file mode 100644 index 1d44dd72814b8..0000000000000 --- a/library/std/src/os/wasi_preview2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Platform-specific extensions to `std` for Preview 2 of the WebAssembly System Interface (WASI). -//! -//! This module is currently empty, but will be filled over time as wasi-libc support for WASI Preview 2 is stabilized. - -#![stable(feature = "raw_ext", since = "1.1.0")] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 7f6b563d72959..3728d5b64b865 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -5,7 +5,7 @@ use crate::any::Any; use crate::collections; use crate::panicking; -use crate::sync::atomic::{AtomicUsize, Ordering}; +use crate::sync::atomic::{AtomicU8, Ordering}; use crate::sync::{Mutex, RwLock}; use crate::thread::Result; @@ -228,7 +228,7 @@ impl BacktraceStyle { if cfg!(feature = "backtrace") { Some(BacktraceStyle::Full) } else { None } } - fn as_usize(self) -> usize { + fn as_u8(self) -> u8 { match self { BacktraceStyle::Short => 1, BacktraceStyle::Full => 2, @@ -236,7 +236,7 @@ impl BacktraceStyle { } } - fn from_usize(s: usize) -> Option { + fn from_u8(s: u8) -> Option { Some(match s { 0 => return None, 1 => BacktraceStyle::Short, @@ -251,7 +251,7 @@ impl BacktraceStyle { // that backtrace. // // Internally stores equivalent of an Option. -static SHOULD_CAPTURE: AtomicUsize = AtomicUsize::new(0); +static SHOULD_CAPTURE: AtomicU8 = AtomicU8::new(0); /// Configure whether the default panic hook will capture and display a /// backtrace. @@ -264,7 +264,7 @@ pub fn set_backtrace_style(style: BacktraceStyle) { // If the `backtrace` feature of this crate isn't enabled, skip setting. return; } - SHOULD_CAPTURE.store(style.as_usize(), Ordering::Release); + SHOULD_CAPTURE.store(style.as_u8(), Ordering::Release); } /// Checks whether the standard library's panic hook will capture and print a @@ -296,7 +296,7 @@ pub fn get_backtrace_style() -> Option { // to optimize away callers. return None; } - if let Some(style) = BacktraceStyle::from_usize(SHOULD_CAPTURE.load(Ordering::Acquire)) { + if let Some(style) = BacktraceStyle::from_u8(SHOULD_CAPTURE.load(Ordering::Acquire)) { return Some(style); } diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index c80f15d8a611b..8294160b72ca7 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -338,7 +338,7 @@ pub mod panic_count { #[cfg(not(feature = "panic_immediate_abort"))] #[unstable(feature = "update_panic_count", issue = "none")] // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[cfg_attr(not(bootstrap), allow(static_mut_ref))] +#[allow(static_mut_ref)] pub mod panic_count { use crate::cell::Cell; use crate::sync::atomic::{AtomicUsize, Ordering}; diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 184c406e326cf..920143b7ac7b2 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -404,7 +404,7 @@ impl Mutex { /// assert_eq!(*x, 1); /// ``` #[inline] - #[stable(feature = "mutex_unpoison", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mutex_unpoison", since = "1.77.0")] pub fn clear_poison(&self) { self.poison.clear(); } diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 23d3dd0707a34..c5d846b85aa1e 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -408,7 +408,7 @@ impl RwLock { /// assert_eq!(*guard, 1); /// ``` #[inline] - #[stable(feature = "mutex_unpoison", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mutex_unpoison", since = "1.77.0")] pub fn clear_poison(&self) { self.poison.clear(); } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index e03e98b18d29f..fae21636897b8 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -7,6 +7,7 @@ mod personality; pub mod cmath; pub mod os_str; +pub mod path; // FIXME(117276): remove this, move feature implementations into individual // submodules. diff --git a/library/std/src/sys/pal/common/thread_local/fast_local.rs b/library/std/src/sys/pal/common/thread_local/fast_local.rs index 9206588be064e..0fdca27852ca6 100644 --- a/library/std/src/sys/pal/common/thread_local/fast_local.rs +++ b/library/std/src/sys/pal/common/thread_local/fast_local.rs @@ -14,7 +14,7 @@ pub macro thread_local_inner { #[inline] #[deny(unsafe_op_in_unsafe_fn)] // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint - #[cfg_attr(not(bootstrap), allow(static_mut_ref))] + #[allow(static_mut_ref)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/sys/pal/common/thread_local/static_local.rs b/library/std/src/sys/pal/common/thread_local/static_local.rs index 51cba66fad76d..0dde78b14dbb8 100644 --- a/library/std/src/sys/pal/common/thread_local/static_local.rs +++ b/library/std/src/sys/pal/common/thread_local/static_local.rs @@ -12,7 +12,7 @@ pub macro thread_local_inner { #[inline] // see comments below #[deny(unsafe_op_in_unsafe_fn)] // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint - #[cfg_attr(not(bootstrap), allow(static_mut_ref))] + #[allow(static_mut_ref)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 3c83afa280be5..57cc656e266a1 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -28,8 +28,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index f927d88d46c34..041b7c355822a 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -40,9 +40,6 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use self::wasi::*; - } else if #[cfg(all(target_os = "wasi", target_env = "preview2"))] { - mod wasi_preview2; - pub use self::wasi_preview2::*; } else if #[cfg(target_family = "wasm")] { mod wasm; pub use self::wasm::*; diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index a769fc1ef5932..46f3e5b401da5 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -22,7 +22,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/pal/sgx/net.rs index 03620a08f2c03..c4d5da1627cb2 100644 --- a/library/std/src/sys/pal/sgx/net.rs +++ b/library/std/src/sys/pal/sgx/net.rs @@ -542,7 +542,4 @@ pub mod netc { pub sin6_flowinfo: u32, pub sin6_scope_id: u32, } - - #[derive(Copy, Clone)] - pub struct sockaddr {} } diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 46699e64169f5..be8e00339021f 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -29,7 +29,6 @@ pub mod fs; pub mod io; pub mod net; pub mod os; -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 95a5b97ea4237..7953104486c56 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -25,8 +25,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/teeos/net.rs b/library/std/src/sys/pal/teeos/net.rs index 0df681dbfa552..fed95205027a7 100644 --- a/library/std/src/sys/pal/teeos/net.rs +++ b/library/std/src/sys/pal/teeos/net.rs @@ -364,9 +364,6 @@ pub mod netc { pub sin6_flowinfo: u32, pub sin6_scope_id: u32, } - - #[derive(Copy, Clone)] - pub struct sockaddr {} } pub type Socket = UdpSocket; diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 9837cc89f2d39..ba53ed88f3765 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -146,3 +146,11 @@ pub(crate) fn image_handle_protocol(protocol_guid: Guid) -> Option let system_handle = uefi::env::try_image_handle()?; open_protocol(system_handle, protocol_guid).ok() } + +/// Get RuntimeServices +pub(crate) fn runtime_services() -> Option> { + let system_table: NonNull = + crate::os::uefi::env::try_system_table()?.cast(); + let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services }; + NonNull::new(runtime_services) +} diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 9ee753aa1a0c1..efa4ed67c50ca 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -26,7 +26,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] @@ -38,7 +37,6 @@ pub mod thread; pub mod thread_local_key; #[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; -#[path = "../unsupported/time.rs"] pub mod time; mod helpers; diff --git a/library/std/src/sys/pal/uefi/path.rs b/library/std/src/sys/pal/uefi/path.rs deleted file mode 100644 index 106682eee56b6..0000000000000 --- a/library/std/src/sys/pal/uefi/path.rs +++ /dev/null @@ -1,25 +0,0 @@ -use super::unsupported; -use crate::ffi::OsStr; -use crate::io; -use crate::path::{Path, PathBuf, Prefix}; - -pub const MAIN_SEP_STR: &str = "\\"; -pub const MAIN_SEP: char = '\\'; - -#[inline] -pub fn is_sep_byte(b: u8) -> bool { - b == b'\\' -} - -#[inline] -pub fn is_verbatim_sep(b: u8) -> bool { - b == b'\\' -} - -pub fn parse_prefix(_p: &OsStr) -> Option> { - None -} - -pub(crate) fn absolute(_path: &Path) -> io::Result { - unsupported() -} diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index 8806eda3ac0a6..5eb36da922b54 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,4 +1,6 @@ use super::alloc::*; +use super::time::*; +use crate::time::Duration; #[test] fn align() { @@ -19,3 +21,21 @@ fn align() { } } } + +#[test] +fn epoch() { + let t = r_efi::system::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: r_efi::efi::UNSPECIFIED_TIMEZONE, + daylight: 0, + pad1: 0, + pad2: 0, + }; + assert_eq!(system_time_internal::uefi_time_to_duration(t), Duration::new(0, 0)); +} diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs new file mode 100644 index 0000000000000..68f428c38fbb3 --- /dev/null +++ b/library/std/src/sys/pal/uefi/time.rs @@ -0,0 +1,105 @@ +use crate::time::Duration; + +const SECS_IN_MINUTE: u64 = 60; +const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; +const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(Duration); + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(Duration); + +pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); + +impl Instant { + pub fn now() -> Instant { + panic!("time not implemented on this platform") + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + self.0.checked_sub(other.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_sub(*other)?)) + } +} + +impl SystemTime { + pub fn now() -> SystemTime { + system_time_internal::now() + .unwrap_or_else(|| panic!("time not implemented on this platform")) + } + + pub fn sub_time(&self, other: &SystemTime) -> Result { + self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_sub(*other)?)) + } +} + +pub(crate) mod system_time_internal { + use super::super::helpers; + use super::*; + use crate::mem::MaybeUninit; + use crate::ptr::NonNull; + use r_efi::efi::{RuntimeServices, Time}; + + pub fn now() -> Option { + let runtime_services: NonNull = helpers::runtime_services()?; + let mut t: MaybeUninit
{ @@ -754,8 +762,8 @@ impl Evaluator<'_> { RustcEnumVariantIdx(it.lookup(self.db.upcast()).index as usize) } _ => { - return Err(MirEvalError::TypeError( - "Multivariant layout only happens for enums", + return Err(MirEvalError::InternalError( + "mismatched layout".into(), )) } }] @@ -993,12 +1001,12 @@ impl Evaluator<'_> { IntervalOrOwned::Borrowed(value) => interval.write_from_interval(self, value)?, } if remain_args == 0 { - return Err(MirEvalError::TypeError("more arguments provided")); + return Err(MirEvalError::InternalError("too many arguments".into())); } remain_args -= 1; } if remain_args > 0 { - return Err(MirEvalError::TypeError("not enough arguments provided")); + return Err(MirEvalError::InternalError("too few arguments".into())); } Ok(()) } @@ -1071,8 +1079,8 @@ impl Evaluator<'_> { match metadata { Some(m) => m, None => { - return Err(MirEvalError::TypeError( - "type without metadata is used for Rvalue::Len", + return Err(MirEvalError::InternalError( + "type without metadata is used for Rvalue::Len".into(), )); } } @@ -1312,7 +1320,7 @@ impl Evaluator<'_> { } AggregateKind::Tuple(ty) => { let layout = self.layout(ty)?; - Owned(self.make_by_layout( + Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -1334,7 +1342,7 @@ impl Evaluator<'_> { AggregateKind::Adt(it, subst) => { let (size, variant_layout, tag) = self.layout_of_variant(*it, subst.clone(), locals)?; - Owned(self.make_by_layout( + Owned(self.construct_with_layout( size, &variant_layout, tag, @@ -1343,7 +1351,7 @@ impl Evaluator<'_> { } AggregateKind::Closure(ty) => { let layout = self.layout(ty)?; - Owned(self.make_by_layout( + Owned(self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -1415,10 +1423,7 @@ impl Evaluator<'_> { Ok(r) } Variants::Multiple { tag, tag_encoding, variants, .. } => { - let Some(target_data_layout) = self.db.target_data_layout(self.crate_id) else { - not_supported!("missing target data layout"); - }; - let size = tag.size(&*target_data_layout).bytes_usize(); + let size = tag.size(&*self.target_data_layout).bytes_usize(); let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field match tag_encoding { TagEncoding::Direct => { @@ -1458,9 +1463,8 @@ impl Evaluator<'_> { if let TyKind::Adt(id, subst) = kind { if let AdtId::StructId(struct_id) = id.0 { let field_types = self.db.field_types(struct_id.into()); - let mut field_types = field_types.iter(); if let Some(ty) = - field_types.next().map(|it| it.1.clone().substitute(Interner, subst)) + field_types.iter().last().map(|it| it.1.clone().substitute(Interner, subst)) { return self.coerce_unsized_look_through_fields(&ty, goal); } @@ -1578,10 +1582,6 @@ impl Evaluator<'_> { Ok(match &layout.variants { Variants::Single { .. } => (layout.size.bytes_usize(), layout, None), Variants::Multiple { variants, tag, tag_encoding, .. } => { - let cx = self - .db - .target_data_layout(self.crate_id) - .ok_or(MirEvalError::TargetDataLayoutNotAvailable)?; let enum_variant_id = match it { VariantId::EnumVariantId(it) => it, _ => not_supported!("multi variant layout for non-enums"), @@ -1612,7 +1612,7 @@ impl Evaluator<'_> { if have_tag { Some(( layout.fields.offset(0).bytes_usize(), - tag.size(&*cx).bytes_usize(), + tag.size(&*self.target_data_layout).bytes_usize(), discriminant, )) } else { @@ -1623,7 +1623,7 @@ impl Evaluator<'_> { }) } - fn make_by_layout( + fn construct_with_layout( &mut self, size: usize, // Not necessarily equal to variant_layout.size variant_layout: &Layout, @@ -1634,7 +1634,14 @@ impl Evaluator<'_> { if let Some((offset, size, value)) = tag { match result.get_mut(offset..offset + size) { Some(it) => it.copy_from_slice(&value.to_le_bytes()[0..size]), - None => return Err(MirEvalError::BrokenLayout(Box::new(variant_layout.clone()))), + None => { + return Err(MirEvalError::InternalError( + format!( + "encoded tag ({offset}, {size}, {value}) is out of bounds 0..{size}" + ) + .into(), + )) + } } } for (i, op) in values.enumerate() { @@ -1642,7 +1649,11 @@ impl Evaluator<'_> { let op = op.get(self)?; match result.get_mut(offset..offset + op.len()) { Some(it) => it.copy_from_slice(op), - None => return Err(MirEvalError::BrokenLayout(Box::new(variant_layout.clone()))), + None => { + return Err(MirEvalError::InternalError( + format!("field offset ({offset}) is out of bounds 0..{size}").into(), + )) + } } } Ok(result) @@ -1695,28 +1706,29 @@ impl Evaluator<'_> { } ConstScalar::Unknown => not_supported!("evaluating unknown const"), }; - let mut v: Cow<'_, [u8]> = Cow::Borrowed(v); let patch_map = memory_map.transform_addresses(|b, align| { let addr = self.heap_allocate(b.len(), align)?; self.write_memory(addr, b)?; Ok(addr.to_usize()) })?; let (size, align) = self.size_align_of(ty, locals)?.unwrap_or((v.len(), 1)); - if size != v.len() { + let v: Cow<'_, [u8]> = if size != v.len() { // Handle self enum if size == 16 && v.len() < 16 { - v = Cow::Owned(pad16(&v, false).to_vec()); + Cow::Owned(pad16(v, false).to_vec()) } else if size < 16 && v.len() == 16 { - v = Cow::Owned(v[0..size].to_vec()); + Cow::Borrowed(&v[0..size]) } else { return Err(MirEvalError::InvalidConst(konst.clone())); } - } + } else { + Cow::Borrowed(v) + }; let addr = self.heap_allocate(size, align)?; self.write_memory(addr, &v)?; self.patch_addresses( &patch_map, - |bytes| match &memory_map { + |bytes| match memory_map { MemoryMap::Empty | MemoryMap::Simple(_) => { Err(MirEvalError::InvalidVTableId(from_bytes!(usize, bytes))) } @@ -2000,7 +2012,7 @@ impl Evaluator<'_> { if let Some((v, l)) = detect_variant_from_bytes( &layout, this.db, - this.trait_env.clone(), + &this.target_data_layout, bytes, e, ) { @@ -2079,7 +2091,7 @@ impl Evaluator<'_> { if let Some((ev, layout)) = detect_variant_from_bytes( &layout, self.db, - self.trait_env.clone(), + &self.target_data_layout, self.read_memory(addr, layout.size.bytes_usize())?, e, ) { @@ -2153,14 +2165,14 @@ impl Evaluator<'_> { ) -> Result> { let id = from_bytes!(usize, bytes.get(self)?); let next_ty = self.vtable_map.ty(id)?.clone(); - match &next_ty.kind(Interner) { + match next_ty.kind(Interner) { TyKind::FnDef(def, generic_args) => { self.exec_fn_def(*def, generic_args, destination, args, locals, target_bb, span) } TyKind::Closure(id, subst) => { self.exec_closure(*id, bytes.slice(0..0), subst, destination, args, locals, span) } - _ => Err(MirEvalError::TypeError("function pointer to non function")), + _ => Err(MirEvalError::InternalError("function pointer to non function".into())), } } @@ -2241,7 +2253,7 @@ impl Evaluator<'_> { CallableDefId::StructId(id) => { let (size, variant_layout, tag) = self.layout_of_variant(id.into(), generic_args, locals)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( size, &variant_layout, tag, @@ -2253,7 +2265,7 @@ impl Evaluator<'_> { CallableDefId::EnumVariantId(id) => { let (size, variant_layout, tag) = self.layout_of_variant(id.into(), generic_args, locals)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( size, &variant_layout, tag, @@ -2407,7 +2419,9 @@ impl Evaluator<'_> { target_bb: Option, span: MirSpan, ) -> Result> { - let func = args.first().ok_or(MirEvalError::TypeError("fn trait with no arg"))?; + let func = args + .first() + .ok_or_else(|| MirEvalError::InternalError("fn trait with no arg".into()))?; let mut func_ty = func.ty.clone(); let mut func_data = func.interval; while let TyKind::Ref(_, _, z) = func_ty.kind(Interner) { @@ -2450,7 +2464,7 @@ impl Evaluator<'_> { ) .intern(Interner); let layout = self.layout(&ty)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -2634,7 +2648,7 @@ pub fn render_const_using_debug_impl( owner: ConstId, c: &Const, ) -> Result { - let mut evaluator = Evaluator::new(db, owner.into(), false, None); + let mut evaluator = Evaluator::new(db, owner.into(), false, None)?; let locals = &Locals { ptr: ArenaMap::new(), body: db @@ -2699,12 +2713,7 @@ pub fn render_const_using_debug_impl( pub fn pad16(it: &[u8], is_signed: bool) -> [u8; 16] { let is_negative = is_signed && it.last().unwrap_or(&0) > &127; - let fill_with = if is_negative { 255 } else { 0 }; - it.iter() - .copied() - .chain(iter::repeat(fill_with)) - .take(16) - .collect::>() - .try_into() - .expect("iterator take is not working") + let mut res = [if is_negative { 255 } else { 0 }; 16]; + res[..it.len()].copy_from_slice(it); + res } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 4336e1e53b7f5..b4fb99acae778 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -18,7 +18,7 @@ macro_rules! from_bytes { ($ty:tt, $value:expr) => { ($ty::from_le_bytes(match ($value).try_into() { Ok(it) => it, - Err(_) => return Err(MirEvalError::TypeError("mismatched size")), + Err(_) => return Err(MirEvalError::InternalError("mismatched size".into())), })) }; } @@ -249,7 +249,9 @@ impl Evaluator<'_> { match alloc_fn { "rustc_allocator_zeroed" | "rustc_allocator" => { let [size, align] = args else { - return Err(MirEvalError::TypeError("rustc_allocator args are not provided")); + return Err(MirEvalError::InternalError( + "rustc_allocator args are not provided".into(), + )); }; let size = from_bytes!(usize, size.get(self)?); let align = from_bytes!(usize, align.get(self)?); @@ -259,7 +261,9 @@ impl Evaluator<'_> { "rustc_deallocator" => { /* no-op for now */ } "rustc_reallocator" => { let [ptr, old_size, align, new_size] = args else { - return Err(MirEvalError::TypeError("rustc_allocator args are not provided")); + return Err(MirEvalError::InternalError( + "rustc_allocator args are not provided".into(), + )); }; let old_size = from_bytes!(usize, old_size.get(self)?); let new_size = from_bytes!(usize, new_size.get(self)?); @@ -339,22 +343,22 @@ impl Evaluator<'_> { Err(MirEvalError::Panic(message)) } SliceLen => { - let arg = args - .next() - .ok_or(MirEvalError::TypeError("argument of <[T]>::len() is not provided"))?; + let arg = args.next().ok_or(MirEvalError::InternalError( + "argument of <[T]>::len() is not provided".into(), + ))?; let ptr_size = arg.len() / 2; Ok(arg[ptr_size..].into()) } DropInPlace => { let ty = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)).ok_or( - MirEvalError::TypeError( - "generic argument of drop_in_place is not provided", + MirEvalError::InternalError( + "generic argument of drop_in_place is not provided".into(), ), )?; - let arg = args - .next() - .ok_or(MirEvalError::TypeError("argument of drop_in_place is not provided"))?; + let arg = args.next().ok_or(MirEvalError::InternalError( + "argument of drop_in_place is not provided".into(), + ))?; self.run_drop_glue_deep( ty.clone(), locals, @@ -380,7 +384,9 @@ impl Evaluator<'_> { 318 => { // SYS_getrandom let [buf, len, _flags] = args else { - return Err(MirEvalError::TypeError("SYS_getrandom args are not provided")); + return Err(MirEvalError::InternalError( + "SYS_getrandom args are not provided".into(), + )); }; let addr = Address::from_bytes(buf.get(self)?)?; let size = from_bytes!(usize, len.get(self)?); @@ -408,7 +414,7 @@ impl Evaluator<'_> { match as_str { "memcmp" => { let [ptr1, ptr2, size] = args else { - return Err(MirEvalError::TypeError("memcmp args are not provided")); + return Err(MirEvalError::InternalError("memcmp args are not provided".into())); }; let addr1 = Address::from_bytes(ptr1.get(self)?)?; let addr2 = Address::from_bytes(ptr2.get(self)?)?; @@ -424,7 +430,9 @@ impl Evaluator<'_> { } "write" => { let [fd, ptr, len] = args else { - return Err(MirEvalError::TypeError("libc::write args are not provided")); + return Err(MirEvalError::InternalError( + "libc::write args are not provided".into(), + )); }; let fd = u128::from_le_bytes(pad16(fd.get(self)?, false)); let interval = Interval { @@ -446,14 +454,16 @@ impl Evaluator<'_> { "pthread_key_create" => { let key = self.thread_local_storage.create_key(); let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError("pthread_key_create arg0 is not provided")); + return Err(MirEvalError::InternalError( + "pthread_key_create arg0 is not provided".into(), + )); }; let arg0_addr = Address::from_bytes(arg0.get(self)?)?; let key_ty = if let Some((ty, ..)) = arg0.ty.as_reference_or_ptr() { ty } else { - return Err(MirEvalError::TypeError( - "pthread_key_create arg0 is not a pointer", + return Err(MirEvalError::InternalError( + "pthread_key_create arg0 is not a pointer".into(), )); }; let arg0_interval = Interval::new( @@ -467,8 +477,8 @@ impl Evaluator<'_> { } "pthread_getspecific" => { let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError( - "pthread_getspecific arg0 is not provided", + return Err(MirEvalError::InternalError( + "pthread_getspecific arg0 is not provided".into(), )); }; let key = from_bytes!(usize, &pad16(arg0.get(self)?, false)[0..8]); @@ -478,14 +488,14 @@ impl Evaluator<'_> { } "pthread_setspecific" => { let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError( - "pthread_setspecific arg0 is not provided", + return Err(MirEvalError::InternalError( + "pthread_setspecific arg0 is not provided".into(), )); }; let key = from_bytes!(usize, &pad16(arg0.get(self)?, false)[0..8]); let Some(arg1) = args.get(1) else { - return Err(MirEvalError::TypeError( - "pthread_setspecific arg1 is not provided", + return Err(MirEvalError::InternalError( + "pthread_setspecific arg1 is not provided".into(), )); }; let value = from_bytes!(u128, pad16(arg1.get(self)?, false)); @@ -502,14 +512,16 @@ impl Evaluator<'_> { } "syscall" => { let Some((id, rest)) = args.split_first() else { - return Err(MirEvalError::TypeError("syscall arg1 is not provided")); + return Err(MirEvalError::InternalError("syscall arg1 is not provided".into())); }; let id = from_bytes!(i64, id.get(self)?); self.exec_syscall(id, rest, destination, locals, span) } "sched_getaffinity" => { let [_pid, _set_size, set] = args else { - return Err(MirEvalError::TypeError("libc::write args are not provided")); + return Err(MirEvalError::InternalError( + "libc::write args are not provided".into(), + )); }; let set = Address::from_bytes(set.get(self)?)?; // Only enable core 0 (we are single threaded anyway), which is bitset 0x0000001 @@ -520,7 +532,9 @@ impl Evaluator<'_> { } "getenv" => { let [name] = args else { - return Err(MirEvalError::TypeError("libc::write args are not provided")); + return Err(MirEvalError::InternalError( + "libc::write args are not provided".into(), + )); }; let mut name_buf = vec![]; let name = { @@ -586,8 +600,8 @@ impl Evaluator<'_> { "sqrt" | "sin" | "cos" | "exp" | "exp2" | "log" | "log10" | "log2" | "fabs" | "floor" | "ceil" | "trunc" | "rint" | "nearbyint" | "round" | "roundeven" => { let [arg] = args else { - return Err(MirEvalError::TypeError( - "f64 intrinsic signature doesn't match fn (f64) -> f64", + return Err(MirEvalError::InternalError( + "f64 intrinsic signature doesn't match fn (f64) -> f64".into(), )); }; let arg = from_bytes!(f64, arg.get(self)?); @@ -614,8 +628,8 @@ impl Evaluator<'_> { } "pow" | "minnum" | "maxnum" | "copysign" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "f64 intrinsic signature doesn't match fn (f64, f64) -> f64", + return Err(MirEvalError::InternalError( + "f64 intrinsic signature doesn't match fn (f64, f64) -> f64".into(), )); }; let arg1 = from_bytes!(f64, arg1.get(self)?); @@ -630,8 +644,8 @@ impl Evaluator<'_> { } "powi" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "powif64 signature doesn't match fn (f64, i32) -> f64", + return Err(MirEvalError::InternalError( + "powif64 signature doesn't match fn (f64, i32) -> f64".into(), )); }; let arg1 = from_bytes!(f64, arg1.get(self)?); @@ -640,8 +654,8 @@ impl Evaluator<'_> { } "fma" => { let [arg1, arg2, arg3] = args else { - return Err(MirEvalError::TypeError( - "fmaf64 signature doesn't match fn (f64, f64, f64) -> f64", + return Err(MirEvalError::InternalError( + "fmaf64 signature doesn't match fn (f64, f64, f64) -> f64".into(), )); }; let arg1 = from_bytes!(f64, arg1.get(self)?); @@ -658,8 +672,8 @@ impl Evaluator<'_> { "sqrt" | "sin" | "cos" | "exp" | "exp2" | "log" | "log10" | "log2" | "fabs" | "floor" | "ceil" | "trunc" | "rint" | "nearbyint" | "round" | "roundeven" => { let [arg] = args else { - return Err(MirEvalError::TypeError( - "f32 intrinsic signature doesn't match fn (f32) -> f32", + return Err(MirEvalError::InternalError( + "f32 intrinsic signature doesn't match fn (f32) -> f32".into(), )); }; let arg = from_bytes!(f32, arg.get(self)?); @@ -686,8 +700,8 @@ impl Evaluator<'_> { } "pow" | "minnum" | "maxnum" | "copysign" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "f32 intrinsic signature doesn't match fn (f32, f32) -> f32", + return Err(MirEvalError::InternalError( + "f32 intrinsic signature doesn't match fn (f32, f32) -> f32".into(), )); }; let arg1 = from_bytes!(f32, arg1.get(self)?); @@ -702,8 +716,8 @@ impl Evaluator<'_> { } "powi" => { let [arg1, arg2] = args else { - return Err(MirEvalError::TypeError( - "powif32 signature doesn't match fn (f32, i32) -> f32", + return Err(MirEvalError::InternalError( + "powif32 signature doesn't match fn (f32, i32) -> f32".into(), )); }; let arg1 = from_bytes!(f32, arg1.get(self)?); @@ -712,8 +726,8 @@ impl Evaluator<'_> { } "fma" => { let [arg1, arg2, arg3] = args else { - return Err(MirEvalError::TypeError( - "fmaf32 signature doesn't match fn (f32, f32, f32) -> f32", + return Err(MirEvalError::InternalError( + "fmaf32 signature doesn't match fn (f32, f32, f32) -> f32".into(), )); }; let arg1 = from_bytes!(f32, arg1.get(self)?); @@ -730,7 +744,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("size_of generic arg is not provided")); + return Err(MirEvalError::InternalError( + "size_of generic arg is not provided".into(), + )); }; let size = self.size_of_sized(ty, locals, "size_of arg")?; destination.write_from_bytes(self, &size.to_le_bytes()[0..destination.size]) @@ -739,7 +755,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("align_of generic arg is not provided")); + return Err(MirEvalError::InternalError( + "align_of generic arg is not provided".into(), + )); }; let align = self.layout(ty)?.align.abi.bytes(); destination.write_from_bytes(self, &align.to_le_bytes()[0..destination.size]) @@ -748,10 +766,14 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("size_of_val generic arg is not provided")); + return Err(MirEvalError::InternalError( + "size_of_val generic arg is not provided".into(), + )); }; let [arg] = args else { - return Err(MirEvalError::TypeError("size_of_val args are not provided")); + return Err(MirEvalError::InternalError( + "size_of_val args are not provided".into(), + )); }; if let Some((size, _)) = self.size_align_of(ty, locals)? { destination.write_from_bytes(self, &size.to_le_bytes()) @@ -765,12 +787,14 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "min_align_of_val generic arg is not provided", + return Err(MirEvalError::InternalError( + "min_align_of_val generic arg is not provided".into(), )); }; let [arg] = args else { - return Err(MirEvalError::TypeError("min_align_of_val args are not provided")); + return Err(MirEvalError::InternalError( + "min_align_of_val args are not provided".into(), + )); }; if let Some((_, align)) = self.size_align_of(ty, locals)? { destination.write_from_bytes(self, &align.to_le_bytes()) @@ -784,7 +808,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("type_name generic arg is not provided")); + return Err(MirEvalError::InternalError( + "type_name generic arg is not provided".into(), + )); }; let ty_name = match ty.display_source_code( self.db, @@ -808,7 +834,9 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("size_of generic arg is not provided")); + return Err(MirEvalError::InternalError( + "size_of generic arg is not provided".into(), + )); }; let result = !ty.clone().is_copy(self.db, locals.body.owner); destination.write_from_bytes(self, &[u8::from(result)]) @@ -817,14 +845,18 @@ impl Evaluator<'_> { // FIXME: this is wrong for const eval, it should return 2 in some // cases. let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_add args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_add args are not provided".into(), + )); }; let ans = lhs.get(self)? == rhs.get(self)?; destination.write_from_bytes(self, &[u8::from(ans)]) } "saturating_add" | "saturating_sub" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("saturating_add args are not provided")); + return Err(MirEvalError::InternalError( + "saturating_add args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -844,7 +876,9 @@ impl Evaluator<'_> { } "wrapping_add" | "unchecked_add" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_add args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_add args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -853,7 +887,9 @@ impl Evaluator<'_> { } "ptr_offset_from_unsigned" | "ptr_offset_from" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_sub args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_sub args are not provided".into(), + )); }; let lhs = i128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = i128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -861,8 +897,8 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "ptr_offset_from generic arg is not provided", + return Err(MirEvalError::InternalError( + "ptr_offset_from generic arg is not provided".into(), )); }; let size = self.size_of_sized(ty, locals, "ptr_offset_from arg")? as i128; @@ -871,7 +907,9 @@ impl Evaluator<'_> { } "wrapping_sub" | "unchecked_sub" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_sub args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_sub args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -880,7 +918,9 @@ impl Evaluator<'_> { } "wrapping_mul" | "unchecked_mul" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("wrapping_mul args are not provided")); + return Err(MirEvalError::InternalError( + "wrapping_mul args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -890,7 +930,9 @@ impl Evaluator<'_> { "wrapping_shl" | "unchecked_shl" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_shl args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_shl args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -900,7 +942,9 @@ impl Evaluator<'_> { "wrapping_shr" | "unchecked_shr" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_shr args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_shr args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -910,7 +954,9 @@ impl Evaluator<'_> { "unchecked_rem" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_rem args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_rem args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -922,7 +968,9 @@ impl Evaluator<'_> { "unchecked_div" | "exact_div" => { // FIXME: signed let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("unchecked_div args are not provided")); + return Err(MirEvalError::InternalError( + "unchecked_div args are not provided".into(), + )); }; let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, false)); let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, false)); @@ -933,7 +981,9 @@ impl Evaluator<'_> { } "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("const_eval_select args are not provided")); + return Err(MirEvalError::InternalError( + "const_eval_select args are not provided".into(), + )); }; let result_ty = TyKind::Tuple( 2, @@ -954,7 +1004,7 @@ impl Evaluator<'_> { || ans.to_le_bytes()[op_size..].iter().any(|&it| it != 0 && it != 255); let is_overflow = vec![u8::from(is_overflow)]; let layout = self.layout(&result_ty)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, None, @@ -966,15 +1016,15 @@ impl Evaluator<'_> { } "copy" | "copy_nonoverlapping" => { let [src, dst, offset] = args else { - return Err(MirEvalError::TypeError( - "copy_nonoverlapping args are not provided", + return Err(MirEvalError::InternalError( + "copy_nonoverlapping args are not provided".into(), )); }; let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "copy_nonoverlapping generic arg is not provided", + return Err(MirEvalError::InternalError( + "copy_nonoverlapping generic arg is not provided".into(), )); }; let src = Address::from_bytes(src.get(self)?)?; @@ -988,18 +1038,22 @@ impl Evaluator<'_> { } "offset" | "arith_offset" => { let [ptr, offset] = args else { - return Err(MirEvalError::TypeError("offset args are not provided")); + return Err(MirEvalError::InternalError("offset args are not provided".into())); }; let ty = if name == "offset" { let Some(ty0) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("offset generic arg is not provided")); + return Err(MirEvalError::InternalError( + "offset generic arg is not provided".into(), + )); }; let Some(ty1) = generic_args.as_slice(Interner).get(1).and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("offset generic arg is not provided")); + return Err(MirEvalError::InternalError( + "offset generic arg is not provided".into(), + )); }; if !matches!( ty1.as_builtin(), @@ -1008,15 +1062,15 @@ impl Evaluator<'_> { | BuiltinType::Uint(BuiltinUint::Usize) ) ) { - return Err(MirEvalError::TypeError( - "offset generic arg is not usize or isize", + return Err(MirEvalError::InternalError( + "offset generic arg is not usize or isize".into(), )); } match ty0.as_raw_ptr() { Some((ty, _)) => ty, None => { - return Err(MirEvalError::TypeError( - "offset generic arg is not a raw pointer", + return Err(MirEvalError::InternalError( + "offset generic arg is not a raw pointer".into(), )); } } @@ -1024,8 +1078,8 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "arith_offset generic arg is not provided", + return Err(MirEvalError::InternalError( + "arith_offset generic arg is not provided".into(), )); }; ty @@ -1046,19 +1100,21 @@ impl Evaluator<'_> { } "transmute" => { let [arg] = args else { - return Err(MirEvalError::TypeError("transmute arg is not provided")); + return Err(MirEvalError::InternalError( + "transmute arg is not provided".into(), + )); }; destination.write_from_interval(self, arg.interval) } "likely" | "unlikely" => { let [arg] = args else { - return Err(MirEvalError::TypeError("likely arg is not provided")); + return Err(MirEvalError::InternalError("likely arg is not provided".into())); }; destination.write_from_interval(self, arg.interval) } "ctpop" => { let [arg] = args else { - return Err(MirEvalError::TypeError("ctpop arg is not provided")); + return Err(MirEvalError::InternalError("ctpop arg is not provided".into())); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).count_ones(); destination @@ -1066,7 +1122,7 @@ impl Evaluator<'_> { } "ctlz" | "ctlz_nonzero" => { let [arg] = args else { - return Err(MirEvalError::TypeError("ctlz arg is not provided")); + return Err(MirEvalError::InternalError("ctlz arg is not provided".into())); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).leading_zeros() as usize; @@ -1076,7 +1132,7 @@ impl Evaluator<'_> { } "cttz" | "cttz_nonzero" => { let [arg] = args else { - return Err(MirEvalError::TypeError("cttz arg is not provided")); + return Err(MirEvalError::InternalError("cttz arg is not provided".into())); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).trailing_zeros(); destination @@ -1084,7 +1140,9 @@ impl Evaluator<'_> { } "rotate_left" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("rotate_left args are not provided")); + return Err(MirEvalError::InternalError( + "rotate_left args are not provided".into(), + )); }; let lhs = &lhs.get(self)?[0..destination.size]; let rhs = rhs.get(self)?[0] as u32; @@ -1114,7 +1172,9 @@ impl Evaluator<'_> { } "rotate_right" => { let [lhs, rhs] = args else { - return Err(MirEvalError::TypeError("rotate_right args are not provided")); + return Err(MirEvalError::InternalError( + "rotate_right args are not provided".into(), + )); }; let lhs = &lhs.get(self)?[0..destination.size]; let rhs = rhs.get(self)?[0] as u32; @@ -1144,13 +1204,15 @@ impl Evaluator<'_> { } "discriminant_value" => { let [arg] = args else { - return Err(MirEvalError::TypeError("discriminant_value arg is not provided")); + return Err(MirEvalError::InternalError( + "discriminant_value arg is not provided".into(), + )); }; let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "discriminant_value generic arg is not provided", + return Err(MirEvalError::InternalError( + "discriminant_value generic arg is not provided".into(), )); }; let addr = Address::from_bytes(arg.get(self)?)?; @@ -1161,11 +1223,15 @@ impl Evaluator<'_> { } "const_eval_select" => { let [tuple, const_fn, _] = args else { - return Err(MirEvalError::TypeError("const_eval_select args are not provided")); + return Err(MirEvalError::InternalError( + "const_eval_select args are not provided".into(), + )); }; let mut args = vec![const_fn.clone()]; let TyKind::Tuple(_, fields) = tuple.ty.kind(Interner) else { - return Err(MirEvalError::TypeError("const_eval_select arg[0] is not a tuple")); + return Err(MirEvalError::InternalError( + "const_eval_select arg[0] is not a tuple".into(), + )); }; let layout = self.layout(&tuple.ty)?; for (i, field) in fields.iter(Interner).enumerate() { @@ -1196,21 +1262,25 @@ impl Evaluator<'_> { } "read_via_copy" | "volatile_load" => { let [arg] = args else { - return Err(MirEvalError::TypeError("read_via_copy args are not provided")); + return Err(MirEvalError::InternalError( + "read_via_copy args are not provided".into(), + )); }; let addr = Address::from_bytes(arg.interval.get(self)?)?; destination.write_from_interval(self, Interval { addr, size: destination.size }) } "write_via_move" => { let [ptr, val] = args else { - return Err(MirEvalError::TypeError("write_via_move args are not provided")); + return Err(MirEvalError::InternalError( + "write_via_move args are not provided".into(), + )); }; let dst = Address::from_bytes(ptr.get(self)?)?; let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError( - "write_via_copy generic arg is not provided", + return Err(MirEvalError::InternalError( + "write_via_copy generic arg is not provided".into(), )); }; let size = self.size_of_sized(ty, locals, "write_via_move ptr type")?; @@ -1219,14 +1289,18 @@ impl Evaluator<'_> { } "write_bytes" => { let [dst, val, count] = args else { - return Err(MirEvalError::TypeError("write_bytes args are not provided")); + return Err(MirEvalError::InternalError( + "write_bytes args are not provided".into(), + )); }; let count = from_bytes!(usize, count.get(self)?); let val = from_bytes!(u8, val.get(self)?); let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("write_bytes generic arg is not provided")); + return Err(MirEvalError::InternalError( + "write_bytes generic arg is not provided".into(), + )); }; let dst = Address::from_bytes(dst.get(self)?)?; let size = self.size_of_sized(ty, locals, "copy_nonoverlapping ptr type")?; @@ -1310,10 +1384,14 @@ impl Evaluator<'_> { let Some(ty) = generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("atomic intrinsic generic arg is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic generic arg is not provided".into(), + )); }; let Some(arg0) = args.first() else { - return Err(MirEvalError::TypeError("atomic intrinsic arg0 is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic arg0 is not provided".into(), + )); }; let arg0_addr = Address::from_bytes(arg0.get(self)?)?; let arg0_interval = @@ -1322,7 +1400,9 @@ impl Evaluator<'_> { return destination.write_from_interval(self, arg0_interval); } let Some(arg1) = args.get(1) else { - return Err(MirEvalError::TypeError("atomic intrinsic arg1 is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic arg1 is not provided".into(), + )); }; if name.starts_with("store_") { return arg0_interval.write_from_interval(self, arg1.interval); @@ -1374,7 +1454,9 @@ impl Evaluator<'_> { return arg0_interval.write_from_bytes(self, &ans.to_le_bytes()[0..destination.size]); } let Some(arg2) = args.get(2) else { - return Err(MirEvalError::TypeError("atomic intrinsic arg2 is not provided")); + return Err(MirEvalError::InternalError( + "atomic intrinsic arg2 is not provided".into(), + )); }; if name.starts_with("cxchg_") || name.starts_with("cxchgweak_") { let dest = if arg1.get(self)? == arg0_interval.get(self)? { @@ -1389,7 +1471,7 @@ impl Evaluator<'_> { ) .intern(Interner); let layout = self.layout(&result_ty)?; - let result = self.make_by_layout( + let result = self.construct_with_layout( layout.size.bytes_usize(), &layout, None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs index f9156417f249f..eddfd0acfb98c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -10,7 +10,7 @@ macro_rules! from_bytes { ($ty:tt, $value:expr) => { ($ty::from_le_bytes(match ($value).try_into() { Ok(it) => it, - Err(_) => return Err(MirEvalError::TypeError("mismatched size")), + Err(_) => return Err(MirEvalError::InternalError("mismatched size".into())), })) }; } @@ -40,7 +40,9 @@ impl Evaluator<'_> { .substitute(Interner, subst); return Ok((fields.len(), field_ty)); } - return Err(MirEvalError::TypeError("simd type with no len param")); + return Err(MirEvalError::InternalError( + "simd type with no len param".into(), + )); } }; match try_const_usize(self.db, len) { @@ -48,14 +50,18 @@ impl Evaluator<'_> { let Some(ty) = subst.as_slice(Interner).first().and_then(|it| it.ty(Interner)) else { - return Err(MirEvalError::TypeError("simd type with no ty param")); + return Err(MirEvalError::InternalError( + "simd type with no ty param".into(), + )); }; Ok((len as usize, ty.clone())) } - None => Err(MirEvalError::TypeError("simd type with unevaluatable len param")), + None => Err(MirEvalError::InternalError( + "simd type with unevaluatable len param".into(), + )), } } - _ => Err(MirEvalError::TypeError("simd type which is not a struct")), + _ => Err(MirEvalError::InternalError("simd type which is not a struct".into())), } } @@ -71,7 +77,9 @@ impl Evaluator<'_> { match name { "and" | "or" | "xor" => { let [left, right] = args else { - return Err(MirEvalError::TypeError("simd bit op args are not provided")); + return Err(MirEvalError::InternalError( + "simd bit op args are not provided".into(), + )); }; let result = left .get(self)? @@ -88,7 +96,7 @@ impl Evaluator<'_> { } "eq" | "ne" | "lt" | "le" | "gt" | "ge" => { let [left, right] = args else { - return Err(MirEvalError::TypeError("simd args are not provided")); + return Err(MirEvalError::InternalError("simd args are not provided".into())); }; let (len, ty) = self.detect_simd_ty(&left.ty)?; let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_))); @@ -125,7 +133,9 @@ impl Evaluator<'_> { } "bitmask" => { let [op] = args else { - return Err(MirEvalError::TypeError("simd_bitmask args are not provided")); + return Err(MirEvalError::InternalError( + "simd_bitmask args are not provided".into(), + )); }; let (op_len, _) = self.detect_simd_ty(&op.ty)?; let op_count = op.interval.size / op_len; @@ -139,18 +149,20 @@ impl Evaluator<'_> { } "shuffle" => { let [left, right, index] = args else { - return Err(MirEvalError::TypeError("simd_shuffle args are not provided")); + return Err(MirEvalError::InternalError( + "simd_shuffle args are not provided".into(), + )); }; let TyKind::Array(_, index_len) = index.ty.kind(Interner) else { - return Err(MirEvalError::TypeError( - "simd_shuffle index argument has non-array type", + return Err(MirEvalError::InternalError( + "simd_shuffle index argument has non-array type".into(), )); }; let index_len = match try_const_usize(self.db, index_len) { Some(it) => it as usize, None => { - return Err(MirEvalError::TypeError( - "simd type with unevaluatable len param", + return Err(MirEvalError::InternalError( + "simd type with unevaluatable len param".into(), )) } }; @@ -164,8 +176,8 @@ impl Evaluator<'_> { let val = match vector.clone().nth(index) { Some(it) => it, None => { - return Err(MirEvalError::TypeError( - "out of bound access in simd shuffle", + return Err(MirEvalError::InternalError( + "out of bound access in simd shuffle".into(), )) } }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 99930798e87ab..28d26c6c8ae6e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -97,7 +97,7 @@ pub enum MirLowerError { MutatingRvalue, UnresolvedLabel, UnresolvedUpvar(Place), - UnaccessableLocal, + InaccessibleLocal, // monomorphization errors: GenericArgNotProvided(TypeOrConstParamId, Substitution), @@ -116,7 +116,7 @@ impl DropScopeToken { ctx.pop_drop_scope_internal(current, span) } - /// It is useful when we want a drop scope is syntaxically closed, but we don't want to execute any drop + /// It is useful when we want a drop scope is syntactically closed, but we don't want to execute any drop /// code. Either when the control flow is diverging (so drop code doesn't reached) or when drop is handled /// for us (for example a block that ended with a return statement. Return will drop everything, so the block shouldn't /// do anything) @@ -186,7 +186,7 @@ impl MirLowerError { | MirLowerError::UnsizedTemporary(_) | MirLowerError::IncompleteExpr | MirLowerError::IncompletePattern - | MirLowerError::UnaccessableLocal + | MirLowerError::InaccessibleLocal | MirLowerError::TraitFunctionDefinition(_, _) | MirLowerError::UnresolvedName(_) | MirLowerError::RecordLiteralWithoutPath @@ -939,7 +939,7 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(Some(current)) } Expr::BinaryOp { lhs, rhs, op } => { - let op = op.ok_or(MirLowerError::IncompleteExpr)?; + let op: BinaryOp = op.ok_or(MirLowerError::IncompleteExpr)?; let is_builtin = 'b: { // Without adjust here is a hack. We assume that we know every possible adjustment // for binary operator, and use without adjust to simplify our conditions. @@ -1843,8 +1843,8 @@ impl<'ctx> MirLowerCtx<'ctx> { None => { // FIXME: It should never happens, but currently it will happen in `const_dependent_on_local` test, which // is a hir lowering problem IMO. - // never!("Using unaccessable local for binding is always a bug"); - Err(MirLowerError::UnaccessableLocal) + // never!("Using inaccessible local for binding is always a bug"); + Err(MirLowerError::InaccessibleLocal) } } } @@ -2068,7 +2068,7 @@ pub fn mir_body_for_closure_query( } pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result> { - let _p = profile::span("mir_body_query").detail(|| match def { + let detail = match def { DefWithBodyId::FunctionId(it) => db.function_data(it).name.display(db.upcast()).to_string(), DefWithBodyId::StaticId(it) => db.static_data(it).name.display(db.upcast()).to_string(), DefWithBodyId::ConstId(it) => db @@ -2082,7 +2082,8 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result format!("in type const {it:?}"), - }); + }; + let _p = tracing::span!(tracing::Level::INFO, "mir_body_query", ?detail).entered(); let body = db.body(def); let infer = db.infer(def); let mut result = lower_to_mir(db, def, &body, &infer, body.body_expr)?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 65ab12929dd2c..8202bac532f7a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -114,7 +114,7 @@ impl MirLowerCtx<'_> { index: i as u32, })) }), - &mut cond_place, + &cond_place, mode, )? } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index 671fd9ec3a451..9804910c878d4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -1,14 +1,14 @@ -mod never_type; mod coercion; +mod diagnostics; +mod display_source_code; +mod incremental; +mod macros; +mod method_resolution; +mod never_type; +mod patterns; mod regression; mod simple; -mod patterns; mod traits; -mod method_resolution; -mod macros; -mod display_source_code; -mod incremental; -mod diagnostics; use std::{collections::HashMap, env}; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs index e4756ee9e29b5..db14addaf185b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs @@ -3424,7 +3424,7 @@ fn bin_op_with_rhs_is_self_for_assoc_bound() { fn repro(t: T) -> bool where T: Request, - T::Output: Convertable, + T::Output: Convertible, { let a = execute(&t).convert(); let b = execute(&t).convert(); @@ -3439,7 +3439,7 @@ where { ::output() } -trait Convertable { +trait Convertible { type TraitSelf: PartialEq; type AssocAsDefaultSelf: PartialEq; fn convert(self) -> Self::AssocAsDefaultSelf; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index b6bc76bc98d53..3a1a4e63ea121 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -100,13 +100,14 @@ pub(crate) fn trait_solve_query( block: Option, goal: Canonical>, ) -> Option { - let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal.data(Interner) { + let detail = match &goal.value.goal.data(Interner) { GoalData::DomainGoal(DomainGoal::Holds(WhereClause::Implemented(it))) => { db.trait_data(it.hir_trait_id()).name.display(db.upcast()).to_string() } GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(_))) => "alias_eq".to_string(), _ => "??".to_string(), - }); + }; + let _p = tracing::span!(tracing::Level::INFO, "trait_solve_query", ?detail).entered(); tracing::info!("trait_solve_query({:?})", goal.value.goal); if let GoalData::DomainGoal(DomainGoal::Holds(WhereClause::AliasEq(AliasEq { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index 2cdee5a15a88a..c150314138ade 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs @@ -24,18 +24,18 @@ use hir_def::{ }; use hir_expand::name::Name; use intern::Interned; +use rustc_abi::TargetDataLayout; use rustc_hash::FxHashSet; use smallvec::{smallvec, SmallVec}; use stdx::never; -use triomphe::Arc; use crate::{ consteval::unknown_const, db::HirDatabase, layout::{Layout, TagEncoding}, mir::pad16, - ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitEnvironment, - TraitRef, TraitRefExt, Ty, WhereClause, + ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt, + Ty, WhereClause, }; pub(crate) fn fn_traits( @@ -192,7 +192,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { /// and it doesn't store the closure types and fields. /// /// Codes should not assume this ordering, and should always use methods available -/// on this struct for retriving, and `TyBuilder::substs_for_closure` for creating. +/// on this struct for retrieving, and `TyBuilder::substs_for_closure` for creating. pub(crate) struct ClosureSubst<'a>(pub(crate) &'a Substitution); impl<'a> ClosureSubst<'a> { @@ -431,18 +431,16 @@ impl FallibleTypeFolder for UnevaluatedConstEvaluatorFolder<'_> { pub(crate) fn detect_variant_from_bytes<'a>( layout: &'a Layout, db: &dyn HirDatabase, - trait_env: Arc, + target_data_layout: &TargetDataLayout, b: &[u8], e: EnumId, ) -> Option<(EnumVariantId, &'a Layout)> { - let krate = trait_env.krate; let (var_id, var_layout) = match &layout.variants { hir_def::layout::Variants::Single { index } => { (db.enum_data(e).variants[index.0].0, layout) } hir_def::layout::Variants::Multiple { tag, tag_encoding, variants, .. } => { - let target_data_layout = db.target_data_layout(krate)?; - let size = tag.size(&*target_data_layout).bytes_usize(); + let size = tag.size(target_data_layout).bytes_usize(); let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field let tag = i128::from_le_bytes(pad16(&b[offset..offset + size], false)); match tag_encoding { diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml index e4e4bcea6108d..7fea8372876ee 100644 --- a/src/tools/rust-analyzer/crates/hir/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml @@ -17,6 +17,7 @@ either.workspace = true arrayvec.workspace = true itertools.workspace = true smallvec.workspace = true +tracing.workspace = true triomphe.workspace = true once_cell = "1.17.1" @@ -30,9 +31,10 @@ profile.workspace = true stdx.workspace = true syntax.workspace = true tt.workspace = true +span.workspace = true [features] in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 7b9f895bc73eb..5c369f42e6e7d 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -2,7 +2,6 @@ use std::ops::ControlFlow; -use base_db::FileId; use hir_def::{ attr::AttrsWithOwner, item_scope::ItemInNs, @@ -11,12 +10,8 @@ use hir_def::{ resolver::{HasResolver, Resolver, TypeNs}, AssocItemId, AttrDefId, ModuleDefId, }; -use hir_expand::{ - name::Name, - span_map::{RealSpanMap, SpanMapRef}, -}; +use hir_expand::{mod_path::PathKind, name::Name}; use hir_ty::{db::HirDatabase, method_resolution}; -use syntax::{ast, AstNode}; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, @@ -129,7 +124,7 @@ fn resolve_doc_path_on_( AttrDefId::GenericParamId(_) => return None, }; - let mut modpath = modpath_from_str(db, link)?; + let mut modpath = modpath_from_str(link)?; let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath); if resolved.is_none() { @@ -244,10 +239,9 @@ fn resolve_impl_trait_item( ) -> Option { let canonical = ty.canonical(); let krate = ty.krate(db); - let environment = resolver.generic_def().map_or_else( - || crate::TraitEnvironment::empty(krate.id).into(), - |d| db.trait_environment(d), - ); + let environment = resolver + .generic_def() + .map_or_else(|| crate::TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); let traits_in_scope = resolver.traits_in_scope(db.upcast()); let mut result = None; @@ -302,37 +296,40 @@ fn as_module_def_if_namespace_matches( AssocItem::TypeAlias(it) => (ModuleDef::TypeAlias(it), Namespace::Types), }; - (ns.unwrap_or(expected_ns) == expected_ns).then(|| DocLinkDef::ModuleDef(def)) + (ns.unwrap_or(expected_ns) == expected_ns).then_some(DocLinkDef::ModuleDef(def)) } -fn modpath_from_str(db: &dyn HirDatabase, link: &str) -> Option { +fn modpath_from_str(link: &str) -> Option { // FIXME: this is not how we should get a mod path here. let try_get_modpath = |link: &str| { - let ast_path = ast::SourceFile::parse(&format!("type T = {link};")) - .syntax_node() - .descendants() - .find_map(ast::Path::cast)?; - if ast_path.syntax().text() != link { - return None; - } - ModPath::from_src( - db.upcast(), - ast_path, - SpanMapRef::RealSpanMap(&RealSpanMap::absolute(FileId::BOGUS)), - ) + let mut parts = link.split("::"); + let mut first_segment = None; + let kind = match parts.next()? { + "" => PathKind::Abs, + "crate" => PathKind::Crate, + "self" => PathKind::Super(0), + "super" => { + let mut deg = 1; + for segment in parts.by_ref() { + if segment == "super" { + deg += 1; + } else { + first_segment = Some(segment); + break; + } + } + PathKind::Super(deg) + } + segment => { + first_segment = Some(segment); + PathKind::Plain + } + }; + let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { + Ok(idx) => Name::new_tuple_field(idx), + Err(_) => Name::new_text_dont_use(segment.into()), + }); + Some(ModPath::from_segments(kind, parts)) }; - - let full = try_get_modpath(link); - if full.is_some() { - return full; - } - - // Tuple field names cannot be a part of `ModPath` usually, but rustdoc can - // resolve doc paths like `TupleStruct::0`. - // FIXME: Find a better way to handle these. - let (base, maybe_tuple_field) = link.rsplit_once("::")?; - let tuple_field = Name::new_tuple_field(maybe_tuple_field.parse().ok()?); - let mut modpath = try_get_modpath(base)?; - modpath.push_segment(tuple_field); - Some(modpath) + try_get_modpath(link) } diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index bf29a53913d1d..2d8f1dbad51a6 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -4,11 +4,12 @@ //! This probably isn't the best way to do this -- ideally, diagnostics should //! be expressed in terms of hir types themselves. pub use hir_ty::diagnostics::{CaseType, IncorrectCase}; +use hir_ty::{db::HirDatabase, diagnostics::BodyValidationDiagnostic, InferenceDiagnostic}; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use either::Either; -use hir_def::{path::ModPath, AssocItemId}; +use hir_def::{body::SyntheticSyntax, hir::ExprOrPatId, path::ModPath, AssocItemId, DefWithBodyId}; use hir_expand::{name::Name, HirFileId, InFile}; use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange}; @@ -30,14 +31,28 @@ macro_rules! diagnostics { )* }; } +// FIXME Accept something like the following in the macro call instead +// diagnostics![ +// pub struct BreakOutsideOfLoop { +// pub expr: InFile>, +// pub is_break: bool, +// pub bad_value_break: bool, +// }, ... +// or more concisely +// BreakOutsideOfLoop { +// expr: InFile>, +// is_break: bool, +// bad_value_break: bool, +// }, ... +// ] diagnostics![ BreakOutsideOfLoop, ExpectedFunction, InactiveCode, + IncoherentImpl, IncorrectCase, InvalidDeriveTarget, - IncoherentImpl, MacroDefError, MacroError, MacroExpansionParseError, @@ -55,8 +70,8 @@ diagnostics![ ReplaceFilterMapNextWithFindMap, TraitImplIncorrectSafety, TraitImplMissingAssocItems, - TraitImplRedundantAssocItems, TraitImplOrphan, + TraitImplRedundantAssocItems, TypedHole, TypeMismatch, UndeclaredLabel, @@ -326,3 +341,219 @@ pub struct TraitImplRedundantAssocItems { pub impl_: AstPtr, pub assoc_item: (Name, AssocItem), } + +impl AnyDiagnostic { + pub(crate) fn body_validation_diagnostic( + db: &dyn HirDatabase, + diagnostic: BodyValidationDiagnostic, + source_map: &hir_def::body::BodySourceMap, + ) -> Option { + match diagnostic { + BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => { + let variant_data = variant.variant_data(db.upcast()); + let missed_fields = missed_fields + .into_iter() + .map(|idx| variant_data.fields()[idx].name.clone()) + .collect(); + + match record { + Either::Left(record_expr) => match source_map.expr_syntax(record_expr) { + Ok(source_ptr) => { + let root = source_ptr.file_syntax(db.upcast()); + if let ast::Expr::RecordExpr(record_expr) = + source_ptr.value.to_node(&root) + { + if record_expr.record_expr_field_list().is_some() { + let field_list_parent_path = + record_expr.path().map(|path| AstPtr::new(&path)); + return Some( + MissingFields { + file: source_ptr.file_id, + field_list_parent: AstPtr::new(&Either::Left( + record_expr, + )), + field_list_parent_path, + missed_fields, + } + .into(), + ); + } + } + } + Err(SyntheticSyntax) => (), + }, + Either::Right(record_pat) => match source_map.pat_syntax(record_pat) { + Ok(source_ptr) => { + if let Some(ptr) = source_ptr.value.cast::() { + let root = source_ptr.file_syntax(db.upcast()); + let record_pat = ptr.to_node(&root); + if record_pat.record_pat_field_list().is_some() { + let field_list_parent_path = + record_pat.path().map(|path| AstPtr::new(&path)); + return Some( + MissingFields { + file: source_ptr.file_id, + field_list_parent: AstPtr::new(&Either::Right( + record_pat, + )), + field_list_parent_path, + missed_fields, + } + .into(), + ); + } + } + } + Err(SyntheticSyntax) => (), + }, + } + } + BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => { + if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) { + return Some( + ReplaceFilterMapNextWithFindMap { + file: next_source_ptr.file_id, + next_expr: next_source_ptr.value, + } + .into(), + ); + } + } + BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => { + match source_map.expr_syntax(match_expr) { + Ok(source_ptr) => { + let root = source_ptr.file_syntax(db.upcast()); + if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) { + match match_expr.expr() { + Some(scrut_expr) if match_expr.match_arm_list().is_some() => { + return Some( + MissingMatchArms { + scrutinee_expr: InFile::new( + source_ptr.file_id, + AstPtr::new(&scrut_expr), + ), + uncovered_patterns, + } + .into(), + ); + } + _ => {} + } + } + } + Err(SyntheticSyntax) => (), + } + } + } + None + } + + pub(crate) fn inference_diagnostic( + db: &dyn HirDatabase, + def: DefWithBodyId, + d: &InferenceDiagnostic, + source_map: &hir_def::body::BodySourceMap, + ) -> Option { + let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic"); + let pat_syntax = |pat| source_map.pat_syntax(pat).expect("unexpected synthetic"); + Some(match d { + &InferenceDiagnostic::NoSuchField { field: expr, private } => { + let expr_or_pat = match expr { + ExprOrPatId::ExprId(expr) => { + source_map.field_syntax(expr).map(AstPtr::wrap_left) + } + ExprOrPatId::PatId(pat) => { + source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) + } + }; + NoSuchField { field: expr_or_pat, private }.into() + } + &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { + MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }.into() + } + &InferenceDiagnostic::PrivateField { expr, field } => { + let expr = expr_syntax(expr); + let field = field.into(); + PrivateField { expr, field }.into() + } + &InferenceDiagnostic::PrivateAssocItem { id, item } => { + let expr_or_pat = match id { + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), + }; + let item = item.into(); + PrivateAssocItem { expr_or_pat, item }.into() + } + InferenceDiagnostic::ExpectedFunction { call_expr, found } => { + let call_expr = expr_syntax(*call_expr); + ExpectedFunction { call: call_expr, found: Type::new(db, def, found.clone()) } + .into() + } + InferenceDiagnostic::UnresolvedField { + expr, + receiver, + name, + method_with_same_name_exists, + } => { + let expr = expr_syntax(*expr); + UnresolvedField { + expr, + name: name.clone(), + receiver: Type::new(db, def, receiver.clone()), + method_with_same_name_exists: *method_with_same_name_exists, + } + .into() + } + InferenceDiagnostic::UnresolvedMethodCall { + expr, + receiver, + name, + field_with_same_name, + assoc_func_with_same_name, + } => { + let expr = expr_syntax(*expr); + UnresolvedMethodCall { + expr, + name: name.clone(), + receiver: Type::new(db, def, receiver.clone()), + field_with_same_name: field_with_same_name + .clone() + .map(|ty| Type::new(db, def, ty)), + assoc_func_with_same_name: *assoc_func_with_same_name, + } + .into() + } + &InferenceDiagnostic::UnresolvedAssocItem { id } => { + let expr_or_pat = match id { + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), + }; + UnresolvedAssocItem { expr_or_pat }.into() + } + &InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => { + let expr = expr_syntax(expr); + BreakOutsideOfLoop { expr, is_break, bad_value_break }.into() + } + InferenceDiagnostic::TypedHole { expr, expected } => { + let expr = expr_syntax(*expr); + TypedHole { expr, expected: Type::new(db, def, expected.clone()) }.into() + } + &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { + let expr_or_pat = match pat { + ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), + ExprOrPatId::PatId(pat) => { + let InFile { file_id, value } = + source_map.pat_syntax(pat).expect("unexpected synthetic"); + + // cast from Either -> Either<_, Pat> + let Some(ptr) = AstPtr::try_from_raw(value.syntax_node_ptr()) else { + return None; + }; + InFile { file_id, value: ptr } + } + }; + MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into() + } + }) + } +} diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index c50be5f11419d..1e21045e9818b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -24,12 +24,12 @@ mod semantics; mod source_analyzer; -mod from_id; mod attrs; +mod from_id; mod has_source; -pub mod diagnostics; pub mod db; +pub mod diagnostics; pub mod symbols; mod display; @@ -61,7 +61,7 @@ use hir_def::{ use hir_expand::{attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, MacroCallKind}; use hir_ty::{ all_super_traits, autoderef, check_orphan_rules, - consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt}, + consteval::{try_const_usize, unknown_const_as_generic, ConstExt}, diagnostics::BodyValidationDiagnostic, known_const_to_ast, layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding}, @@ -76,7 +76,6 @@ use hir_ty::{ }; use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; -use once_cell::unsync::Lazy; use rustc_hash::FxHashSet; use stdx::{impl_from, never}; use syntax::{ @@ -132,8 +131,10 @@ pub use { MacroFileIdExt, }, hir_ty::{ + consteval::ConstEvalError, display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, layout::LayoutError, + mir::{MirEvalError, MirLowerError}, PointerCast, Safety, }, // FIXME: Properly encapsulate mir @@ -234,8 +235,8 @@ impl Crate { db: &dyn DefDatabase, query: import_map::Query, ) -> impl Iterator> { - let _p = profile::span("query_external_importables"); - import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| { + let _p = tracing::span!(tracing::Level::INFO, "query_external_importables"); + import_map::search_dependencies(db, self.into(), &query).into_iter().map(|item| { match ItemInNs::from(item) { ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id), ItemInNs::Macros(mac_id) => Either::Right(mac_id), @@ -538,13 +539,8 @@ impl Module { /// Fills `acc` with the module's diagnostics. pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec) { - let _p = profile::span("Module::diagnostics").detail(|| { - format!( - "{:?}", - self.name(db) - .map_or("".into(), |name| name.display(db.upcast()).to_string()) - ) - }); + let name = self.name(db); + let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", ?name); let def_map = self.id.def_map(db.upcast()); for diag in def_map.diagnostics() { if diag.in_module != self.id.local_id { @@ -907,7 +903,7 @@ fn emit_def_diagnostic_( } DefDiagnosticKind::InvalidDeriveTarget { ast, id } => { let node = ast.to_node(db.upcast()); - let derive = node.attrs().nth(*id as usize); + let derive = node.attrs().nth(*id); match derive { Some(derive) => { acc.push( @@ -922,7 +918,7 @@ fn emit_def_diagnostic_( } DefDiagnosticKind::MalformedDerive { ast, id } => { let node = ast.to_node(db.upcast()); - let derive = node.attrs().nth(*id as usize); + let derive = node.attrs().nth(*id); match derive { Some(derive) => { acc.push( @@ -1592,181 +1588,43 @@ impl DefWithBody { } for diag in source_map.diagnostics() { - match diag { - BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push( - InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into(), - ), - BodyDiagnostic::MacroError { node, message } => acc.push( - MacroError { - node: (*node).map(|it| it.into()), - precise_location: None, - message: message.to_string(), - } - .into(), - ), - BodyDiagnostic::UnresolvedProcMacro { node, krate } => acc.push( - UnresolvedProcMacro { - node: (*node).map(|it| it.into()), - precise_location: None, - macro_name: None, - kind: MacroKind::ProcMacro, - krate: *krate, - } - .into(), - ), - BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push( - UnresolvedMacroCall { - macro_call: (*node).map(|ast_ptr| ast_ptr.into()), - precise_location: None, - path: path.clone(), - is_bang: true, - } - .into(), - ), + acc.push(match diag { + BodyDiagnostic::InactiveCode { node, cfg, opts } => { + InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into() + } + BodyDiagnostic::MacroError { node, message } => MacroError { + node: (*node).map(|it| it.into()), + precise_location: None, + message: message.to_string(), + } + .into(), + BodyDiagnostic::UnresolvedProcMacro { node, krate } => UnresolvedProcMacro { + node: (*node).map(|it| it.into()), + precise_location: None, + macro_name: None, + kind: MacroKind::ProcMacro, + krate: *krate, + } + .into(), + BodyDiagnostic::UnresolvedMacroCall { node, path } => UnresolvedMacroCall { + macro_call: (*node).map(|ast_ptr| ast_ptr.into()), + precise_location: None, + path: path.clone(), + is_bang: true, + } + .into(), BodyDiagnostic::UnreachableLabel { node, name } => { - acc.push(UnreachableLabel { node: *node, name: name.clone() }.into()) + UnreachableLabel { node: *node, name: name.clone() }.into() } BodyDiagnostic::UndeclaredLabel { node, name } => { - acc.push(UndeclaredLabel { node: *node, name: name.clone() }.into()) + UndeclaredLabel { node: *node, name: name.clone() }.into() } - } + }); } let infer = db.infer(self.into()); - let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1); - let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic"); - let pat_syntax = |pat| source_map.pat_syntax(pat).expect("unexpected synthetic"); for d in &infer.diagnostics { - match d { - &hir_ty::InferenceDiagnostic::NoSuchField { field: expr, private } => { - let expr_or_pat = match expr { - ExprOrPatId::ExprId(expr) => { - source_map.field_syntax(expr).map(AstPtr::wrap_left) - } - ExprOrPatId::PatId(pat) => { - source_map.pat_field_syntax(pat).map(AstPtr::wrap_right) - } - }; - acc.push(NoSuchField { field: expr_or_pat, private }.into()) - } - &hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { - acc.push( - MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found } - .into(), - ) - } - &hir_ty::InferenceDiagnostic::PrivateField { expr, field } => { - let expr = expr_syntax(expr); - let field = field.into(); - acc.push(PrivateField { expr, field }.into()) - } - &hir_ty::InferenceDiagnostic::PrivateAssocItem { id, item } => { - let expr_or_pat = match id { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), - ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), - }; - let item = item.into(); - acc.push(PrivateAssocItem { expr_or_pat, item }.into()) - } - hir_ty::InferenceDiagnostic::ExpectedFunction { call_expr, found } => { - let call_expr = expr_syntax(*call_expr); - - acc.push( - ExpectedFunction { - call: call_expr, - found: Type::new(db, DefWithBodyId::from(self), found.clone()), - } - .into(), - ) - } - hir_ty::InferenceDiagnostic::UnresolvedField { - expr, - receiver, - name, - method_with_same_name_exists, - } => { - let expr = expr_syntax(*expr); - - acc.push( - UnresolvedField { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - method_with_same_name_exists: *method_with_same_name_exists, - } - .into(), - ) - } - hir_ty::InferenceDiagnostic::UnresolvedMethodCall { - expr, - receiver, - name, - field_with_same_name, - assoc_func_with_same_name, - } => { - let expr = expr_syntax(*expr); - - acc.push( - UnresolvedMethodCall { - expr, - name: name.clone(), - receiver: Type::new(db, DefWithBodyId::from(self), receiver.clone()), - field_with_same_name: field_with_same_name - .clone() - .map(|ty| Type::new(db, DefWithBodyId::from(self), ty)), - assoc_func_with_same_name: *assoc_func_with_same_name, - } - .into(), - ) - } - &hir_ty::InferenceDiagnostic::UnresolvedAssocItem { id } => { - let expr_or_pat = match id { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), - ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), - }; - acc.push(UnresolvedAssocItem { expr_or_pat }.into()) - } - &hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { - expr, - is_break, - bad_value_break, - } => { - let expr = expr_syntax(expr); - acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into()) - } - hir_ty::InferenceDiagnostic::TypedHole { expr, expected } => { - let expr = expr_syntax(*expr); - acc.push( - TypedHole { - expr, - expected: Type::new(db, DefWithBodyId::from(self), expected.clone()), - } - .into(), - ) - } - &hir_ty::InferenceDiagnostic::MismatchedTupleStructPatArgCount { - pat, - expected, - found, - } => { - let expr_or_pat = match pat { - ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), - ExprOrPatId::PatId(pat) => { - let InFile { file_id, value } = - source_map.pat_syntax(pat).expect("unexpected synthetic"); - - // cast from Either -> Either<_, Pat> - let Some(ptr) = AstPtr::try_from_raw(value.syntax_node_ptr()) else { - continue; - }; - InFile { file_id, value: ptr } - } - }; - acc.push( - MismatchedTupleStructPatArgCount { expr_or_pat, expected, found }.into(), - ) - } - } + acc.extend(AnyDiagnostic::inference_diagnostic(db, self.into(), d, &source_map)); } for (pat_or_expr, mismatch) in infer.type_mismatches() { let expr_or_pat = match pat_or_expr { @@ -1805,8 +1663,6 @@ impl DefWithBody { } } - let hir_body = db.body(self.into()); - if let Ok(borrowck_results) = db.borrowck(self.into()) { for borrowck_result in borrowck_results.iter() { let mir_body = &borrowck_result.mir_body; @@ -1828,7 +1684,7 @@ impl DefWithBody { ) } let mol = &borrowck_result.mutability_of_locals; - for (binding_id, binding_data) in hir_body.bindings.iter() { + for (binding_id, binding_data) in body.bindings.iter() { if binding_data.problems.is_some() { // We should report specific diagnostics for these problems, not `need-mut` and `unused-mut`. continue; @@ -1890,109 +1746,7 @@ impl DefWithBody { } for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) { - match diagnostic { - BodyValidationDiagnostic::RecordMissingFields { - record, - variant, - missed_fields, - } => { - let variant_data = variant.variant_data(db.upcast()); - let missed_fields = missed_fields - .into_iter() - .map(|idx| variant_data.fields()[idx].name.clone()) - .collect(); - - match record { - Either::Left(record_expr) => match source_map.expr_syntax(record_expr) { - Ok(source_ptr) => { - let root = source_ptr.file_syntax(db.upcast()); - if let ast::Expr::RecordExpr(record_expr) = - source_ptr.value.to_node(&root) - { - if record_expr.record_expr_field_list().is_some() { - let field_list_parent_path = - record_expr.path().map(|path| AstPtr::new(&path)); - acc.push( - MissingFields { - file: source_ptr.file_id, - field_list_parent: AstPtr::new(&Either::Left( - record_expr, - )), - field_list_parent_path, - missed_fields, - } - .into(), - ) - } - } - } - Err(SyntheticSyntax) => (), - }, - Either::Right(record_pat) => match source_map.pat_syntax(record_pat) { - Ok(source_ptr) => { - if let Some(ptr) = source_ptr.value.cast::() { - let root = source_ptr.file_syntax(db.upcast()); - let record_pat = ptr.to_node(&root); - if record_pat.record_pat_field_list().is_some() { - let field_list_parent_path = - record_pat.path().map(|path| AstPtr::new(&path)); - acc.push( - MissingFields { - file: source_ptr.file_id, - field_list_parent: AstPtr::new(&Either::Right( - record_pat, - )), - field_list_parent_path, - missed_fields, - } - .into(), - ) - } - } - } - Err(SyntheticSyntax) => (), - }, - } - } - BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => { - if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) { - acc.push( - ReplaceFilterMapNextWithFindMap { - file: next_source_ptr.file_id, - next_expr: next_source_ptr.value, - } - .into(), - ); - } - } - BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => { - match source_map.expr_syntax(match_expr) { - Ok(source_ptr) => { - let root = source_ptr.file_syntax(db.upcast()); - if let ast::Expr::MatchExpr(match_expr) = - &source_ptr.value.to_node(&root) - { - match match_expr.expr() { - Some(scrut_expr) if match_expr.match_arm_list().is_some() => { - acc.push( - MissingMatchArms { - scrutinee_expr: InFile::new( - source_ptr.file_id, - AstPtr::new(&scrut_expr), - ), - uncovered_patterns, - } - .into(), - ); - } - _ => {} - } - } - } - Err(SyntheticSyntax) => (), - } - } - } + acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map)); } let def: ModuleDef = match self { @@ -2008,7 +1762,6 @@ impl DefWithBody { } } } - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Function { pub(crate) id: FunctionId, @@ -4299,7 +4052,7 @@ impl Type { name: Option<&Name>, mut callback: impl FnMut(Function) -> Option, ) -> Option { - let _p = profile::span("iterate_method_candidates"); + let _p = tracing::span!(tracing::Level::INFO, "iterate_method_candidates"); let mut slot = None; self.iterate_method_candidates_dyn( @@ -4378,7 +4131,7 @@ impl Type { name: Option<&Name>, mut callback: impl FnMut(AssocItem) -> Option, ) -> Option { - let _p = profile::span("iterate_path_candidates"); + let _p = tracing::span!(tracing::Level::INFO, "iterate_path_candidates"); let mut slot = None; self.iterate_path_candidates_dyn( db, @@ -4444,7 +4197,7 @@ impl Type { &'a self, db: &'a dyn HirDatabase, ) -> impl Iterator + 'a { - let _p = profile::span("applicable_inherent_traits"); + let _p = tracing::span!(tracing::Level::INFO, "applicable_inherent_traits"); self.autoderef_(db) .filter_map(|ty| ty.dyn_trait()) .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) @@ -4452,7 +4205,7 @@ impl Type { } pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator + 'a { - let _p = profile::span("env_traits"); + let _p = tracing::span!(tracing::Level::INFO, "env_traits"); self.autoderef_(db) .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_))) .flat_map(|ty| { diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index fdb94a6d5a74d..a869029d09663 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -25,6 +25,7 @@ use hir_expand::{ use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::{smallvec, SmallVec}; +use span::{Span, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use stdx::TupleExt; use syntax::{ algo::skip_trivia_token, @@ -131,6 +132,7 @@ pub struct SemanticsImpl<'db> { /// Rootnode to HirFileId cache cache: RefCell>, // These 2 caches are mainly useful for semantic highlighting as nothing else descends a lot of tokens + // So we might wanna move them out into something specific for semantic highlighting expansion_info_cache: RefCell>, /// MacroCall to its expansion's MacroFileId cache macro_call_cache: RefCell, MacroFileId>>, @@ -607,29 +609,102 @@ impl<'db> SemanticsImpl<'db> { res } - fn descend_into_macros_impl( + // return: + // SourceAnalyzer(file_id that original call include!) + // macro file id + // token in include! macro mapped from token in params + // span for the mapped token + fn is_from_include_file( &self, token: SyntaxToken, - f: &mut dyn FnMut(InFile) -> ControlFlow<()>, - ) { - let _p = profile::span("descend_into_macros"); - let sa = match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) { - Some(it) => it, - None => return, - }; + ) -> Option<(SourceAnalyzer, HirFileId, SyntaxToken, Span)> { + let parent = token.parent()?; + let file_id = self.find_file(&parent).file_id.file_id()?; + + let mut cache = self.expansion_info_cache.borrow_mut(); + + // iterate related crates and find all include! invocations that include_file_id matches + for (invoc, _) in self + .db + .relevant_crates(file_id) + .iter() + .flat_map(|krate| self.db.include_macro_invoc(*krate)) + .filter(|&(_, include_file_id)| include_file_id == file_id) + { + let macro_file = invoc.as_macro_file(); + let expansion_info = cache + .entry(macro_file) + .or_insert_with(|| macro_file.expansion_info(self.db.upcast())); - let span = match sa.file_id.file_id() { - Some(file_id) => self.db.real_span_map(file_id).span_for_range(token.text_range()), - None => { - stdx::never!(); - return; + // Create the source analyzer for the macro call scope + let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file())) + else { + continue; + }; + { + let InMacroFile { file_id: macro_file, value } = expansion_info.expanded(); + self.cache(value, macro_file.into()); } - }; + + // get mapped token in the include! macro file + let span = span::SpanData { + range: token.text_range(), + anchor: span::SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID }, + ctx: SyntaxContextId::ROOT, + }; + let Some(InMacroFile { file_id, value: mut mapped_tokens }) = + expansion_info.map_range_down(span) + else { + continue; + }; + + // if we find one, then return + if let Some(t) = mapped_tokens.next() { + return Some((sa, file_id.into(), t, span)); + } + } + + None + } + + fn descend_into_macros_impl( + &self, + mut token: SyntaxToken, + f: &mut dyn FnMut(InFile) -> ControlFlow<()>, + ) { + let _p = tracing::span!(tracing::Level::INFO, "descend_into_macros"); + let (sa, span, file_id) = + match token.parent().and_then(|parent| self.analyze_no_infer(&parent)) { + Some(sa) => match sa.file_id.file_id() { + Some(file_id) => ( + sa, + self.db.real_span_map(file_id).span_for_range(token.text_range()), + file_id.into(), + ), + None => { + stdx::never!(); + return; + } + }, + None => { + // if we cannot find a source analyzer for this token, then we try to find out + // whether this file is an included file and treat that as the include input + let Some((it, macro_file_id, mapped_token, s)) = + self.is_from_include_file(token) + else { + return; + }; + token = mapped_token; + (it, s, macro_file_id) + } + }; let mut cache = self.expansion_info_cache.borrow_mut(); let mut mcache = self.macro_call_cache.borrow_mut(); let def_map = sa.resolver.def_map(); + let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![(file_id, smallvec![token])]; + let mut process_expansion_for_token = |stack: &mut Vec<_>, macro_file| { let expansion_info = cache .entry(macro_file) @@ -651,8 +726,6 @@ impl<'db> SemanticsImpl<'db> { res }; - let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![(sa.file_id, smallvec![token])]; - while let Some((file_id, mut tokens)) = stack.pop() { while let Some(token) = tokens.pop() { let was_not_remapped = (|| { @@ -1222,7 +1295,7 @@ impl<'db> SemanticsImpl<'db> { offset: Option, infer_body: bool, ) -> Option { - let _p = profile::span("Semantics::analyze_impl"); + let _p = tracing::span!(tracing::Level::INFO, "Semantics::analyze_impl"); let node = self.find_file(node); let container = self.with_ctx(|ctx| ctx.find_container(node))?; diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index f60b3749b0805..14dbe6924032f 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -117,7 +117,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> { impl SourceToDefCtx<'_, '_> { pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> { - let _p = profile::span("SourceBinder::to_module_def"); + let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::to_module_def"); let mut mods = SmallVec::new(); for &crate_id in self.db.relevant_crates(file).iter() { // FIXME: inner items @@ -132,7 +132,7 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn module_to_def(&self, src: InFile) -> Option { - let _p = profile::span("module_to_def"); + let _p = tracing::span!(tracing::Level::INFO, "module_to_def"); let parent_declaration = src .syntax() .ancestors_with_macros_skip_attr_item(self.db.upcast()) @@ -153,7 +153,7 @@ impl SourceToDefCtx<'_, '_> { } pub(super) fn source_file_to_def(&self, src: InFile) -> Option { - let _p = profile::span("source_file_to_def"); + let _p = tracing::span!(tracing::Level::INFO, "source_file_to_def"); let file_id = src.file_id.original_file(self.db.upcast()); self.file_to_def(file_id).first().copied() } diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml index 4d4bac5fb9664..98961a18de257 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml @@ -17,6 +17,7 @@ cov-mark = "2.0.0-pre.1" itertools.workspace = true either.workspace = true smallvec.workspace = true +tracing.workspace = true # local deps stdx.workspace = true @@ -38,4 +39,4 @@ sourcegen.workspace = true in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 410c623109ea0..c1b95bb1e253e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -105,7 +105,7 @@ fn add_missing_impl_members_inner( assist_id: &'static str, label: &'static str, ) -> Option<()> { - let _p = profile::span("add_missing_impl_members_inner"); + let _p = tracing::span!(tracing::Level::INFO, "add_missing_impl_members_inner"); let impl_def = ctx.find_node_at_offset::()?; let impl_ = ctx.sema.to_def(&impl_def)?; @@ -370,17 +370,17 @@ impl Foo for S { add_missing_impl_members, r#" pub trait Trait<'a, 'b, A, B, C> { - fn foo(&self, one: &'a A, anoter: &'b B) -> &'a C; + fn foo(&self, one: &'a A, another: &'b B) -> &'a C; } impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () {$0}"#, r#" pub trait Trait<'a, 'b, A, B, C> { - fn foo(&self, one: &'a A, anoter: &'b B) -> &'a C; + fn foo(&self, one: &'a A, another: &'b B) -> &'a C; } impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () { - fn foo(&self, one: &'x T, anoter: &'y V) -> &'x U { + fn foo(&self, one: &'x T, another: &'y V) -> &'x U { ${0:todo!()} } }"#, @@ -393,7 +393,7 @@ impl<'x, 'y, T, V, U> Trait<'x, 'y, T, V, U> for () { add_missing_default_members, r#" pub trait Trait<'a, 'b, A, B, C: Default> { - fn foo(&self, _one: &'a A, _anoter: &'b B) -> (C, &'a i32) { + fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) { let value: &'a i32 = &0; (C::default(), value) } @@ -402,14 +402,14 @@ pub trait Trait<'a, 'b, A, B, C: Default> { impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () {$0}"#, r#" pub trait Trait<'a, 'b, A, B, C: Default> { - fn foo(&self, _one: &'a A, _anoter: &'b B) -> (C, &'a i32) { + fn foo(&self, _one: &'a A, _another: &'b B) -> (C, &'a i32) { let value: &'a i32 = &0; (C::default(), value) } } impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () { - $0fn foo(&self, _one: &'x T, _anoter: &'y V) -> (U, &'x i32) { + $0fn foo(&self, _one: &'x T, _another: &'y V) -> (U, &'x i32) { let value: &'x i32 = &0; (::default(), value) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 0f23b69908d6c..22d16cf6b36e4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -163,7 +163,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op block } else { // `expr_replace` is a descendant of `to_wrap`, so both steps need to be - // handled seperately, otherwise we wrap the wrong expression + // handled separately, otherwise we wrap the wrong expression let to_wrap = edit.make_mut(to_wrap); // Replace the target expr first so that we don't need to find where diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs index 7e4f140a28faa..dc27af5cbed20 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs @@ -418,7 +418,7 @@ where } #[test] - fn new_function_with_generics_and_wheres() { + fn new_function_with_generics_and_where() { check_assist( generate_default_from_new, r#" diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs index 154a1f59c722c..898bd01291a25 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs @@ -295,7 +295,7 @@ fn generate_impl( // those in strukt. // // These generics parameters will also be used in `field_ty` and - // `where_clauses`, so we should substitude arguments in them as well. + // `where_clauses`, so we should substitute arguments in them as well. let strukt_params = resolve_name_conflicts(strukt_params, &old_impl_params); let (field_ty, ty_where_clause) = match &strukt_params { Some(strukt_params) => { @@ -491,7 +491,7 @@ fn remove_useless_where_clauses(trait_ty: &ast::Type, self_ty: &ast::Type, wc: a // Generate generic args that should be apply to current impl. // -// For exmaple, say we have implementation `impl Trait for B`, +// For example, say we have implementation `impl Trait for B`, // and `b: B` in struct `S`. Then the `A` should be instantiated to `T`. // While the last two generic args `B` and `C` doesn't change, it remains // ``. So we apply `` as generic arguments to impl. @@ -637,7 +637,7 @@ fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> Option let path_expr_segment = make::path_from_text(item.name()?.to_string().as_str()); // We want rhs of the const assignment to be a qualified path - // The general case for const assigment can be found [here](`https://doc.rust-lang.org/reference/items/constant-items.html`) + // The general case for const assignment can be found [here](`https://doc.rust-lang.org/reference/items/constant-items.html`) // The qualified will have the following generic syntax : // >::ConstName; // FIXME : We can't rely on `make::path_qualified` for now but it would be nice to replace the following with it. @@ -779,7 +779,7 @@ impl Trait for Base {} #[test] fn test_self_ty() { - // trait whith `Self` type cannot be delegated + // trait with `Self` type cannot be delegated // // See the function `fn f() -> Self`. // It should be `fn f() -> Base` in `Base`, and `fn f() -> S` in `S` diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs index d90d366ffe4c4..91eaa96b6cb0d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_mut_trait_impl.rs @@ -6,7 +6,7 @@ use syntax::{ use crate::{AssistContext, AssistId, AssistKind, Assists}; -// FIXME: Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredicable case [#15581]. +// FIXME: Generate proper `index_mut` method body refer to `index` method body may impossible due to the unpredictable case [#15581]. // Here just leave the `index_mut` method body be same as `index` method body, user can modify it manually to meet their need. // Assist: generate_mut_trait_impl diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs index a8817436ba1fc..8881aa69f29d3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_trait_from_impl.rs @@ -183,7 +183,7 @@ fn remove_items_visibility(item: &ast::AssocItem) { fn strip_body(item: &ast::AssocItem) { if let ast::AssocItem::Fn(f) = item { if let Some(body) = f.body() { - // In constrast to function bodies, we want to see no ws before a semicolon. + // In contrast to function bodies, we want to see no ws before a semicolon. // So let's remove them if we see any. if let Some(prev) = body.syntax().prev_sibling_or_token() { if prev.kind() == SyntaxKind::WHITESPACE { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs index 965e4aa786e7a..f7da88b2c1838 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/into_to_qualified_from.rs @@ -120,7 +120,7 @@ fn main() -> () { } #[test] - fn fromed_in_child_mod_imported() { + fn from_in_child_mod_imported() { check_assist( into_to_qualified_from, r#" @@ -168,7 +168,7 @@ fn main() -> () { } #[test] - fn fromed_in_child_mod_not_imported() { + fn from_in_child_mod_not_imported() { check_assist( into_to_qualified_from, r#" diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs index 2beab26dce738..797c5c0653321 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_imports.rs @@ -1,8 +1,9 @@ use either::Either; use ide_db::imports::{ insert_use::{ImportGranularity, InsertUseConfig}, - merge_imports::{try_merge_imports, try_merge_trees, MergeBehavior}, + merge_imports::{try_merge_imports, try_merge_trees, try_normalize_use_tree, MergeBehavior}, }; +use itertools::Itertools; use syntax::{ algo::neighbor, ast::{self, edit_in_place::Removable}, @@ -32,24 +33,13 @@ use Edit::*; pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let (target, edits) = if ctx.has_empty_selection() { // Merge a neighbor - let mut tree: ast::UseTree = ctx.find_node_at_offset()?; - if ctx.config.insert_use.granularity == ImportGranularity::One - && tree.parent_use_tree_list().is_some() - { - cov_mark::hit!(resolve_top_use_tree_for_import_one); - tree = tree.top_use_tree(); - } + cov_mark::hit!(merge_with_use_item_neighbors); + let tree = ctx.find_node_at_offset::()?.top_use_tree(); let target = tree.syntax().text_range(); - let edits = if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) { - cov_mark::hit!(merge_with_use_item_neighbors); - let mut neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir)).into_iter(); - use_item.try_merge_from(&mut neighbor, &ctx.config.insert_use) - } else { - cov_mark::hit!(merge_with_use_tree_neighbors); - let mut neighbor = next_prev().find_map(|dir| neighbor(&tree, dir)).into_iter(); - tree.clone().try_merge_from(&mut neighbor, &ctx.config.insert_use) - }; + let use_item = tree.syntax().parent().and_then(ast::Use::cast)?; + let mut neighbor = next_prev().find_map(|dir| neighbor(&use_item, dir)).into_iter(); + let edits = use_item.try_merge_from(&mut neighbor, &ctx.config.insert_use); (target, edits?) } else { // Merge selected @@ -94,7 +84,35 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio for edit in edits_mut { match edit { Remove(it) => it.as_ref().either(Removable::remove, Removable::remove), - Replace(old, new) => ted::replace(old, new), + Replace(old, new) => { + ted::replace(old, &new); + + // If there's a selection and we're replacing a use tree in a tree list, + // normalize the parent use tree if it only contains the merged subtree. + if !ctx.has_empty_selection() { + let normalized_use_tree = ast::UseTree::cast(new) + .as_ref() + .and_then(ast::UseTree::parent_use_tree_list) + .and_then(|use_tree_list| { + if use_tree_list.use_trees().collect_tuple::<(_,)>().is_some() { + Some(use_tree_list.parent_use_tree()) + } else { + None + } + }) + .and_then(|target_tree| { + try_normalize_use_tree( + &target_tree, + ctx.config.insert_use.granularity.into(), + ) + .map(|top_use_tree_flat| (target_tree, top_use_tree_flat)) + }); + if let Some((old_tree, new_tree)) = normalized_use_tree { + cov_mark::hit!(replace_parent_with_normalized_use_tree); + ted::replace(old_tree.syntax(), new_tree.syntax()); + } + } + } } } }, @@ -201,20 +219,17 @@ use std::fmt$0::{Display, Debug}; use std::fmt::{Display, Debug}; ", r" -use std::fmt::{Display, Debug}; +use std::fmt::{Debug, Display}; ", ); // The assist macro below calls `check_assist_import_one` 4 times with different input - // use item variations based on the first 2 input parameters, but only 2 calls - // contain `use {std::fmt$0::{Display, Debug}};` for which the top use tree will need - // to be resolved. - cov_mark::check_count!(resolve_top_use_tree_for_import_one, 2); + // use item variations based on the first 2 input parameters. cov_mark::check_count!(merge_with_use_item_neighbors, 4); check_assist_import_one_variations!( "std::fmt$0::{Display, Debug}", "std::fmt::{Display, Debug}", - "use {std::fmt::{Display, Debug}};" + "use {std::fmt::{Debug, Display}};" ); } @@ -257,7 +272,7 @@ use std::fmt::{Debug, Display}; } #[test] - fn merge_self1() { + fn merge_self() { check_assist( merge_imports, r" @@ -276,21 +291,8 @@ use std::fmt::{self, Display}; } #[test] - fn merge_self2() { - check_assist( - merge_imports, - r" -use std::{fmt, $0fmt::Display}; -", - r" -use std::{fmt::{self, Display}}; -", - ); - } - - #[test] - fn not_applicable_to_single_one_style_import() { - cov_mark::check!(resolve_top_use_tree_for_import_one); + fn not_applicable_to_single_import() { + check_assist_not_applicable(merge_imports, "use std::{fmt, $0fmt::Display};"); check_assist_not_applicable_for_import_one( merge_imports, "use {std::{fmt, $0fmt::Display}};", @@ -385,14 +387,14 @@ pub(in this::path) use std::fmt::{Debug, Display}; #[test] fn test_merge_nested() { - cov_mark::check!(merge_with_use_tree_neighbors); check_assist( merge_imports, r" -use std::{fmt$0::Debug, fmt::Display}; +use std::{fmt$0::Debug, fmt::Error}; +use std::{fmt::Write, fmt::Display}; ", r" -use std::{fmt::{Debug, Display}}; +use std::fmt::{Debug, Display, Error, Write}; ", ); } @@ -402,10 +404,11 @@ use std::{fmt::{Debug, Display}}; check_assist( merge_imports, r" -use std::{fmt::Debug, fmt$0::Display}; +use std::{fmt::Debug, fmt$0::Error}; +use std::{fmt::Write, fmt::Display}; ", r" -use std::{fmt::{Debug, Display}}; +use std::fmt::{Debug, Display, Error, Write}; ", ); } @@ -419,13 +422,13 @@ use std$0::{fmt::{Write, Display}}; use std::{fmt::{self, Debug}}; ", r" -use std::{fmt::{self, Debug, Display, Write}}; +use std::fmt::{self, Debug, Display, Write}; ", ); check_assist_import_one_variations!( "std$0::{fmt::{Write, Display}}", "std::{fmt::{self, Debug}}", - "use {std::{fmt::{self, Debug, Display, Write}}};" + "use {std::fmt::{self, Debug, Display, Write}};" ); } @@ -438,26 +441,13 @@ use std$0::{fmt::{self, Debug}}; use std::{fmt::{Write, Display}}; ", r" -use std::{fmt::{self, Debug, Display, Write}}; +use std::fmt::{self, Debug, Display, Write}; ", ); check_assist_import_one_variations!( "std$0::{fmt::{self, Debug}}", "std::{fmt::{Write, Display}}", - "use {std::{fmt::{self, Debug, Display, Write}}};" - ); - } - - #[test] - fn test_merge_self_with_nested_self_item() { - check_assist( - merge_imports, - r" -use std::{fmt$0::{self, Debug}, fmt::{Write, Display}}; -", - r" -use std::{fmt::{self, Debug, Display, Write}}; -", + "use {std::fmt::{self, Debug, Display, Write}};" ); } @@ -470,13 +460,13 @@ use foo::$0{bar::{self}}; use foo::{bar}; ", r" -use foo::{bar::{self}}; +use foo::bar; ", ); check_assist_import_one_variations!( "foo::$0{bar::{self}}", "foo::{bar}", - "use {foo::{bar::{self}}};" + "use {foo::bar};" ); } @@ -489,13 +479,13 @@ use foo::$0{bar}; use foo::{bar::{self}}; ", r" -use foo::{bar::{self}}; +use foo::bar; ", ); check_assist_import_one_variations!( "foo::$0{bar}", "foo::{bar::{self}}", - "use {foo::{bar::{self}}};" + "use {foo::bar};" ); } @@ -508,13 +498,13 @@ use std$0::{fmt::*}; use std::{fmt::{self, Display}}; ", r" -use std::{fmt::{self, Display, *}}; +use std::fmt::{self, Display, *}; ", ); check_assist_import_one_variations!( "std$0::{fmt::*}", "std::{fmt::{self, Display}}", - "use {std::{fmt::{self, Display, *}}};" + "use {std::fmt::{self, Display, *}};" ); } @@ -579,29 +569,27 @@ use foo::{bar, baz}; check_assist( merge_imports, r" -use { - foo$0::bar, - foo::baz, +use foo$0::{ + bar, baz, }; +use foo::qux; ", r" -use { - foo::{bar, baz}, +use foo::{ + bar, baz, qux, }; ", ); check_assist( merge_imports, r" -use { - foo::baz, - foo$0::bar, +use foo::{ + baz, bar, }; +use foo$0::qux; ", r" -use { - foo::{bar, baz}, -}; +use foo::{bar, baz, qux}; ", ); } @@ -711,12 +699,19 @@ use std::{ };", ); - // FIXME: Remove redundant braces. See also unnecessary-braces diagnostic. cov_mark::check!(merge_with_selected_use_tree_neighbors); + check_assist( + merge_imports, + r"use std::{fmt::Result, $0fmt::Display, fmt::Debug$0};", + r"use std::{fmt::Result, fmt::{Debug, Display}};", + ); + + cov_mark::check!(merge_with_selected_use_tree_neighbors); + cov_mark::check!(replace_parent_with_normalized_use_tree); check_assist( merge_imports, r"use std::$0{fmt::Display, fmt::Debug}$0;", - r"use std::{fmt::{Debug, Display}};", + r"use std::fmt::{Debug, Display};", ); } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs new file mode 100644 index 0000000000000..7d003efe721d1 --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/normalize_import.rs @@ -0,0 +1,219 @@ +use ide_db::imports::merge_imports::try_normalize_import; +use syntax::{ast, AstNode}; + +use crate::{ + assist_context::{AssistContext, Assists}, + AssistId, AssistKind, +}; + +// Assist: normalize_import +// +// Normalizes an import. +// +// ``` +// use$0 std::{io, {fmt::Formatter}}; +// ``` +// -> +// ``` +// use std::{fmt::Formatter, io}; +// ``` +pub(crate) fn normalize_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let use_item = if ctx.has_empty_selection() { + ctx.find_node_at_offset()? + } else { + ctx.covering_element().ancestors().find_map(ast::Use::cast)? + }; + + let target = use_item.syntax().text_range(); + let normalized_use_item = + try_normalize_import(&use_item, ctx.config.insert_use.granularity.into())?; + + acc.add( + AssistId("normalize_import", AssistKind::RefactorRewrite), + "Normalize import", + target, + |builder| { + builder.replace_ast(use_item, normalized_use_item); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{ + check_assist, check_assist_import_one, check_assist_not_applicable, + check_assist_not_applicable_for_import_one, + }; + + use super::*; + + macro_rules! check_assist_variations { + ($fixture: literal, $expected: literal) => { + check_assist( + normalize_import, + concat!("use $0", $fixture, ";"), + concat!("use ", $expected, ";"), + ); + check_assist( + normalize_import, + concat!("$0use ", $fixture, ";"), + concat!("use ", $expected, ";"), + ); + + check_assist_import_one( + normalize_import, + concat!("use $0", $fixture, ";"), + concat!("use {", $expected, "};"), + ); + check_assist_import_one( + normalize_import, + concat!("$0use ", $fixture, ";"), + concat!("use {", $expected, "};"), + ); + + check_assist_import_one( + normalize_import, + concat!("use $0{", $fixture, "};"), + concat!("use {", $expected, "};"), + ); + check_assist_import_one( + normalize_import, + concat!("$0use {", $fixture, "};"), + concat!("use {", $expected, "};"), + ); + + check_assist( + normalize_import, + concat!("use $0", $fixture, "$0;"), + concat!("use ", $expected, ";"), + ); + check_assist( + normalize_import, + concat!("$0use ", $fixture, ";$0"), + concat!("use ", $expected, ";"), + ); + }; + } + + macro_rules! check_assist_not_applicable_variations { + ($fixture: literal) => { + check_assist_not_applicable(normalize_import, concat!("use $0", $fixture, ";")); + check_assist_not_applicable(normalize_import, concat!("$0use ", $fixture, ";")); + + check_assist_not_applicable_for_import_one( + normalize_import, + concat!("use $0{", $fixture, "};"), + ); + check_assist_not_applicable_for_import_one( + normalize_import, + concat!("$0use {", $fixture, "};"), + ); + }; + } + + #[test] + fn test_order() { + check_assist_variations!( + "foo::{*, Qux, bar::{Quux, Bar}, baz, FOO_BAZ, self, Baz}", + "foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}" + ); + } + + #[test] + fn test_redundant_braces() { + check_assist_variations!("foo::{bar::{baz, Qux}}", "foo::bar::{baz, Qux}"); + check_assist_variations!("foo::{bar::{self}}", "foo::bar"); + check_assist_variations!("foo::{bar::{*}}", "foo::bar::*"); + check_assist_variations!("foo::{bar::{Qux as Quux}}", "foo::bar::Qux as Quux"); + check_assist_variations!( + "foo::bar::{{FOO_BAZ, Qux, self}, {*, baz}}", + "foo::bar::{self, baz, Qux, FOO_BAZ, *}" + ); + check_assist_variations!( + "foo::bar::{{{FOO_BAZ}, {{Qux}, {self}}}, {{*}, {baz}}}", + "foo::bar::{self, baz, Qux, FOO_BAZ, *}" + ); + } + + #[test] + fn test_merge() { + check_assist_variations!( + "foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux}}", + "foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}" + ); + check_assist_variations!( + "foo::{*, bar, {FOO_BAZ, qux}, bar::{*, baz}, {Quux, bar::{baz::Foo}}}", + "foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}" + ); + } + + #[test] + fn test_merge_self() { + check_assist_variations!("std::{fmt, fmt::Display}", "std::fmt::{self, Display}"); + } + + #[test] + fn test_merge_nested() { + check_assist_variations!("std::{fmt::Debug, fmt::Display}", "std::fmt::{Debug, Display}"); + } + + #[test] + fn test_merge_nested2() { + check_assist_variations!("std::{fmt::Debug, fmt::Display}", "std::fmt::{Debug, Display}"); + } + + #[test] + fn test_merge_self_with_nested_self_item() { + check_assist_variations!( + "std::{fmt::{self, Debug}, fmt::{Write, Display}}", + "std::fmt::{self, Debug, Display, Write}" + ); + } + + #[test] + fn works_with_trailing_comma() { + check_assist( + normalize_import, + r" +use $0{ + foo::bar, + foo::baz, +}; + ", + r" +use foo::{bar, baz}; + ", + ); + check_assist_import_one( + normalize_import, + r" +use $0{ + foo::bar, + foo::baz, +}; +", + r" +use { + foo::{bar, baz}, +}; +", + ); + } + + #[test] + fn not_applicable_to_normalized_import() { + check_assist_not_applicable_variations!("foo::bar"); + check_assist_not_applicable_variations!("foo::bar::*"); + check_assist_not_applicable_variations!("foo::bar::Qux as Quux"); + check_assist_not_applicable_variations!("foo::bar::{self, baz, Qux, FOO_BAZ, *}"); + check_assist_not_applicable_variations!( + "foo::{self, bar::{Bar, Quux}, baz, Baz, Qux, FOO_BAZ, *}" + ); + check_assist_not_applicable_variations!( + "foo::{bar::{self, baz, *}, qux, Quux, FOO_BAZ, *}" + ); + check_assist_not_applicable_variations!( + "foo::{bar::{self, baz::{self, Foo}, *}, qux, Quux, FOO_BAZ, *}" + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs index 3a0121f55fa02..64e30b1834522 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/sort_items.rs @@ -116,11 +116,9 @@ trait AddRewrite { new: Vec, target: TextRange, ) -> Option<()>; - fn yeet() {} } impl AddRewrite for Assists { - fn yeet() {} fn add_rewrite( &mut self, label: &str, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs index 1eb4903ab2033..2fec104323dc7 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs @@ -111,6 +111,8 @@ mod handlers { mod add_label_to_loop; mod add_lifetime_to_type; mod add_missing_impl_members; + mod add_missing_match_arms; + mod add_return_type; mod add_turbo_fish; mod apply_demorgan; mod auto_import; @@ -124,15 +126,15 @@ mod handlers { mod convert_iter_for_each_to_for; mod convert_let_else_to_match; mod convert_match_to_let_else; + mod convert_named_struct_to_tuple_struct; mod convert_nested_function_to_closure; + mod convert_to_guarded_return; mod convert_tuple_return_type_to_struct; mod convert_tuple_struct_to_named_struct; - mod convert_named_struct_to_tuple_struct; - mod convert_to_guarded_return; mod convert_two_arm_bool_match_to_matches_macro; mod convert_while_to_loop; - mod desugar_doc_comment; mod destructure_tuple_binding; + mod desugar_doc_comment; mod expand_glob_import; mod extract_expressions_from_format_string; mod extract_function; @@ -140,7 +142,6 @@ mod handlers { mod extract_struct_from_enum_variant; mod extract_type_alias; mod extract_variable; - mod add_missing_match_arms; mod fix_visibility; mod flip_binexpr; mod flip_comma; @@ -148,6 +149,7 @@ mod handlers { mod generate_constant; mod generate_default_from_enum_variant; mod generate_default_from_new; + mod generate_delegate_methods; mod generate_delegate_trait; mod generate_deref; mod generate_derive; @@ -162,62 +164,61 @@ mod handlers { mod generate_is_empty_from_len; mod generate_mut_trait_impl; mod generate_new; - mod generate_delegate_methods; mod generate_trait_from_impl; - mod add_return_type; mod inline_call; mod inline_const_as_literal; mod inline_local_variable; mod inline_macro; mod inline_type_alias; + mod into_to_qualified_from; + mod introduce_named_generic; mod introduce_named_lifetime; mod invert_if; mod merge_imports; mod merge_match_arms; + mod merge_nested_if; mod move_bounds; mod move_const_to_impl; + mod move_from_mod_rs; mod move_guard; mod move_module_to_file; mod move_to_mod_rs; - mod move_from_mod_rs; + mod normalize_import; mod number_representation; mod promote_local_to_const; mod pull_assignment_up; - mod qualify_path; mod qualify_method_call; + mod qualify_path; mod raw_string; mod remove_dbg; mod remove_mut; + mod remove_parentheses; mod remove_unused_imports; mod remove_unused_param; - mod remove_parentheses; mod reorder_fields; mod reorder_impl_items; - mod replace_try_expr_with_match; + mod replace_arith_op; mod replace_derive_with_manual_impl; mod replace_if_let_with_match; mod replace_is_method_with_if_let_method; - mod replace_method_eager_lazy; - mod replace_arith_op; - mod introduce_named_generic; mod replace_let_with_if_let; + mod replace_method_eager_lazy; mod replace_named_generic_with_impl; mod replace_qualified_name_with_use; mod replace_string_with_char; + mod replace_try_expr_with_match; mod replace_turbofish_with_explicit_type; - mod split_import; - mod unmerge_match_arm; - mod unwrap_tuple; mod sort_items; + mod split_import; mod toggle_ignore; + mod unmerge_match_arm; mod unmerge_use; mod unnecessary_async; + mod unqualify_method_call; mod unwrap_block; mod unwrap_result_return_type; - mod unqualify_method_call; + mod unwrap_tuple; mod wrap_return_type_in_result; - mod into_to_qualified_from; - mod merge_nested_if; pub(crate) fn all() -> &'static [Handler] { &[ @@ -300,6 +301,7 @@ mod handlers { move_module_to_file::move_module_to_file, move_to_mod_rs::move_to_mod_rs, move_from_mod_rs::move_from_mod_rs, + normalize_import::normalize_import, number_representation::reformat_number_literal, pull_assignment_up::pull_assignment_up, promote_local_to_const::promote_local_to_const, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs index 0ce89ae0a9a5e..8d7c49d52c23d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs @@ -2217,6 +2217,19 @@ fn t() {} ) } +#[test] +fn doctest_normalize_import() { + check_doc_test( + "normalize_import", + r#####" +use$0 std::{io, {fmt::Formatter}}; +"#####, + r#####" +use std::{fmt::Formatter, io}; +"#####, + ) +} + #[test] fn doctest_promote_local_to_const() { check_doc_test( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/sourcegen.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/sourcegen.rs index ad5ec83287529..088d93f9a6ba4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/sourcegen.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/sourcegen.rs @@ -2,6 +2,7 @@ use std::{fmt, fs, path::Path}; +use stdx::format_to_acc; use test_utils::project_root; #[test] @@ -172,8 +173,7 @@ impl fmt::Display for Assist { fn hide_hash_comments(text: &str) -> String { text.split('\n') // want final newline .filter(|&it| !(it.starts_with("# ") || it == "#")) - .map(|it| format!("{it}\n")) - .collect() + .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n")) } fn reveal_hash_comments(text: &str) -> String { @@ -187,6 +187,5 @@ fn reveal_hash_comments(text: &str) -> String { it } }) - .map(|it| format!("{it}\n")) - .collect() + .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n")) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index 2420945f75607..eeb3d80d07bd1 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -23,8 +23,8 @@ use syntax::{ use crate::assist_context::{AssistContext, SourceChangeBuilder}; -pub(crate) mod suggest_name; mod gen_trait_fn_body; +pub(crate) mod suggest_name; pub(crate) fn unwrap_trivial_block(block_expr: ast::BlockExpr) -> ast::Expr { extract_trivial_expression(&block_expr) diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml index 7fbcf3d19e0f1..f2a11276ba2b8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [dependencies] cov-mark = "2.0.0-pre.1" itertools.workspace = true +tracing.workspace = true once_cell = "1.17.0" smallvec.workspace = true @@ -38,4 +39,4 @@ test-utils.workspace = true test-fixture.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index 4d3d0b4d1a6f5..ba3c0cf3fd60e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -2,8 +2,10 @@ pub(crate) mod attribute; pub(crate) mod dot; +pub(crate) mod env_vars; pub(crate) mod expr; pub(crate) mod extern_abi; +pub(crate) mod extern_crate; pub(crate) mod field; pub(crate) mod flyimport; pub(crate) mod fn_param; @@ -19,8 +21,6 @@ pub(crate) mod snippet; pub(crate) mod r#type; pub(crate) mod use_; pub(crate) mod vis; -pub(crate) mod env_vars; -pub(crate) mod extern_crate; use std::iter; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs index 8f7c3b5070bfd..a7a6cdebd361e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs @@ -25,8 +25,8 @@ use crate::{ mod cfg; mod derive; mod lint; -mod repr; mod macro_use; +mod repr; pub(crate) use self::derive::complete_derive_path; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index e5fdac327cdb6..00135a6d202cb 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -31,7 +31,7 @@ pub(crate) fn complete_dot( } let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. }); - let is_method_acces_with_parens = + let is_method_access_with_parens = matches!(dot_access.kind, DotAccessKind::Method { has_parens: true }); complete_fields( @@ -41,7 +41,7 @@ pub(crate) fn complete_dot( |acc, field, ty| acc.add_field(ctx, dot_access, None, field, &ty), |acc, field, ty| acc.add_tuple_field(ctx, None, field, &ty), is_field_access, - is_method_acces_with_parens, + is_method_access_with_parens, ); complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None)); @@ -114,14 +114,14 @@ fn complete_fields( mut named_field: impl FnMut(&mut Completions, hir::Field, hir::Type), mut tuple_index: impl FnMut(&mut Completions, usize, hir::Type), is_field_access: bool, - is_method_acess_with_parens: bool, + is_method_access_with_parens: bool, ) { let mut seen_names = FxHashSet::default(); for receiver in receiver.autoderef(ctx.db) { for (field, ty) in receiver.fields(ctx.db) { if seen_names.insert(field.name(ctx.db)) && (is_field_access - || (is_method_acess_with_parens && (ty.is_fn() || ty.is_closure()))) + || (is_method_access_with_parens && (ty.is_fn() || ty.is_closure()))) { named_field(acc, field, ty); } @@ -131,7 +131,7 @@ fn complete_fields( // already seen without inserting into the hashset. if !seen_names.contains(&hir::Name::new_tuple_field(i)) && (is_field_access - || (is_method_acess_with_parens && (ty.is_fn() || ty.is_closure()))) + || (is_method_access_with_parens && (ty.is_fn() || ty.is_closure()))) { // Tuple fields are always public (tuple struct fields are handled above). tuple_index(acc, i, ty); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index d3c817d4b43ad..1433216d6111d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -15,7 +15,7 @@ pub(crate) fn complete_expr_path( path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, expr_ctx: &ExprCtx, ) { - let _p = profile::span("complete_expr_path"); + let _p = tracing::span!(tracing::Level::INFO, "complete_expr_path").entered(); if !ctx.qualifier_ctx.none() { return; } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs index 75017cf66f8db..b5d5604c7519f 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs @@ -26,7 +26,6 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[ "ptx-kernel", "msp430-interrupt", "x86-interrupt", - "amdgpu-kernel", "efiapi", "avr-interrupt", "avr-non-blocking-interrupt", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index e330430d6b90b..0e04ad35d33d1 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs @@ -207,7 +207,8 @@ fn import_on_the_fly( position: SyntaxNode, potential_import_name: String, ) -> Option<()> { - let _p = profile::span("import_on_the_fly").detail(|| potential_import_name.clone()); + let _p = + tracing::span!(tracing::Level::INFO, "import_on_the_fly", ?potential_import_name).entered(); ImportScope::find_insert_use_container(&position, &ctx.sema)?; @@ -293,7 +294,8 @@ fn import_on_the_fly_pat_( position: SyntaxNode, potential_import_name: String, ) -> Option<()> { - let _p = profile::span("import_on_the_fly_pat").detail(|| potential_import_name.clone()); + let _p = tracing::span!(tracing::Level::INFO, "import_on_the_fly_pat", ?potential_import_name) + .entered(); ImportScope::find_insert_use_container(&position, &ctx.sema)?; @@ -343,7 +345,9 @@ fn import_on_the_fly_method( position: SyntaxNode, potential_import_name: String, ) -> Option<()> { - let _p = profile::span("import_on_the_fly_method").detail(|| potential_import_name.clone()); + let _p = + tracing::span!(tracing::Level::INFO, "import_on_the_fly_method", ?potential_import_name) + .entered(); ImportScope::find_insert_use_container(&position, &ctx.sema)?; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs index 4de15ab759629..addd9dac1a766 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs @@ -28,7 +28,7 @@ pub(crate) fn complete_item_list( path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, kind: &ItemListKind, ) { - let _p = profile::span("complete_item_list"); + let _p = tracing::span!(tracing::Level::INFO, "complete_item_list").entered(); if path_ctx.is_trivial_path() { add_keywords(acc, ctx, Some(kind)); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs index 5d138eea46f4b..ecf5b29e2c0c3 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs @@ -21,7 +21,7 @@ pub(crate) fn complete_mod( return None; } - let _p = profile::span("completion::complete_mod"); + let _p = tracing::span!(tracing::Level::INFO, "completion::complete_mod").entered(); let mut current_module = ctx.module; // For `mod $0`, `ctx.module` is its parent, but for `mod f$0`, it's `mod f` itself, but we're diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index a846ffe10e636..af83d4104f76e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -84,6 +84,13 @@ pub(crate) fn complete_postfix( ) .add_to(acc, ctx.db); + postfix_snippet( + "lete", + "let Ok else {}", + &format!("let Ok($1) = {receiver_text} else {{\n $2\n}};\n$0"), + ) + .add_to(acc, ctx.db); + postfix_snippet( "while", "while let Ok {}", @@ -99,6 +106,13 @@ pub(crate) fn complete_postfix( ) .add_to(acc, ctx.db); + postfix_snippet( + "lete", + "let Some else {}", + &format!("let Some($1) = {receiver_text} else {{\n $2\n}};\n$0"), + ) + .add_to(acc, ctx.db); + postfix_snippet( "while", "while let Some {}", @@ -469,6 +483,29 @@ fn main() { ); } + #[test] + fn option_letelse() { + check_edit( + "lete", + r#" +//- minicore: option +fn main() { + let bar = Some(true); + bar.$0 +} +"#, + r#" +fn main() { + let bar = Some(true); + let Some($1) = bar else { + $2 +}; +$0 +} +"#, + ); + } + #[test] fn result_match() { check_edit( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs index a30fd13b1d5f3..e6a4335c3fec8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs @@ -15,7 +15,7 @@ pub(crate) fn complete_type_path( path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx, location: &TypeLocation, ) { - let _p = profile::span("complete_type_path"); + let _p = tracing::span!(tracing::Level::INFO, "complete_type_path").entered(); let scope_def_applicable = |def| { use hir::{GenericParam::*, ModuleDef::*}; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index 575f524209c70..2c0370c58f70a 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -568,7 +568,8 @@ impl CompletionContext<'_> { /// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items and /// passes all doc-aliases along, to funnel it into [`Completions::add_path_resolution`]. pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef, Vec)) { - let _p = profile::span("CompletionContext::process_all_names"); + let _p = + tracing::span!(tracing::Level::INFO, "CompletionContext::process_all_names").entered(); self.scope.process_all_names(&mut |name, def| { if self.is_scope_def_hidden(def) { return; @@ -579,7 +580,8 @@ impl CompletionContext<'_> { } pub(crate) fn process_all_names_raw(&self, f: &mut dyn FnMut(Name, ScopeDef)) { - let _p = profile::span("CompletionContext::process_all_names_raw"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::process_all_names_raw") + .entered(); self.scope.process_all_names(f); } @@ -637,7 +639,7 @@ impl<'a> CompletionContext<'a> { position @ FilePosition { file_id, offset }: FilePosition, config: &'a CompletionConfig, ) -> Option<(CompletionContext<'a>, CompletionAnalysis)> { - let _p = profile::span("CompletionContext::new"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::new").entered(); let sema = Semantics::new(db); let original_file = sema.parse(file_id); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index 8a4ac00de9105..c06b64df1c525 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -72,7 +72,7 @@ fn expand( mut fake_ident_token: SyntaxToken, relative_offset: TextSize, ) -> ExpansionResult { - let _p = profile::span("CompletionContext::expand"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::expand").entered(); let mut derive_ctx = None; 'expansion: loop { @@ -211,7 +211,7 @@ fn analyze( original_token: &SyntaxToken, self_token: &SyntaxToken, ) -> Option<(CompletionAnalysis, (Option, Option), QualifierCtx)> { - let _p = profile::span("CompletionContext::analyze"); + let _p = tracing::span!(tracing::Level::INFO, "CompletionContext::analyze").entered(); let ExpansionResult { original_file, speculative_file, offset, fake_ident_token, derive_ctx } = expansion_result; @@ -1267,8 +1267,7 @@ fn pattern_context_for( pat .syntax() .ancestors() - .skip_while(|it| ast::Pat::can_cast(it.kind())) - .next() + .find(|it| !ast::Pat::can_cast(it.kind())) .map_or((PatternRefutability::Irrefutable, false), |node| { let refutability = match_ast! { match node { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index 864b993f7136e..bcf169f46530d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -433,7 +433,7 @@ impl Builder { } pub(crate) fn build(self, db: &RootDatabase) -> CompletionItem { - let _p = profile::span("item::Builder::build"); + let _p = tracing::span!(tracing::Level::INFO, "item::Builder::build").entered(); let label = self.label; let mut label_detail = None; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index 6a98e109f6dff..733523d369424 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -8,9 +8,9 @@ mod context; mod item; mod render; +mod snippet; #[cfg(test)] mod tests; -mod snippet; use ide_db::{ base_db::FilePosition, @@ -236,7 +236,7 @@ pub fn resolve_completion_edits( FilePosition { file_id, offset }: FilePosition, imports: impl IntoIterator, ) -> Option> { - let _p = profile::span("resolve_completion_edits"); + let _p = tracing::span!(tracing::Level::INFO, "resolve_completion_edits").entered(); let sema = hir::Semantics::new(db); let original_file = sema.parse(file_id); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index 6fd988bfc0fc6..4d49d2f4987f1 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -1,14 +1,14 @@ //! `render` module provides utilities for rendering completion suggestions //! into code pieces that will be presented to user. -pub(crate) mod macro_; -pub(crate) mod function; pub(crate) mod const_; +pub(crate) mod function; +pub(crate) mod literal; +pub(crate) mod macro_; pub(crate) mod pattern; pub(crate) mod type_alias; -pub(crate) mod variant; pub(crate) mod union_literal; -pub(crate) mod literal; +pub(crate) mod variant; use hir::{AsAssocItem, HasAttrs, HirDisplay, ModuleDef, ScopeDef, Type}; use ide_db::{ @@ -292,7 +292,7 @@ fn render_resolution_pat( import_to_add: Option, resolution: ScopeDef, ) -> Builder { - let _p = profile::span("render_resolution"); + let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered(); use hir::ModuleDef::*; if let ScopeDef::ModuleDef(Macro(mac)) = resolution { @@ -310,7 +310,7 @@ fn render_resolution_path( import_to_add: Option, resolution: ScopeDef, ) -> Builder { - let _p = profile::span("render_resolution"); + let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered(); use hir::ModuleDef::*; match resolution { @@ -418,7 +418,7 @@ fn render_resolution_simple_( import_to_add: Option, resolution: ScopeDef, ) -> Builder { - let _p = profile::span("render_resolution"); + let _p = tracing::span!(tracing::Level::INFO, "render_resolution").entered(); let db = ctx.db(); let ctx = ctx.import_to_add(import_to_add); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs index 3c73983c39a2b..a2bfac994ff0b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/const_.rs @@ -6,7 +6,7 @@ use ide_db::SymbolKind; use crate::{item::CompletionItem, render::RenderContext}; pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option { - let _p = profile::span("render_const"); + let _p = tracing::span!(tracing::Level::INFO, "render_const").entered(); render(ctx, const_) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index 0f2608d1325a9..4ae7ea861c75b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -25,7 +25,7 @@ pub(crate) fn render_fn( local_name: Option, func: hir::Function, ) -> Builder { - let _p = profile::span("render_fn"); + let _p = tracing::span!(tracing::Level::INFO, "render_fn").entered(); render(ctx, local_name, func, FuncKind::Function(path_ctx)) } @@ -36,7 +36,7 @@ pub(crate) fn render_method( local_name: Option, func: hir::Function, ) -> Builder { - let _p = profile::span("render_method"); + let _p = tracing::span!(tracing::Level::INFO, "render_method").entered(); render(ctx, local_name, func, FuncKind::Method(dot_access, receiver)) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs index f2d67df01d31b..f52a5f7625557 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/literal.rs @@ -27,7 +27,7 @@ pub(crate) fn render_variant_lit( variant: hir::Variant, path: Option, ) -> Option { - let _p = profile::span("render_enum_variant"); + let _p = tracing::span!(tracing::Level::INFO, "render_enum_variant").entered(); let db = ctx.db(); let name = local_name.unwrap_or_else(|| variant.name(db)); @@ -41,7 +41,7 @@ pub(crate) fn render_struct_literal( path: Option, local_name: Option, ) -> Option { - let _p = profile::span("render_struct_literal"); + let _p = tracing::span!(tracing::Level::INFO, "render_struct_literal").entered(); let db = ctx.db(); let name = local_name.unwrap_or_else(|| strukt.name(db)); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs index 915a245ab6b4c..540cfd03d6061 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/macro_.rs @@ -17,7 +17,7 @@ pub(crate) fn render_macro( name: hir::Name, macro_: hir::Macro, ) -> Builder { - let _p = profile::span("render_macro"); + let _p = tracing::span!(tracing::Level::INFO, "render_macro").entered(); render(ctx, *kind == PathKind::Use, *has_macro_bang, *has_call_parens, name, macro_) } @@ -27,7 +27,7 @@ pub(crate) fn render_macro_pat( name: hir::Name, macro_: hir::Macro, ) -> Builder { - let _p = profile::span("render_macro"); + let _p = tracing::span!(tracing::Level::INFO, "render_macro").entered(); render(ctx, false, false, false, name, macro_) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs index 6f998119b7cac..a5f851566cb08 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs @@ -20,7 +20,7 @@ pub(crate) fn render_struct_pat( strukt: hir::Struct, local_name: Option, ) -> Option { - let _p = profile::span("render_struct_pat"); + let _p = tracing::span!(tracing::Level::INFO, "render_struct_pat").entered(); let fields = strukt.fields(ctx.db()); let (visible_fields, fields_omitted) = visible_fields(ctx.completion, &fields, strukt)?; @@ -50,7 +50,7 @@ pub(crate) fn render_variant_pat( local_name: Option, path: Option<&hir::ModPath>, ) -> Option { - let _p = profile::span("render_variant_pat"); + let _p = tracing::span!(tracing::Level::INFO, "render_variant_pat").entered(); let fields = variant.fields(ctx.db()); let (visible_fields, fields_omitted) = visible_fields(ctx.completion, &fields, variant)?; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs index 343ba7e28d8e0..b192309e93f34 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/type_alias.rs @@ -10,7 +10,7 @@ pub(crate) fn render_type_alias( ctx: RenderContext<'_>, type_alias: hir::TypeAlias, ) -> Option { - let _p = profile::span("render_type_alias"); + let _p = tracing::span!(tracing::Level::INFO, "render_type_alias").entered(); render(ctx, type_alias, false) } @@ -18,7 +18,7 @@ pub(crate) fn render_type_alias_with_eq( ctx: RenderContext<'_>, type_alias: hir::TypeAlias, ) -> Option { - let _p = profile::span("render_type_alias_with_eq"); + let _p = tracing::span!(tracing::Level::INFO, "render_type_alias_with_eq").entered(); render(ctx, type_alias, true) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index f13754e2ded05..154b69875aea8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -12,8 +12,8 @@ mod attribute; mod expression; mod flyimport; mod fn_param; -mod item_list; mod item; +mod item_list; mod pattern; mod predicate; mod proc_macros; @@ -210,23 +210,14 @@ pub(crate) fn check_edit_with_config( let mut combined_edit = completion.text_edit.clone(); - resolve_completion_edits( - &db, - &config, - position, - completion - .import_to_add - .iter() - .cloned() - .filter_map(|(import_path, import_name)| Some((import_path, import_name))), - ) - .into_iter() - .flatten() - .for_each(|text_edit| { - combined_edit.union(text_edit).expect( - "Failed to apply completion resolve changes: change ranges overlap, but should not", - ) - }); + resolve_completion_edits(&db, &config, position, completion.import_to_add.iter().cloned()) + .into_iter() + .flatten() + .for_each(|text_edit| { + combined_edit.union(text_edit).expect( + "Failed to apply completion resolve changes: change ranges overlap, but should not", + ) + }); combined_edit.apply(&mut actual); assert_eq_text!(&ra_fixture_after, &actual) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index b4f936b35aead..758c254a88289 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -105,7 +105,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) { fn completes_all_the_things_in_fn_body() { check( r#" -use non_existant::Unresolved; +use non_existent::Unresolved; mod qualified { pub enum Enum { Variant } } impl Unit { @@ -170,7 +170,7 @@ impl Unit { ); check( r#" -use non_existant::Unresolved; +use non_existent::Unresolved; mod qualified { pub enum Enum { Variant } } impl Unit { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index 1af16ef857d03..eaa1bebc03c7e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -106,7 +106,7 @@ fn main() { } "#, r#" -use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}}; +use dep::{some_module::{SecondStruct, ThirdStruct}, FirstStruct}; fn main() { ThirdStruct diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs index 766d1c1e43dba..296253aa1ee19 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs @@ -15,12 +15,13 @@ use crate::{symbol_index::SymbolsDatabase, Change, RootDatabase}; impl RootDatabase { pub fn request_cancellation(&mut self) { - let _p = profile::span("RootDatabase::request_cancellation"); + let _p = + tracing::span!(tracing::Level::INFO, "RootDatabase::request_cancellation").entered(); self.salsa_runtime_mut().synthetic_write(Durability::LOW); } pub fn apply_change(&mut self, change: Change) { - let _p = profile::span("RootDatabase::apply_change"); + let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered(); self.request_cancellation(); tracing::trace!("apply_change {:?}", change); if let Some(roots) = &change.source_change.roots { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 5995b318e8eff..81f2f87d96236 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -404,7 +404,7 @@ impl NameClass { } pub fn classify(sema: &Semantics<'_, RootDatabase>, name: &ast::Name) -> Option { - let _p = profile::span("classify_name"); + let _p = tracing::span!(tracing::Level::INFO, "classify_name").entered(); let parent = name.syntax().parent()?; @@ -496,7 +496,7 @@ impl NameClass { sema: &Semantics<'_, RootDatabase>, lifetime: &ast::Lifetime, ) -> Option { - let _p = profile::span("classify_lifetime").detail(|| lifetime.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "classify_lifetime", ?lifetime).entered(); let parent = lifetime.syntax().parent()?; if let Some(it) = ast::LifetimeParam::cast(parent.clone()) { @@ -587,7 +587,7 @@ impl NameRefClass { sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameRef, ) -> Option { - let _p = profile::span("classify_name_ref").detail(|| name_ref.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "classify_name_ref", ?name_ref).entered(); let parent = name_ref.syntax().parent()?; @@ -686,7 +686,7 @@ impl NameRefClass { sema: &Semantics<'_, RootDatabase>, lifetime: &ast::Lifetime, ) -> Option { - let _p = profile::span("classify_lifetime_ref").detail(|| lifetime.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "classify_lifetime_ref", ?lifetime).entered(); let parent = lifetime.syntax().parent()?; match parent.kind() { SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs index cc8e8431708ab..72ca354365e7b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs @@ -1,4 +1,4 @@ -//! Documentation attribute related utilties. +//! Documentation attribute related utilities. use either::Either; use hir::{ db::{DefDatabase, HirDatabase}, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs index f160def0aff00..677c8fd54c058 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs @@ -22,10 +22,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"detects certain glob imports that require reporting an ambiguity error"##, }, Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## }, - Lint { - label: "ambiguous_wide_pointer_comparisons", - description: r##"detects ambiguous wide pointer comparisons"##, - }, Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## }, Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## }, Lint { @@ -110,7 +106,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "deref_into_dyn_supertrait", - description: r##"`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion"##, + description: r##"`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future"##, }, Lint { label: "deref_nullptr", @@ -180,7 +176,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[ }, Lint { label: "future_incompatible", - description: r##"lint group for: ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, Lint { label: "fuzzy_provenance_casts", @@ -198,6 +194,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "illegal_floating_point_literal_pattern", description: r##"floating-point literals cannot be used in patterns"##, }, + Lint { + label: "implied_bounds_entailment", + description: r##"impl method assumes more implied bounds than its corresponding trait method"##, + }, Lint { label: "improper_ctypes", description: r##"proper use of libc types in foreign modules"##, @@ -579,10 +579,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[ description: r##"enabling track_caller on an async fn is a no-op unless the async_fn_track_caller feature is enabled"##, }, Lint { label: "uninhabited_static", description: r##"uninhabited static"## }, - Lint { - label: "unit_bindings", - description: r##"binding is useless because it has the unit `()` type"##, - }, Lint { label: "unknown_crate_types", description: r##"unknown crate type found in `#[crate_type]` directive"##, @@ -740,19 +736,16 @@ pub const DEFAULT_LINTS: &[Lint] = &[ label: "while_true", description: r##"suggest using `loop { }` instead of `while true { }`"##, }, - Lint { - label: "writes_through_immutable_pointer", - description: r##"shared references are immutable, and pointers derived from them must not be written to"##, - }, ]; pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "future_incompatible", - description: r##"lint group for: ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##, + description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##, }, children: &[ + "deref_into_dyn_supertrait", "ambiguous_associated_items", "ambiguous_glob_imports", "byte_slice_in_packed_struct_with_derive", @@ -767,6 +760,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "forbidden_lint_groups", "ill_formed_attribute_input", "illegal_floating_point_literal_pattern", + "implied_bounds_entailment", "indirect_structural_match", "invalid_doc_attributes", "invalid_type_param_default", @@ -790,7 +784,6 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[ "unstable_syntax_pre_expansion", "unsupported_calling_conventions", "where_clauses_object_safety", - "writes_through_immutable_pointer", ], }, LintGroup { @@ -963,17 +956,6 @@ The tracking issue for this feature is: [#44839] [#44839]: https://github.com/rust-lang/rust/issues/44839 ------------------------- -"##, - }, - Lint { - label: "abi_amdgpu_kernel", - description: r##"# `abi_amdgpu_kernel` - -The tracking issue for this feature is: [#51575] - -[#51575]: https://github.com/rust-lang/rust/issues/51575 - ------------------------ "##, }, @@ -1403,17 +1385,6 @@ The tracking issue for this feature is: [#91583] [#91583]: https://github.com/rust-lang/rust/issues/91583 ------------------------- -"##, - }, - Lint { - label: "array_methods", - description: r##"# `array_methods` - -The tracking issue for this feature is: [#76118] - -[#76118]: https://github.com/rust-lang/rust/issues/76118 - ------------------------ "##, }, @@ -1586,7 +1557,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `reg_data` | None | `i8`, `i16`, `i32` | | CSKY | `reg` | None | `i8`, `i16`, `i32` | | CSKY | `freg` | None | `f32`, | -| s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | +| s390x | `reg`, `reg_addr` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | ## Register aliases @@ -1660,9 +1631,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | NVPTX | `reg64` | None | `rd0` | None | | Hexagon | `reg` | None | `r0` | None | | PowerPC | `reg` | None | `0` | None | -| PowerPC | `reg_nonzero` | None | `3` | `b` | +| PowerPC | `reg_nonzero` | None | `3` | None | | PowerPC | `freg` | None | `0` | None | | s390x | `reg` | None | `%r0` | None | +| s390x | `reg_addr` | None | `%r1` | None | | s390x | `freg` | None | `%f0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | @@ -1756,6 +1728,15 @@ The tracking issue for this feature is: [#110011] [#110011]: https://github.com/rust-lang/rust/issues/110011 +------------------------ +"##, + }, + Lint { + label: "async_fn_traits", + description: r##"# `async_fn_traits` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -2007,17 +1988,6 @@ The tracking issue for this feature is: [#80996] [#80996]: https://github.com/rust-lang/rust/issues/80996 ------------------------- -"##, - }, - Lint { - label: "bound_map", - description: r##"# `bound_map` - -The tracking issue for this feature is: [#86026] - -[#86026]: https://github.com/rust-lang/rust/issues/86026 - ------------------------ "##, }, @@ -2397,6 +2367,17 @@ fn b() { } } ``` +"##, + }, + Lint { + label: "cfg_sanitizer_cfi", + description: r##"# `cfg_sanitizer_cfi` + +The tracking issue for this feature is: [#89653] + +[#89653]: https://github.com/rust-lang/rust/issues/89653 + +------------------------ "##, }, Lint { @@ -2829,17 +2810,6 @@ The tracking issue for this feature is: [#91583] [#91583]: https://github.com/rust-lang/rust/issues/91583 ------------------------- -"##, - }, - Lint { - label: "const_assume", - description: r##"# `const_assume` - -The tracking issue for this feature is: [#76972] - -[#76972]: https://github.com/rust-lang/rust/issues/76972 - ------------------------ "##, }, @@ -3114,6 +3084,17 @@ The tracking issue for this feature is: [#79597] [#79597]: https://github.com/rust-lang/rust/issues/79597 +------------------------ +"##, + }, + Lint { + label: "const_hint_assert_unchecked", + description: r##"# `const_hint_assert_unchecked` + +The tracking issue for this feature is: [#119131] + +[#119131]: https://github.com/rust-lang/rust/issues/119131 + ------------------------ "##, }, @@ -3518,6 +3499,17 @@ The tracking issue for this feature is: [#83570] [#83570]: https://github.com/rust-lang/rust/issues/83570 +------------------------ +"##, + }, + Lint { + label: "const_slice_first_last_chunk", + description: r##"# `const_slice_first_last_chunk` + +The tracking issue for this feature is: [#111774] + +[#111774]: https://github.com/rust-lang/rust/issues/111774 + ------------------------ "##, }, @@ -3593,6 +3585,17 @@ The tracking issue for this feature is: [#101804] [#101804]: https://github.com/rust-lang/rust/issues/101804 +------------------------ +"##, + }, + Lint { + label: "const_str_from_raw_parts_mut", + description: r##"# `const_str_from_raw_parts_mut` + +The tracking issue for this feature is: [#119206] + +[#119206]: https://github.com/rust-lang/rust/issues/119206 + ------------------------ "##, }, @@ -3615,6 +3618,17 @@ The tracking issue for this feature is: [#91005] [#91005]: https://github.com/rust-lang/rust/issues/91005 +------------------------ +"##, + }, + Lint { + label: "const_strict_overflow_ops", + description: r##"# `const_strict_overflow_ops` + +The tracking issue for this feature is: [#118260] + +[#118260]: https://github.com/rust-lang/rust/issues/118260 + ------------------------ "##, }, @@ -3754,15 +3768,6 @@ The tracking issue for this feature is: [#117693] [#117693]: https://github.com/rust-lang/rust/issues/117693 ------------------------- -"##, - }, - Lint { - label: "core_panic", - description: r##"# `core_panic` - -This feature is internal to the Rust compiler and is not intended for general use. - ------------------------ "##, }, @@ -5316,6 +5321,17 @@ The tracking issue for this feature is: [#113521] [#113521]: https://github.com/rust-lang/rust/issues/113521 +------------------------ +"##, + }, + Lint { + label: "generic_nonzero", + description: r##"# `generic_nonzero` + +The tracking issue for this feature is: [#120257] + +[#120257]: https://github.com/rust-lang/rust/issues/120257 + ------------------------ "##, }, @@ -5436,6 +5452,17 @@ The tracking issue for this feature is: [#44839] [#44839]: https://github.com/rust-lang/rust/issues/44839 +------------------------ +"##, + }, + Lint { + label: "hint_assert_unchecked", + description: r##"# `hint_assert_unchecked` + +The tracking issue for this feature is: [#119131] + +[#119131]: https://github.com/rust-lang/rust/issues/119131 + ------------------------ "##, }, @@ -5759,6 +5786,15 @@ The tracking issue for this feature is: [#53485] Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`; add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `Iterator`. +"##, + }, + Lint { + label: "is_val_statically_known", + description: r##"# `is_val_statically_known` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + +------------------------ "##, }, Lint { @@ -6417,6 +6453,17 @@ The tracking issue for this feature is: [#98262] [#98262]: https://github.com/rust-lang/rust/issues/98262 +------------------------ +"##, + }, + Lint { + label: "min_exhaustive_patterns", + description: r##"# `min_exhaustive_patterns` + +The tracking issue for this feature is: [#119612] + +[#119612]: https://github.com/rust-lang/rust/issues/119612 + ------------------------ "##, }, @@ -6514,17 +6561,6 @@ The tracking issue for this feature is: [#81872] [#81872]: https://github.com/rust-lang/rust/issues/81872 ------------------------- -"##, - }, - Lint { - label: "mutex_unpoison", - description: r##"# `mutex_unpoison` - -The tracking issue for this feature is: [#96469] - -[#96469]: https://github.com/rust-lang/rust/issues/96469 - ------------------------ "##, }, @@ -6532,9 +6568,9 @@ The tracking issue for this feature is: [#96469] label: "naked_functions", description: r##"# `naked_functions` -The tracking issue for this feature is: [#32408] +The tracking issue for this feature is: [#90957] -[#32408]: https://github.com/rust-lang/rust/issues/32408 +[#90957]: https://github.com/rust-lang/rust/issues/90957 ------------------------ "##, @@ -6760,6 +6796,37 @@ The tracking issue for this feature is: [#117691] [#117691]: https://github.com/rust-lang/rust/issues/117691 +------------------------ +"##, + }, + Lint { + label: "non_zero_count_ones", + description: r##"# `non_zero_count_ones` + +The tracking issue for this feature is: [#120287] + +[#120287]: https://github.com/rust-lang/rust/issues/120287 + +------------------------ +"##, + }, + Lint { + label: "nonzero_from_mut", + description: r##"# `nonzero_from_mut` + +The tracking issue for this feature is: [#106290] + +[#106290]: https://github.com/rust-lang/rust/issues/106290 + +------------------------ +"##, + }, + Lint { + label: "nonzero_internals", + description: r##"# `nonzero_internals` + +This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use. + ------------------------ "##, }, @@ -6817,23 +6884,23 @@ The tracking issue for this feature is: [#43561] "##, }, Lint { - label: "offset_of", - description: r##"# `offset_of` + label: "offset_of_enum", + description: r##"# `offset_of_enum` -The tracking issue for this feature is: [#106655] +The tracking issue for this feature is: [#120141] -[#106655]: https://github.com/rust-lang/rust/issues/106655 +[#120141]: https://github.com/rust-lang/rust/issues/120141 ------------------------ "##, }, Lint { - label: "offset_of_enum", - description: r##"# `offset_of_enum` + label: "offset_of_nested", + description: r##"# `offset_of_nested` -The tracking issue for this feature is: [#106655] +The tracking issue for this feature is: [#120140] -[#106655]: https://github.com/rust-lang/rust/issues/106655 +[#120140]: https://github.com/rust-lang/rust/issues/120140 ------------------------ "##, @@ -7164,6 +7231,17 @@ The tracking issue for this feature is: [#115268] [#115268]: https://github.com/rust-lang/rust/issues/115268 +------------------------ +"##, + }, + Lint { + label: "proc_macro_c_str_literals", + description: r##"# `proc_macro_c_str_literals` + +The tracking issue for this feature is: [#119750] + +[#119750]: https://github.com/rust-lang/rust/issues/119750 + ------------------------ "##, }, @@ -7383,17 +7461,6 @@ The tracking issue for this feature is: [#107792] [#107792]: https://github.com/rust-lang/rust/issues/107792 ------------------------- -"##, - }, - Lint { - label: "raw_os_nonzero", - description: r##"# `raw_os_nonzero` - -The tracking issue for this feature is: [#82363] - -[#82363]: https://github.com/rust-lang/rust/issues/82363 - ------------------------ "##, }, @@ -7553,17 +7620,6 @@ The tracking issue for this feature is: [#93743] [#93743]: https://github.com/rust-lang/rust/issues/93743 ------------------------- -"##, - }, - Lint { - label: "round_ties_even", - description: r##"# `round_ties_even` - -The tracking issue for this feature is: [#96710] - -[#96710]: https://github.com/rust-lang/rust/issues/96710 - ------------------------ "##, }, @@ -7813,17 +7869,6 @@ The tracking issue for this feature is: [#27747] [#27747]: https://github.com/rust-lang/rust/issues/27747 ------------------------- -"##, - }, - Lint { - label: "slice_first_last_chunk", - description: r##"# `slice_first_last_chunk` - -The tracking issue for this feature is: [#111774] - -[#111774]: https://github.com/rust-lang/rust/issues/111774 - ------------------------ "##, }, @@ -7846,17 +7891,6 @@ The tracking issue for this feature is: [#89792] [#89792]: https://github.com/rust-lang/rust/issues/89792 ------------------------- -"##, - }, - Lint { - label: "slice_group_by", - description: r##"# `slice_group_by` - -The tracking issue for this feature is: [#80552] - -[#80552]: https://github.com/rust-lang/rust/issues/80552 - ------------------------ "##, }, @@ -8056,6 +8090,17 @@ The tracking issue for this feature is: [#96137] [#96137]: https://github.com/rust-lang/rust/issues/96137 +------------------------ +"##, + }, + Lint { + label: "split_at_checked", + description: r##"# `split_at_checked` + +The tracking issue for this feature is: [#119128] + +[#119128]: https://github.com/rust-lang/rust/issues/119128 + ------------------------ "##, }, @@ -8192,6 +8237,17 @@ The tracking issue for this feature is: [#15701] [#15701]: https://github.com/rust-lang/rust/issues/15701 +------------------------ +"##, + }, + Lint { + label: "str_from_raw_parts", + description: r##"# `str_from_raw_parts` + +The tracking issue for this feature is: [#119206] + +[#119206]: https://github.com/rust-lang/rust/issues/119206 + ------------------------ "##, }, @@ -8212,6 +8268,17 @@ The tracking issue for this feature is: [#116258] This feature is internal to the Rust compiler and is not intended for general use. +------------------------ +"##, + }, + Lint { + label: "str_lines_remainder", + description: r##"# `str_lines_remainder` + +The tracking issue for this feature is: [#77998] + +[#77998]: https://github.com/rust-lang/rust/issues/77998 + ------------------------ "##, }, @@ -8245,6 +8312,17 @@ The tracking issue for this feature is: [#77998] [#77998]: https://github.com/rust-lang/rust/issues/77998 +------------------------ +"##, + }, + Lint { + label: "strict_overflow_ops", + description: r##"# `strict_overflow_ops` + +The tracking issue for this feature is: [#118260] + +[#118260]: https://github.com/rust-lang/rust/issues/118260 + ------------------------ "##, }, @@ -8758,6 +8836,37 @@ pub fn main() { println!("{:?}", b); } ``` +"##, + }, + Lint { + label: "trait_upcasting", + description: r##"# `trait_upcasting` + +The tracking issue for this feature is: [#65991] + +[#65991]: https://github.com/rust-lang/rust/issues/65991 + +------------------------ + +The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a +trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo` +so long as `Bar: Foo`. + +```rust,edition2018 +#![feature(trait_upcasting)] +#![allow(incomplete_features)] + +trait Foo {} + +trait Bar: Foo {} + +impl Foo for i32 {} + +impl Bar for T {} + +let bar: &dyn Bar = &123; +let foo: &dyn Foo = bar; +``` "##, }, Lint { @@ -10492,6 +10601,11 @@ differing by an underscore."##, label: "clippy::duration_subsec", description: r##"Checks for calculation of subsecond microseconds or milliseconds from other `Duration` methods."##, + }, + Lint { + label: "clippy::eager_transmute", + description: r##"Checks for integer validity checks, followed by a transmute that is (incorrectly) evaluated +eagerly (e.g. using `bool::then_some`)."##, }, Lint { label: "clippy::else_if_without_else", @@ -10510,6 +10624,10 @@ As of this writing, the `never_type` is still a nightly-only experimental API. Therefore, this lint is only triggered if the `never_type` is enabled."##, }, + Lint { + label: "clippy::empty_enum_variants_with_brackets", + description: r##"Finds enum variants without fields that are declared with empty brackets."##, + }, Lint { label: "clippy::empty_line_after_doc_comments", description: r##"Checks for empty lines after documentation comments."##, @@ -10776,7 +10894,7 @@ multithreaded executors are likely to be used for running these Futures."##, Lint { label: "clippy::get_first", description: r##"Checks for usage of `x.get(0)` instead of -`x.first()`."##, +`x.first()` or `x.front()`."##, }, Lint { label: "clippy::get_last_with_len", @@ -10876,6 +10994,11 @@ because `Deref` is a supertrait of `DerefMut`)"##, description: r##"Looks for floating-point expressions that can be expressed using built-in methods to improve accuracy at the cost of performance."##, + }, + Lint { + label: "clippy::incompatible_msrv", + description: r##"This lint checks that no function newer than the defined MSRV (minimum +supported rust version) is used in the crate."##, }, Lint { label: "clippy::inconsistent_digit_grouping", @@ -11028,6 +11151,16 @@ create a `Vec`."##, label: "clippy::iter_count", description: r##"Checks for the use of `.iter().count()`."##, }, + Lint { + label: "clippy::iter_filter_is_ok", + description: r##"Checks for usage of `.filter(Result::is_ok)` that may be replaced with a `.flatten()` call. +This lint will require additional changes to the follow-up calls as it appects the type."##, + }, + Lint { + label: "clippy::iter_filter_is_some", + description: r##"Checks for usage of `.filter(Option::is_some)` that may be replaced with a `.flatten()` call. +This lint will require additional changes to the follow-up calls as it appects the type."##, + }, Lint { label: "clippy::iter_kv_map", description: r##"Checks for iterating a map (`HashMap` or `BTreeMap`) and @@ -11196,6 +11329,14 @@ when `lines` has type `std::io::Lines`."##, label: "clippy::linkedlist", description: r##"Checks for usage of any `LinkedList`, suggesting to use a `Vec` or a `VecDeque` (formerly called `RingBuf`)."##, + }, + Lint { + label: "clippy::lint_groups_priority", + description: r##"Checks for lint groups with the same priority as lints in the `Cargo.toml` +[`[lints]` table](https://doc.rust-lang.org/cargo/reference/manifest.html#the-lints-section). + +This lint will be removed once [cargo#12918](https://github.com/rust-lang/cargo/issues/12918) +is resolved."##, }, Lint { label: "clippy::little_endian_bytes", @@ -11280,6 +11421,7 @@ ascii range"##, description: r##"Checks for manual `is_infinite` reimplementations (i.e., `x == ::INFINITY || x == ::NEG_INFINITY`)."##, }, + Lint { label: "clippy::manual_is_variant_and", description: r##""## }, Lint { label: "clippy::manual_let_else", description: r##"Warn of cases where `let...else` could be used"##, @@ -11556,10 +11698,10 @@ is greater than the largest index used to index into the slice."##, Lint { label: "clippy::missing_enforced_import_renames", description: r##"Checks for imports that do not rename the item as specified -in the `enforce-import-renames` config option. +in the `enforced-import-renames` config option. Note: Even though this lint is warn-by-default, it will only trigger if -import renames are defined in the clippy.toml file."##, +import renames are defined in the `clippy.toml` file."##, }, Lint { label: "clippy::missing_errors_doc", @@ -11947,6 +12089,10 @@ character escapes in C."##, taken to satisfy a bound and suggests to dereference the other argument instead"##, }, + Lint { + label: "clippy::option_as_ref_cloned", + description: r##"Checks for usage of `.as_ref().cloned()` and `.as_mut().cloned()` on `Option`s"##, + }, Lint { label: "clippy::option_as_ref_deref", description: r##"Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as String::as_str)."##, @@ -11958,7 +12104,7 @@ suggests usage of the `env!` macro."##, }, Lint { label: "clippy::option_filter_map", - description: r##"Checks for iterators of `Option`s using ``.filter(Option::is_some).map(Option::unwrap)` that may + description: r##"Checks for iterators of `Option`s using `.filter(Option::is_some).map(Option::unwrap)` that may be replaced with a `.flatten()` call."##, }, Lint { @@ -12144,6 +12290,11 @@ namely `*const T` to `*const U` and `*mut T` to `*mut U`."##, label: "clippy::pub_enum_variant_names", description: r##"Nothing. This lint has been deprecated."##, }, + Lint { + label: "clippy::pub_underscore_fields", + description: r##"Checks whether any field of the struct is prefixed with an `_` (underscore) and also marked +`pub` (public)"##, + }, Lint { label: "clippy::pub_use", description: r##"Restricts the usage of `pub use ...`"## }, Lint { label: "clippy::pub_with_shorthand", @@ -12239,8 +12390,8 @@ value that is going to be dropped without further use."##, Lint { label: "clippy::redundant_closure", description: r##"Checks for closures which just call another function where -the function can be called directly. `unsafe` functions or calls where types -get adjusted are ignored."##, +the function can be called directly. `unsafe` functions, calls where types +get adjusted or where the callee is marked `#[track_caller]` are ignored."##, }, Lint { label: "clippy::redundant_closure_call", @@ -12348,7 +12499,7 @@ they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://gi }, Lint { label: "clippy::result_filter_map", - description: r##"Checks for iterators of `Result`s using ``.filter(Result::is_ok).map(Result::unwrap)` that may + description: r##"Checks for iterators of `Result`s using `.filter(Result::is_ok).map(Result::unwrap)` that may be replaced with a `.flatten()` call."##, }, Lint { @@ -12443,7 +12594,7 @@ see the `unseparated_literal_suffix` lint."##, }, Lint { label: "clippy::serde_api_misuse", - description: r##"Checks for mis-uses of the serde API."##, + description: r##"Checks for misuses of the serde API."##, }, Lint { label: "clippy::shadow_reuse", @@ -12580,6 +12731,12 @@ use an unstable sort than a stable sort."##, label: "clippy::std_instead_of_core", description: r##"Finds items imported through `std` when available through `core`."##, }, + Lint { + label: "clippy::str_split_at_newline", + description: r##"Checks for usages of `str.trim().split(\ +)` and `str.trim().split(\\ +)`."##, + }, Lint { label: "clippy::str_to_string", description: r##"This lint checks for `.to_string()` method calls on values of type `&str`."##, @@ -12674,6 +12831,11 @@ is followed immediately by a newline or the `else` seems to be missing."##, label: "clippy::suspicious_op_assign_impl", description: r##"Lints for suspicious operations in impls of OpAssign, e.g. subtracting elements in an AddAssign impl."##, + }, + Lint { + label: "clippy::suspicious_open_options", + description: r##"Checks for the suspicious use of `OpenOptions::create()` +without an explicit `OpenOptions::truncate()`."##, }, Lint { label: "clippy::suspicious_operation_groupings", @@ -12724,6 +12886,10 @@ either `ignore`, `no_run` or `compile_fail`."##, description: r##"Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module (marked with `#[cfg(test)]`)."##, }, + Lint { + label: "clippy::thread_local_initializer_can_be_made_const", + description: r##"Suggests to use `const` in `thread_local!` macro if possible."##, + }, Lint { label: "clippy::to_digit_is_some", description: r##"Checks for `.to_digit(..).is_some()` on `char`s."##, @@ -12734,6 +12900,10 @@ either `ignore`, `no_run` or `compile_fail`."##, applied to a type that implements [`Display`](https://doc.rust-lang.org/std/fmt/trait.Display.html) in a macro that does formatting."##, }, + Lint { + label: "clippy::to_string_trait_impl", + description: r##"Checks for direct implementations of `ToString`."##, + }, Lint { label: "clippy::todo", description: r##"Checks for usage of `todo!`."## }, Lint { label: "clippy::too_many_arguments", @@ -12847,7 +13017,7 @@ declarations above a certain complexity threshold."##, }, Lint { label: "clippy::unchecked_duration_subtraction", - description: r##"Lints subtraction between an [`Instant`] and a [`Duration`]."##, + description: r##"Lints subtraction between an `Instant` and a `Duration`."##, }, Lint { label: "clippy::unconditional_recursion", @@ -13001,6 +13171,10 @@ sub-expression."##, label: "clippy::unnecessary_owned_empty_strings", description: r##"Detects cases of owned empty strings being passed as an argument to a function expecting `&str`"##, }, + Lint { + label: "clippy::unnecessary_result_map_or_else", + description: r##"Checks for usage of `.map_or_else()` map closure for `Result` type."##, + }, Lint { label: "clippy::unnecessary_safety_comment", description: r##"Checks for `// SAFETY: ` comments on safe code."##, @@ -13510,7 +13684,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::correctness", - description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_slice_different_sizes, clippy::deprecated_semver, clippy::derive_ord_xor_partial_ord, clippy::derived_hash_with_manual_eq, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::if_let_mutex, clippy::ifs_same_cond, clippy::impl_hash_borrow_with_str_and_bytes, clippy::impossible_comparisons, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iter_skip_zero, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::overly_complex_bool_expr, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::read_line_without_trim, clippy::recursive_format_impl, clippy::redundant_comparisons, clippy::redundant_locals, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::transmute_null_to_fn, clippy::transmuting_null, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, + description: r##"lint group for: clippy::absurd_extreme_comparisons, clippy::almost_swapped, clippy::approx_constant, clippy::async_yields_async, clippy::bad_bit_mask, clippy::cast_slice_different_sizes, clippy::deprecated_semver, clippy::derive_ord_xor_partial_ord, clippy::derived_hash_with_manual_eq, clippy::eager_transmute, clippy::enum_clike_unportable_variant, clippy::eq_op, clippy::erasing_op, clippy::fn_address_comparisons, clippy::if_let_mutex, clippy::ifs_same_cond, clippy::impl_hash_borrow_with_str_and_bytes, clippy::impossible_comparisons, clippy::ineffective_bit_mask, clippy::infinite_iter, clippy::inherent_to_string_shadow_display, clippy::inline_fn_without_body, clippy::invalid_null_ptr_usage, clippy::invalid_regex, clippy::invisible_characters, clippy::iter_next_loop, clippy::iter_skip_zero, clippy::iterator_step_by_zero, clippy::let_underscore_lock, clippy::lint_groups_priority, clippy::match_str_case_mismatch, clippy::mem_replace_with_uninit, clippy::min_max, clippy::mismatched_target_os, clippy::mistyped_literal_suffixes, clippy::modulo_one, clippy::mut_from_ref, clippy::never_loop, clippy::non_octal_unix_permissions, clippy::nonsensical_open_options, clippy::not_unsafe_ptr_arg_deref, clippy::option_env_unwrap, clippy::out_of_bounds_indexing, clippy::overly_complex_bool_expr, clippy::panicking_unwrap, clippy::possible_missing_comma, clippy::read_line_without_trim, clippy::recursive_format_impl, clippy::redundant_comparisons, clippy::redundant_locals, clippy::reversed_empty_ranges, clippy::self_assignment, clippy::serde_api_misuse, clippy::size_of_in_element_count, clippy::suspicious_splitn, clippy::transmute_null_to_fn, clippy::transmuting_null, clippy::uninit_assumed_init, clippy::uninit_vec, clippy::unit_cmp, clippy::unit_hash, clippy::unit_return_expecting_ord, clippy::unsound_collection_transmute, clippy::unused_io_amount, clippy::useless_attribute, clippy::vec_resize_to_zero, clippy::while_immutable_condition, clippy::wrong_transmute, clippy::zst_offset"##, }, children: &[ "clippy::absurd_extreme_comparisons", @@ -13522,6 +13696,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::deprecated_semver", "clippy::derive_ord_xor_partial_ord", "clippy::derived_hash_with_manual_eq", + "clippy::eager_transmute", "clippy::enum_clike_unportable_variant", "clippy::eq_op", "clippy::erasing_op", @@ -13541,6 +13716,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::iter_skip_zero", "clippy::iterator_step_by_zero", "clippy::let_underscore_lock", + "clippy::lint_groups_priority", "clippy::match_str_case_mismatch", "clippy::mem_replace_with_uninit", "clippy::min_max", @@ -13665,7 +13841,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::pedantic", - description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, + description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##, }, children: &[ "clippy::bool_to_int_with_if", @@ -13705,6 +13881,8 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::into_iter_without_iter", "clippy::invalid_upcast_comparisons", "clippy::items_after_statements", + "clippy::iter_filter_is_ok", + "clippy::iter_filter_is_some", "clippy::iter_not_returning_iterator", "clippy::iter_without_into_iter", "clippy::large_digit_groups", @@ -13715,6 +13893,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::macro_use_imports", "clippy::manual_assert", "clippy::manual_instant_elapsed", + "clippy::manual_is_variant_and", "clippy::manual_let_else", "clippy::manual_ok_or", "clippy::manual_string_new", @@ -13741,9 +13920,11 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::needless_raw_string_hashes", "clippy::no_effect_underscore_binding", "clippy::no_mangle_with_rust_abi", + "clippy::option_as_ref_cloned", "clippy::option_option", "clippy::ptr_as_ptr", "clippy::ptr_cast_constness", + "clippy::pub_underscore_fields", "clippy::range_minus_one", "clippy::range_plus_one", "clippy::redundant_closure_for_method_calls", @@ -13757,6 +13938,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::similar_names", "clippy::single_match_else", "clippy::stable_sort_primitive", + "clippy::str_split_at_newline", "clippy::string_add_assign", "clippy::struct_excessive_bools", "clippy::struct_field_names", @@ -13783,7 +13965,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::perf", - description: r##"lint group for: clippy::box_collection, clippy::box_default, clippy::boxed_local, clippy::cmp_owned, clippy::collapsible_str_replace, clippy::drain_collect, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_collect, clippy::format_in_format_args, clippy::iter_nth, clippy::iter_overeager_cloned, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_retain, clippy::manual_str_repeat, clippy::manual_try_fold, clippy::map_entry, clippy::missing_spin_loop, clippy::redundant_allocation, clippy::result_large_err, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push, clippy::waker_clone_wake"##, + description: r##"lint group for: clippy::box_collection, clippy::box_default, clippy::boxed_local, clippy::cmp_owned, clippy::collapsible_str_replace, clippy::drain_collect, clippy::expect_fun_call, clippy::extend_with_drain, clippy::format_collect, clippy::format_in_format_args, clippy::iter_nth, clippy::iter_overeager_cloned, clippy::large_const_arrays, clippy::large_enum_variant, clippy::manual_memcpy, clippy::manual_retain, clippy::manual_str_repeat, clippy::manual_try_fold, clippy::map_entry, clippy::missing_spin_loop, clippy::redundant_allocation, clippy::result_large_err, clippy::single_char_pattern, clippy::slow_vector_initialization, clippy::thread_local_initializer_can_be_made_const, clippy::to_string_in_format_args, clippy::unnecessary_to_owned, clippy::useless_vec, clippy::vec_init_then_push, clippy::waker_clone_wake"##, }, children: &[ "clippy::box_collection", @@ -13810,6 +13992,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::result_large_err", "clippy::single_char_pattern", "clippy::slow_vector_initialization", + "clippy::thread_local_initializer_can_be_made_const", "clippy::to_string_in_format_args", "clippy::unnecessary_to_owned", "clippy::useless_vec", @@ -13820,7 +14003,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::restriction", - description: r##"lint group for: clippy::absolute_paths, clippy::alloc_instead_of_core, clippy::allow_attributes, clippy::allow_attributes_without_reason, clippy::arithmetic_side_effects, clippy::as_conversions, clippy::as_underscore, clippy::assertions_on_result_states, clippy::big_endian_bytes, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::default_union_representation, clippy::deref_by_slicing, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::empty_drop, clippy::empty_structs_with_brackets, clippy::error_impl_error, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::format_push_string, clippy::get_unwrap, clippy::host_endian_bytes, clippy::if_then_some_else_none, clippy::impl_trait_in_params, clippy::implicit_return, clippy::indexing_slicing, clippy::infinite_loop, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_division, clippy::iter_over_hash_type, clippy::large_include_file, clippy::let_underscore_must_use, clippy::let_underscore_untyped, clippy::little_endian_bytes, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::min_ident_chars, clippy::missing_assert_message, clippy::missing_asserts_for_indexing, clippy::missing_docs_in_private_items, clippy::missing_inline_in_public_items, clippy::missing_trait_methods, clippy::mixed_read_write_in_expression, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::multiple_unsafe_ops_per_block, clippy::mutex_atomic, clippy::needless_raw_strings, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::partial_pub_fields, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::pub_use, clippy::pub_with_shorthand, clippy::pub_without_shorthand, clippy::question_mark_used, clippy::rc_buffer, clippy::rc_mutex, clippy::redundant_type_annotations, clippy::ref_patterns, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::semicolon_inside_block, clippy::semicolon_outside_block, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::single_call_fn, clippy::single_char_lifetime_names, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::str_to_string, clippy::string_add, clippy::string_lit_chars_any, clippy::string_slice, clippy::string_to_string, clippy::suspicious_xor_used_as_pow, clippy::tests_outside_test_module, clippy::todo, clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_safety_comment, clippy::unnecessary_safety_doc, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, + description: r##"lint group for: clippy::absolute_paths, clippy::alloc_instead_of_core, clippy::allow_attributes, clippy::allow_attributes_without_reason, clippy::arithmetic_side_effects, clippy::as_conversions, clippy::as_underscore, clippy::assertions_on_result_states, clippy::big_endian_bytes, clippy::clone_on_ref_ptr, clippy::create_dir, clippy::dbg_macro, clippy::decimal_literal_representation, clippy::default_numeric_fallback, clippy::default_union_representation, clippy::deref_by_slicing, clippy::disallowed_script_idents, clippy::else_if_without_else, clippy::empty_drop, clippy::empty_enum_variants_with_brackets, clippy::empty_structs_with_brackets, clippy::error_impl_error, clippy::exhaustive_enums, clippy::exhaustive_structs, clippy::exit, clippy::expect_used, clippy::filetype_is_file, clippy::float_arithmetic, clippy::float_cmp_const, clippy::fn_to_numeric_cast_any, clippy::format_push_string, clippy::get_unwrap, clippy::host_endian_bytes, clippy::if_then_some_else_none, clippy::impl_trait_in_params, clippy::implicit_return, clippy::indexing_slicing, clippy::infinite_loop, clippy::inline_asm_x86_att_syntax, clippy::inline_asm_x86_intel_syntax, clippy::integer_division, clippy::iter_over_hash_type, clippy::large_include_file, clippy::let_underscore_must_use, clippy::let_underscore_untyped, clippy::little_endian_bytes, clippy::lossy_float_literal, clippy::map_err_ignore, clippy::mem_forget, clippy::min_ident_chars, clippy::missing_assert_message, clippy::missing_asserts_for_indexing, clippy::missing_docs_in_private_items, clippy::missing_inline_in_public_items, clippy::missing_trait_methods, clippy::mixed_read_write_in_expression, clippy::mod_module_files, clippy::modulo_arithmetic, clippy::multiple_inherent_impl, clippy::multiple_unsafe_ops_per_block, clippy::mutex_atomic, clippy::needless_raw_strings, clippy::non_ascii_literal, clippy::panic, clippy::panic_in_result_fn, clippy::partial_pub_fields, clippy::pattern_type_mismatch, clippy::print_stderr, clippy::print_stdout, clippy::pub_use, clippy::pub_with_shorthand, clippy::pub_without_shorthand, clippy::question_mark_used, clippy::rc_buffer, clippy::rc_mutex, clippy::redundant_type_annotations, clippy::ref_patterns, clippy::rest_pat_in_fully_bound_structs, clippy::same_name_method, clippy::self_named_module_files, clippy::semicolon_inside_block, clippy::semicolon_outside_block, clippy::separated_literal_suffix, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::single_call_fn, clippy::single_char_lifetime_names, clippy::std_instead_of_alloc, clippy::std_instead_of_core, clippy::str_to_string, clippy::string_add, clippy::string_lit_chars_any, clippy::string_slice, clippy::string_to_string, clippy::suspicious_xor_used_as_pow, clippy::tests_outside_test_module, clippy::todo, clippy::try_err, clippy::undocumented_unsafe_blocks, clippy::unimplemented, clippy::unnecessary_safety_comment, clippy::unnecessary_safety_doc, clippy::unnecessary_self_imports, clippy::unneeded_field_pattern, clippy::unreachable, clippy::unseparated_literal_suffix, clippy::unwrap_in_result, clippy::unwrap_used, clippy::use_debug, clippy::verbose_file_reads, clippy::wildcard_enum_match_arm"##, }, children: &[ "clippy::absolute_paths", @@ -13842,6 +14025,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::disallowed_script_idents", "clippy::else_if_without_else", "clippy::empty_drop", + "clippy::empty_enum_variants_with_brackets", "clippy::empty_structs_with_brackets", "clippy::error_impl_error", "clippy::exhaustive_enums", @@ -13939,7 +14123,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::style", - description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blocks_in_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::default_instead_of_iter_empty, clippy::disallowed_macros, clippy::disallowed_methods, clippy::disallowed_names, clippy::disallowed_types, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::err_expect, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::filter_map_bool_then, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::get_first, clippy::if_same_then_else, clippy::implicit_saturating_add, clippy::implicit_saturating_sub, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::init_numbered_fields, clippy::into_iter_on_ref, clippy::is_digit_ascii_radix, clippy::items_after_test_module, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::let_unit_value, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_bits, clippy::manual_is_ascii_check, clippy::manual_is_finite, clippy::manual_is_infinite, clippy::manual_map, clippy::manual_next_back, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::manual_while_let_some, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_enforced_import_renames, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::needless_doctest_main, clippy::needless_else, clippy::needless_late_init, clippy::needless_parens_on_range_literals, clippy::needless_pub_self, clippy::needless_range_loop, clippy::needless_return, clippy::needless_return_with_question_mark, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::non_minimal_cfg, clippy::obfuscated_if_else, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_err_ok, clippy::option_map_or_none, clippy::partialeq_to_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::toplevel_ref_arg, clippy::trim_split_whitespace, clippy::unnecessary_fallible_conversions, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unnecessary_owned_empty_strings, clippy::unsafe_removed_from_name, clippy::unused_enumerate_index, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, + description: r##"lint group for: clippy::assertions_on_constants, clippy::assign_op_pattern, clippy::blocks_in_conditions, clippy::bool_assert_comparison, clippy::borrow_interior_mutable_const, clippy::builtin_type_shadow, clippy::bytes_nth, clippy::chars_last_cmp, clippy::chars_next_cmp, clippy::cmp_null, clippy::collapsible_else_if, clippy::collapsible_if, clippy::collapsible_match, clippy::comparison_chain, clippy::comparison_to_empty, clippy::declare_interior_mutable_const, clippy::default_instead_of_iter_empty, clippy::disallowed_macros, clippy::disallowed_methods, clippy::disallowed_names, clippy::disallowed_types, clippy::double_must_use, clippy::double_neg, clippy::duplicate_underscore_argument, clippy::enum_variant_names, clippy::err_expect, clippy::excessive_precision, clippy::field_reassign_with_default, clippy::filter_map_bool_then, clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation, clippy::for_kv_map, clippy::from_over_into, clippy::from_str_radix_10, clippy::get_first, clippy::if_same_then_else, clippy::implicit_saturating_add, clippy::implicit_saturating_sub, clippy::inconsistent_digit_grouping, clippy::infallible_destructuring_match, clippy::inherent_to_string, clippy::init_numbered_fields, clippy::into_iter_on_ref, clippy::is_digit_ascii_radix, clippy::items_after_test_module, clippy::iter_cloned_collect, clippy::iter_next_slice, clippy::iter_nth_zero, clippy::iter_skip_next, clippy::just_underscores_and_digits, clippy::len_without_is_empty, clippy::len_zero, clippy::let_and_return, clippy::let_unit_value, clippy::main_recursion, clippy::manual_async_fn, clippy::manual_bits, clippy::manual_is_ascii_check, clippy::manual_is_finite, clippy::manual_is_infinite, clippy::manual_map, clippy::manual_next_back, clippy::manual_non_exhaustive, clippy::manual_range_contains, clippy::manual_saturating_arithmetic, clippy::manual_while_let_some, clippy::map_clone, clippy::map_collect_result_unit, clippy::match_like_matches_macro, clippy::match_overlapping_arm, clippy::match_ref_pats, clippy::match_result_ok, clippy::mem_replace_option_with_none, clippy::mem_replace_with_default, clippy::missing_enforced_import_renames, clippy::missing_safety_doc, clippy::mixed_case_hex_literals, clippy::module_inception, clippy::must_use_unit, clippy::mut_mutex_lock, clippy::needless_borrow, clippy::needless_borrows_for_generic_args, clippy::needless_doctest_main, clippy::needless_else, clippy::needless_late_init, clippy::needless_parens_on_range_literals, clippy::needless_pub_self, clippy::needless_range_loop, clippy::needless_return, clippy::needless_return_with_question_mark, clippy::neg_multiply, clippy::new_ret_no_self, clippy::new_without_default, clippy::non_minimal_cfg, clippy::obfuscated_if_else, clippy::ok_expect, clippy::op_ref, clippy::option_map_or_err_ok, clippy::option_map_or_none, clippy::partialeq_to_none, clippy::print_literal, clippy::print_with_newline, clippy::println_empty_string, clippy::ptr_arg, clippy::ptr_eq, clippy::question_mark, clippy::redundant_closure, clippy::redundant_field_names, clippy::redundant_pattern, clippy::redundant_pattern_matching, clippy::redundant_static_lifetimes, clippy::result_map_or_into_option, clippy::result_unit_err, clippy::same_item_push, clippy::self_named_constructors, clippy::should_implement_trait, clippy::single_char_add_str, clippy::single_component_path_imports, clippy::single_match, clippy::string_extend_chars, clippy::tabs_in_doc_comments, clippy::to_digit_is_some, clippy::to_string_trait_impl, clippy::toplevel_ref_arg, clippy::trim_split_whitespace, clippy::unnecessary_fallible_conversions, clippy::unnecessary_fold, clippy::unnecessary_lazy_evaluations, clippy::unnecessary_mut_passed, clippy::unnecessary_owned_empty_strings, clippy::unsafe_removed_from_name, clippy::unused_enumerate_index, clippy::unused_unit, clippy::unusual_byte_groupings, clippy::unwrap_or_default, clippy::upper_case_acronyms, clippy::while_let_on_iterator, clippy::write_literal, clippy::write_with_newline, clippy::writeln_empty_string, clippy::wrong_self_convention, clippy::zero_ptr"##, }, children: &[ "clippy::assertions_on_constants", @@ -14064,6 +14248,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::string_extend_chars", "clippy::tabs_in_doc_comments", "clippy::to_digit_is_some", + "clippy::to_string_trait_impl", "clippy::toplevel_ref_arg", "clippy::trim_split_whitespace", "clippy::unnecessary_fallible_conversions", @@ -14088,7 +14273,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ LintGroup { lint: Lint { label: "clippy::suspicious", - description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion"##, + description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_result_map_or_else"##, }, children: &[ "clippy::almost_complete_range", @@ -14110,6 +14295,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::forget_non_drop", "clippy::four_forward_slashes", "clippy::from_raw_with_void_ptr", + "clippy::incompatible_msrv", "clippy::ineffective_open_options", "clippy::iter_out_of_bounds", "clippy::join_absolute_paths", @@ -14139,12 +14325,14 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[ "clippy::suspicious_else_formatting", "clippy::suspicious_map", "clippy::suspicious_op_assign_impl", + "clippy::suspicious_open_options", "clippy::suspicious_to_owned", "clippy::suspicious_unary_op_formatting", "clippy::swap_ptr_to_ref", "clippy::test_attr_in_doctest", "clippy::type_id_on_box", "clippy::unconditional_recursion", + "clippy::unnecessary_result_map_or_else", ], }, ]; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs index 9363bdfa14b2a..0b5ad7060e043 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs @@ -35,7 +35,7 @@ pub fn pick_token(mut tokens: TokenAtOffset) -> Option /// Converts the mod path struct into its ast representation. pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { - let _p = profile::span("mod_path_to_ast"); + let _p = tracing::span!(tracing::Level::INFO, "mod_path_to_ast").entered(); let mut segments = Vec::new(); let mut is_abs = false; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 089bd44c2a5da..cb3f01f345825 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -208,7 +208,8 @@ impl ImportAssets { prefer_no_std: bool, prefer_prelude: bool, ) -> impl Iterator { - let _p = profile::span("import_assets::search_for_imports"); + let _p = + tracing::span!(tracing::Level::INFO, "import_assets::search_for_imports").entered(); self.search_for(sema, Some(prefix_kind), prefer_no_std, prefer_prelude) } @@ -219,7 +220,8 @@ impl ImportAssets { prefer_no_std: bool, prefer_prelude: bool, ) -> impl Iterator { - let _p = profile::span("import_assets::search_for_relative_paths"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::search_for_relative_paths") + .entered(); self.search_for(sema, None, prefer_no_std, prefer_prelude) } @@ -260,7 +262,7 @@ impl ImportAssets { prefer_no_std: bool, prefer_prelude: bool, ) -> impl Iterator { - let _p = profile::span("import_assets::search_for"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::search_for").entered(); let scope = match sema.scope(&self.candidate_node) { Some(it) => it, @@ -305,7 +307,7 @@ impl ImportAssets { } fn scope_definitions(&self, sema: &Semantics<'_, RootDatabase>) -> FxHashSet { - let _p = profile::span("import_assets::scope_definitions"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::scope_definitions").entered(); let mut scope_definitions = FxHashSet::default(); if let Some(scope) = sema.scope(&self.candidate_node) { scope.process_all_names(&mut |_, scope_def| { @@ -323,7 +325,8 @@ fn path_applicable_imports( mod_path: impl Fn(ItemInNs) -> Option + Copy, scope_filter: impl Fn(ItemInNs) -> bool + Copy, ) -> FxHashSet { - let _p = profile::span("import_assets::path_applicable_imports"); + let _p = + tracing::span!(tracing::Level::INFO, "import_assets::path_applicable_imports").entered(); match &path_candidate.qualifier { None => { @@ -370,7 +373,7 @@ fn import_for_item( original_item: ItemInNs, scope_filter: impl Fn(ItemInNs) -> bool, ) -> Option { - let _p = profile::span("import_assets::import_for_item"); + let _p = tracing::span!(tracing::Level::INFO, "import_assets::import_for_item").entered(); let [first_segment, ..] = unresolved_qualifier else { return None }; let item_as_assoc = item_as_assoc(db, original_item); @@ -504,7 +507,8 @@ fn trait_applicable_items( mod_path: impl Fn(ItemInNs) -> Option, scope_filter: impl Fn(hir::Trait) -> bool, ) -> FxHashSet { - let _p = profile::span("import_assets::trait_applicable_items"); + let _p = + tracing::span!(tracing::Level::INFO, "import_assets::trait_applicable_items").entered(); let db = sema.db; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs index 09b4a1c1baac0..f29f91eea84f5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs @@ -17,6 +17,7 @@ use syntax::{ use crate::{ imports::merge_imports::{ common_prefix, eq_attrs, eq_visibility, try_merge_imports, use_tree_cmp, MergeBehavior, + NormalizationStyle, }, RootDatabase, }; @@ -40,6 +41,15 @@ pub enum ImportGranularity { One, } +impl From for NormalizationStyle { + fn from(granularity: ImportGranularity) -> Self { + match granularity { + ImportGranularity::One => NormalizationStyle::One, + _ => NormalizationStyle::Default, + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct InsertUseConfig { pub granularity: ImportGranularity, @@ -184,7 +194,7 @@ fn insert_use_with_alias_option( cfg: &InsertUseConfig, alias: Option, ) { - let _p = profile::span("insert_use"); + let _p = tracing::span!(tracing::Level::INFO, "insert_use").entered(); let mut mb = match cfg.granularity { ImportGranularity::Crate => Some(MergeBehavior::Crate), ImportGranularity::Module => Some(MergeBehavior::Module), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs index 2ed6069887138..6b0fecae26758 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs @@ -635,7 +635,7 @@ use std::io;", check_one( "std::io", r"use {std::fmt::{Result, Display}};", - r"use {std::{fmt::{Result, Display}, io}};", + r"use {std::{fmt::{Display, Result}, io}};", ); } @@ -650,12 +650,12 @@ fn merge_groups_full() { check_crate( "std::io", r"use std::fmt::{Result, Display};", - r"use std::{fmt::{Result, Display}, io};", + r"use std::{fmt::{Display, Result}, io};", ); check_one( "std::io", r"use {std::fmt::{Result, Display}};", - r"use {std::{fmt::{Result, Display}, io}};", + r"use {std::{fmt::{Display, Result}, io}};", ); } @@ -749,12 +749,12 @@ fn merge_groups_full_nested_deep() { check_crate( "std::foo::bar::quux::Baz", r"use std::foo::bar::{Qux, quux::{Fez, Fizz}};", - r"use std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}};", + r"use std::foo::bar::{quux::{Baz, Fez, Fizz}, Qux};", ); check_one( "std::foo::bar::quux::Baz", r"use {std::foo::bar::{Qux, quux::{Fez, Fizz}}};", - r"use {std::foo::bar::{Qux, quux::{Baz, Fez, Fizz}}};", + r"use {std::foo::bar::{quux::{Baz, Fez, Fizz}, Qux}};", ); } @@ -763,7 +763,7 @@ fn merge_groups_full_nested_long() { check_crate( "std::foo::bar::Baz", r"use std::{foo::bar::Qux};", - r"use std::{foo::bar::{Baz, Qux}};", + r"use std::foo::bar::{Baz, Qux};", ); } @@ -772,12 +772,12 @@ fn merge_groups_last_nested_long() { check_crate( "std::foo::bar::Baz", r"use std::{foo::bar::Qux};", - r"use std::{foo::bar::{Baz, Qux}};", + r"use std::foo::bar::{Baz, Qux};", ); check_one( "std::foo::bar::Baz", r"use {std::{foo::bar::Qux}};", - r"use {std::{foo::bar::{Baz, Qux}}};", + r"use {std::foo::bar::{Baz, Qux}};", ); } @@ -898,7 +898,7 @@ fn merge_glob() { r" use syntax::{SyntaxKind::*};", r" -use syntax::{SyntaxKind::{self, *}};", +use syntax::SyntaxKind::{self, *};", ) } @@ -907,7 +907,7 @@ fn merge_glob_nested() { check_crate( "foo::bar::quux::Fez", r"use foo::bar::{Baz, quux::*};", - r"use foo::bar::{Baz, quux::{Fez, *}};", + r"use foo::bar::{quux::{Fez, *}, Baz};", ) } @@ -1211,7 +1211,7 @@ fn insert_with_renamed_import_complex_use() { use self::foo::{self, Foo as _, Bar}; "#, r#" -use self::foo::{self, Foo, Bar}; +use self::foo::{self, Bar, Foo}; "#, &InsertUseConfig { granularity: ImportGranularity::Crate, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs index 7ec38c317df30..b153aafa0e179 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs @@ -1,15 +1,17 @@ //! Handle syntactic aspects of merging UseTrees. use std::cmp::Ordering; -use std::iter::empty; use itertools::{EitherOrBoth, Itertools}; use parser::T; use stdx::is_upper_snake_case; use syntax::{ algo, - ast::{self, make, AstNode, HasAttrs, HasName, HasVisibility, PathSegmentKind}, + ast::{ + self, edit_in_place::Removable, make, AstNode, HasAttrs, HasName, HasVisibility, + PathSegmentKind, + }, ted::{self, Position}, - Direction, + Direction, SyntaxElement, }; use crate::syntax_helpers::node_ext::vis_eq; @@ -58,6 +60,10 @@ pub fn try_merge_imports( let lhs_tree = lhs.use_tree()?; let rhs_tree = rhs.use_tree()?; try_merge_trees_mut(&lhs_tree, &rhs_tree, merge_behavior)?; + + // Ignore `None` result because normalization should not affect the merge result. + try_normalize_use_tree_mut(&lhs_tree, merge_behavior.into()); + Some(lhs) } @@ -71,6 +77,10 @@ pub fn try_merge_trees( let lhs = lhs.clone_subtree().clone_for_update(); let rhs = rhs.clone_subtree().clone_for_update(); try_merge_trees_mut(&lhs, &rhs, merge)?; + + // Ignore `None` result because normalization should not affect the merge result. + try_normalize_use_tree_mut(&lhs, merge.into()); + Some(lhs) } @@ -173,61 +183,301 @@ fn recursive_merge(lhs: &ast::UseTree, rhs: &ast::UseTree, merge: MergeBehavior) } Err(insert_idx) => { use_trees.insert(insert_idx, rhs_t.clone()); - match lhs.use_tree_list() { - // Creates a new use tree list with the item. - None => lhs.get_or_create_use_tree_list().add_use_tree(rhs_t), - // Recreates the use tree list with sorted items (see `use_tree_cmp` doc). - Some(use_tree_list) => { - if use_tree_list.l_curly_token().is_none() { - ted::insert_raw( - Position::first_child_of(use_tree_list.syntax()), - make::token(T!['{']), - ); - } - if use_tree_list.r_curly_token().is_none() { - ted::insert_raw( - Position::last_child_of(use_tree_list.syntax()), - make::token(T!['}']), - ); - } + // We simply add the use tree to the end of tree list. Ordering of use trees + // and imports is done by the `try_normalize_*` functions. The sorted `use_trees` + // vec is only used for binary search. + lhs.get_or_create_use_tree_list().add_use_tree(rhs_t); + } + } + } + Some(()) +} - let mut elements = Vec::new(); - for (idx, tree) in use_trees.iter().enumerate() { - if idx > 0 { - elements.push(make::token(T![,]).into()); - elements.push(make::tokens::single_space().into()); - } - elements.push(tree.syntax().clone().into()); - } +/// Style to follow when normalizing a use tree. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum NormalizationStyle { + /// Merges all descendant use tree lists with only one child use tree into their parent use tree. + /// + /// Examples: + /// - `foo::{bar::{Qux}}` -> `foo::bar::Qux` + /// - `foo::{bar::{self}}` -> `foo::bar` + /// - `{foo::bar}` -> `foo::bar` + Default, + /// Same as default but wraps the root use tree in a use tree list. + /// + /// Examples: + /// - `foo::{bar::{Qux}}` -> `{foo::bar::Qux}` + /// - `foo::{bar::{self}}` -> `{foo::bar}` + /// - `{foo::bar}` -> `{foo::bar}` + One, +} + +impl From for NormalizationStyle { + fn from(mb: MergeBehavior) -> Self { + match mb { + MergeBehavior::One => NormalizationStyle::One, + _ => NormalizationStyle::Default, + } + } +} + +/// Normalizes a use item by: +/// - Ordering all use trees +/// - Merging use trees with common prefixes +/// - Removing redundant braces based on the specified normalization style +/// (see [`NormalizationStyle`] doc) +/// +/// Examples: +/// +/// Using the "Default" normalization style +/// +/// - `foo::{bar::Qux, bar::{self}}` -> `foo::bar::{self, Qux}` +/// - `foo::bar::{self}` -> `foo::bar` +/// - `{foo::bar}` -> `foo::bar` +/// +/// Using the "One" normalization style +/// +/// - `foo::{bar::Qux, bar::{self}}` -> `{foo::bar::{self, Qux}}` +/// - `foo::bar::{self}` -> `{foo::bar}` +/// - `foo::bar` -> `{foo::bar}` +pub fn try_normalize_import(use_item: &ast::Use, style: NormalizationStyle) -> Option { + let use_item = use_item.clone_subtree().clone_for_update(); + try_normalize_use_tree_mut(&use_item.use_tree()?, style)?; + Some(use_item) +} + +/// Normalizes a use tree (see [`try_normalize_import`] doc). +pub fn try_normalize_use_tree( + use_tree: &ast::UseTree, + style: NormalizationStyle, +) -> Option { + let use_tree = use_tree.clone_subtree().clone_for_update(); + try_normalize_use_tree_mut(&use_tree, style)?; + Some(use_tree) +} + +pub fn try_normalize_use_tree_mut( + use_tree: &ast::UseTree, + style: NormalizationStyle, +) -> Option<()> { + if style == NormalizationStyle::One { + let mut modified = false; + modified |= use_tree.wrap_in_tree_list().is_some(); + modified |= recursive_normalize(use_tree, style).is_some(); + if !modified { + // Either the use tree was already normalized or its semantically empty. + return None; + } + } else { + recursive_normalize(use_tree, NormalizationStyle::Default)?; + } + Some(()) +} - let start = use_tree_list - .l_curly_token() - .and_then(|l_curly| { - algo::non_trivia_sibling(l_curly.into(), Direction::Next) - }) - .filter(|it| it.kind() != T!['}']); - let end = use_tree_list - .r_curly_token() - .and_then(|r_curly| { - algo::non_trivia_sibling(r_curly.into(), Direction::Prev) - }) - .filter(|it| it.kind() != T!['{']); - if let Some((start, end)) = start.zip(end) { - // Attempt to insert elements while preserving preceding and trailing trivia. - ted::replace_all(start..=end, elements); +/// Recursively normalizes a use tree and its subtrees (if any). +fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Option<()> { + let use_tree_list = use_tree.use_tree_list()?; + let merge_subtree_into_parent_tree = |single_subtree: &ast::UseTree| { + let merged_path = match (use_tree.path(), single_subtree.path()) { + (None, None) => None, + (Some(outer), None) => Some(outer), + (None, Some(inner)) if path_is_self(&inner) => None, + (None, Some(inner)) => Some(inner), + (Some(outer), Some(inner)) if path_is_self(&inner) => Some(outer), + (Some(outer), Some(inner)) => Some(make::path_concat(outer, inner).clone_for_update()), + }; + if merged_path.is_some() + || single_subtree.use_tree_list().is_some() + || single_subtree.star_token().is_some() + { + ted::remove_all_iter(use_tree.syntax().children_with_tokens()); + if let Some(path) = merged_path { + ted::insert_raw(Position::first_child_of(use_tree.syntax()), path.syntax()); + if single_subtree.use_tree_list().is_some() || single_subtree.star_token().is_some() + { + ted::insert_raw( + Position::last_child_of(use_tree.syntax()), + make::token(T![::]), + ); + } + } + if let Some(inner_use_tree_list) = single_subtree.use_tree_list() { + ted::insert_raw( + Position::last_child_of(use_tree.syntax()), + inner_use_tree_list.syntax(), + ); + } else if single_subtree.star_token().is_some() { + ted::insert_raw(Position::last_child_of(use_tree.syntax()), make::token(T![*])); + } else if let Some(rename) = single_subtree.rename() { + ted::insert_raw( + Position::last_child_of(use_tree.syntax()), + make::tokens::single_space(), + ); + ted::insert_raw(Position::last_child_of(use_tree.syntax()), rename.syntax()); + } + Some(()) + } else { + // Bail on semantically empty use trees. + None + } + }; + let one_style_tree_list = |subtree: &ast::UseTree| match ( + subtree.path().is_none() && subtree.star_token().is_none() && subtree.rename().is_none(), + subtree.use_tree_list(), + ) { + (true, tree_list) => tree_list, + _ => None, + }; + let add_element_to_list = |elem: SyntaxElement, elements: &mut Vec| { + if !elements.is_empty() { + elements.push(make::token(T![,]).into()); + elements.push(make::tokens::single_space().into()); + } + elements.push(elem); + }; + if let Some((single_subtree,)) = use_tree_list.use_trees().collect_tuple() { + if style == NormalizationStyle::One { + // Only normalize descendant subtrees if the normalization style is "one". + recursive_normalize(&single_subtree, NormalizationStyle::Default)?; + } else { + // Otherwise, merge the single subtree into it's parent (if possible) + // and then normalize the result. + merge_subtree_into_parent_tree(&single_subtree)?; + recursive_normalize(use_tree, style); + } + } else { + // Tracks whether any changes have been made to the use tree. + let mut modified = false; + + // Recursively un-nests (if necessary) and then normalizes each subtree in the tree list. + for subtree in use_tree_list.use_trees() { + if let Some(one_tree_list) = one_style_tree_list(&subtree) { + let mut elements = Vec::new(); + let mut one_tree_list_iter = one_tree_list.use_trees(); + let mut prev_skipped = Vec::new(); + loop { + let mut prev_skipped_iter = prev_skipped.into_iter(); + let mut curr_skipped = Vec::new(); + + while let Some(sub_sub_tree) = + one_tree_list_iter.next().or(prev_skipped_iter.next()) + { + if let Some(sub_one_tree_list) = one_style_tree_list(&sub_sub_tree) { + curr_skipped.extend(sub_one_tree_list.use_trees()); } else { - let new_use_tree_list = make::use_tree_list(empty()).clone_for_update(); - let trees_pos = match new_use_tree_list.l_curly_token() { - Some(l_curly) => Position::after(l_curly), - None => Position::last_child_of(new_use_tree_list.syntax()), - }; - ted::insert_all_raw(trees_pos, elements); - ted::replace(use_tree_list.syntax(), new_use_tree_list.syntax()); + modified |= + recursive_normalize(&sub_sub_tree, NormalizationStyle::Default) + .is_some(); + add_element_to_list( + sub_sub_tree.syntax().clone().into(), + &mut elements, + ); } } + + if curr_skipped.is_empty() { + // Un-nesting is complete. + break; + } + prev_skipped = curr_skipped; + } + + // Either removes the subtree (if its semantically empty) or replaces it with + // the un-nested elements. + if elements.is_empty() { + subtree.remove(); + } else { + ted::replace_with_many(subtree.syntax(), elements); } + modified = true; + } else { + modified |= recursive_normalize(&subtree, NormalizationStyle::Default).is_some(); } } + + // Merge all merge-able subtrees. + let mut tree_list_iter = use_tree_list.use_trees(); + let mut anchor = tree_list_iter.next()?; + let mut prev_skipped = Vec::new(); + loop { + let mut has_merged = false; + let mut prev_skipped_iter = prev_skipped.into_iter(); + let mut next_anchor = None; + let mut curr_skipped = Vec::new(); + + while let Some(candidate) = tree_list_iter.next().or(prev_skipped_iter.next()) { + let result = try_merge_trees_mut(&anchor, &candidate, MergeBehavior::Crate); + if result.is_some() { + // Remove merged subtree. + candidate.remove(); + has_merged = true; + } else if next_anchor.is_none() { + next_anchor = Some(candidate); + } else { + curr_skipped.push(candidate); + } + } + + if has_merged { + // Normalize the merge result. + recursive_normalize(&anchor, NormalizationStyle::Default); + modified = true; + } + + let (Some(next_anchor), true) = (next_anchor, !curr_skipped.is_empty()) else { + // Merging is complete. + break; + }; + + // Try to merge the remaining subtrees in the next iteration. + anchor = next_anchor; + prev_skipped = curr_skipped; + } + + let mut subtrees: Vec<_> = use_tree_list.use_trees().collect(); + // Merge the remaining subtree into its parent, if its only one and + // the normalization style is not "one". + if subtrees.len() == 1 && style != NormalizationStyle::One { + modified |= merge_subtree_into_parent_tree(&subtrees[0]).is_some(); + } + // Order the remaining subtrees (if necessary). + if subtrees.len() > 1 { + let mut did_sort = false; + subtrees.sort_unstable_by(|a, b| { + let order = use_tree_cmp_bin_search(a, b); + if !did_sort && order == Ordering::Less { + did_sort = true; + } + order + }); + if did_sort { + let start = use_tree_list + .l_curly_token() + .and_then(|l_curly| algo::non_trivia_sibling(l_curly.into(), Direction::Next)) + .filter(|it| it.kind() != T!['}']); + let end = use_tree_list + .r_curly_token() + .and_then(|r_curly| algo::non_trivia_sibling(r_curly.into(), Direction::Prev)) + .filter(|it| it.kind() != T!['{']); + if let Some((start, end)) = start.zip(end) { + // Attempt to insert elements while preserving preceding and trailing trivia. + let mut elements = Vec::new(); + for subtree in subtrees { + add_element_to_list(subtree.syntax().clone().into(), &mut elements); + } + ted::replace_all(start..=end, elements); + } else { + let new_use_tree_list = make::use_tree_list(subtrees).clone_for_update(); + ted::replace(use_tree_list.syntax(), new_use_tree_list.syntax()); + } + modified = true; + } + } + + if !modified { + // Either the use tree was already normalized or its semantically empty. + return None; + } } Some(()) } @@ -280,7 +530,7 @@ fn use_tree_cmp_bin_search(lhs: &ast::UseTree, rhs: &ast::UseTree) -> Ordering { /// and `crate` first, then identifier imports with lowercase ones first and upper snake case /// (e.g. UPPER_SNAKE_CASE) ones last, then glob imports, and at last list imports. /// -/// Example foo::{self, foo, baz, Baz, Qux, FOO_BAZ, *, {Bar}} +/// Example: `foo::{self, baz, foo, Baz, Qux, FOO_BAZ, *, {Bar}}` /// Ref: . pub(super) fn use_tree_cmp(a: &ast::UseTree, b: &ast::UseTree) -> Ordering { let a_is_simple_path = a.is_simple_path() && a.rename().is_none(); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs index 432f1d745d205..1b6f650768b9e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs @@ -20,14 +20,9 @@ pub fn items_with_name<'a>( name: NameToImport, assoc_item_search: AssocSearchMode, ) -> impl Iterator + 'a { - let _p = profile::span("items_with_name").detail(|| { - format!( - "Name: {}, crate: {:?}, assoc items: {:?}", - name.text(), - assoc_item_search, - krate.display_name(sema.db).map(|name| name.to_string()), - ) - }); + let krate_name = krate.display_name(sema.db).map(|name| name.to_string()); + let _p = tracing::span!(tracing::Level::INFO, "items_with_name", name = name.text(), assoc_item_search = ?assoc_item_search, crate = ?krate_name) + .entered(); let prefix = matches!(name, NameToImport::Prefix(..)); let (local_query, external_query) = match name { @@ -77,7 +72,7 @@ fn find_items<'a>( local_query: symbol_index::Query, external_query: import_map::Query, ) -> impl Iterator + 'a { - let _p = profile::span("find_items"); + let _p = tracing::span!(tracing::Level::INFO, "find_items").entered(); let db = sema.db; // NOTE: `external_query` includes `assoc_item_search`, so we don't need to diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index 1cc1e36329909..2881748dd477e 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -9,6 +9,7 @@ mod apply_change; pub mod active_parameter; pub mod assists; pub mod defs; +pub mod documentation; pub mod famous_defs; pub mod helpers; pub mod items_locator; @@ -22,7 +23,6 @@ pub mod symbol_index; pub mod traits; pub mod ty_filter; pub mod use_trivial_constructor; -pub mod documentation; pub mod imports { pub mod import_assets; @@ -35,10 +35,10 @@ pub mod generated { } pub mod syntax_helpers { - pub mod node_ext; - pub mod insert_whitespace_into_node; pub mod format_string; pub mod format_string_exprs; + pub mod insert_whitespace_into_node; + pub mod node_ext; pub use parser::LexedStr; } @@ -414,6 +414,6 @@ impl SnippetCap { #[cfg(test)] mod tests { - mod sourcegen_lints; mod line_index; + mod sourcegen_lints; } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 7769d8fba100c..006d8882c11e0 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -134,6 +134,7 @@ pub enum ReferenceCategory { // FIXME: Some day should be able to search in doc comments. Would probably // need to switch from enum to bitflags then? // DocComment + Test, } /// Generally, `search_scope` returns files that might contain references for the element. @@ -273,7 +274,7 @@ impl IntoIterator for SearchScope { impl Definition { fn search_scope(&self, db: &RootDatabase) -> SearchScope { - let _p = profile::span("search_scope"); + let _p = tracing::span!(tracing::Level::INFO, "search_scope").entered(); if let Definition::BuiltinType(_) = self { return SearchScope::crate_graph(db); @@ -303,14 +304,18 @@ impl Definition { DefWithBody::InTypeConst(_) => return SearchScope::empty(), }; return match def { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range( + def.as_ref().original_file_range_with_macro_call_body(db), + ), None => SearchScope::single_file(file_id), }; } if let Definition::SelfType(impl_) = self { return match impl_.source(db).map(|src| src.syntax().cloned()) { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range( + def.as_ref().original_file_range_with_macro_call_body(db), + ), None => SearchScope::single_file(file_id), }; } @@ -327,7 +332,9 @@ impl Definition { hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()), }; return match def { - Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)), + Some(def) => SearchScope::file_range( + def.as_ref().original_file_range_with_macro_call_body(db), + ), None => SearchScope::single_file(file_id), }; } @@ -435,7 +442,7 @@ impl<'a> FindUsages<'a> { } pub fn search(&self, sink: &mut dyn FnMut(FileId, FileReference) -> bool) { - let _p = profile::span("FindUsages:search"); + let _p = tracing::span!(tracing::Level::INFO, "FindUsages:search").entered(); let sema = self.sema; let search_scope = { @@ -743,7 +750,7 @@ impl<'a> FindUsages<'a> { let reference = FileReference { range, name: FileReferenceNode::NameRef(name_ref.clone()), - category: ReferenceCategory::new(&def, name_ref), + category: ReferenceCategory::new(self.sema, &def, name_ref), }; sink(file_id, reference) } @@ -759,7 +766,7 @@ impl<'a> FindUsages<'a> { let reference = FileReference { range, name: FileReferenceNode::NameRef(name_ref.clone()), - category: ReferenceCategory::new(&def, name_ref), + category: ReferenceCategory::new(self.sema, &def, name_ref), }; sink(file_id, reference) } @@ -769,7 +776,7 @@ impl<'a> FindUsages<'a> { let reference = FileReference { range, name: FileReferenceNode::NameRef(name_ref.clone()), - category: ReferenceCategory::new(&def, name_ref), + category: ReferenceCategory::new(self.sema, &def, name_ref), }; sink(file_id, reference) } else { @@ -783,10 +790,10 @@ impl<'a> FindUsages<'a> { let local = Definition::Local(local); let access = match self.def { Definition::Field(_) if field == self.def => { - ReferenceCategory::new(&field, name_ref) + ReferenceCategory::new(self.sema, &field, name_ref) } Definition::Local(_) if local == self.def => { - ReferenceCategory::new(&local, name_ref) + ReferenceCategory::new(self.sema, &local, name_ref) } _ => return false, }; @@ -871,7 +878,15 @@ fn def_to_ty(sema: &Semantics<'_, RootDatabase>, def: &Definition) -> Option Option { + fn new( + sema: &Semantics<'_, RootDatabase>, + def: &Definition, + r: &ast::NameRef, + ) -> Option { + if is_name_ref_in_test(sema, r) { + return Some(ReferenceCategory::Test); + } + // Only Locals and Fields have accesses for now. if !matches!(def, Definition::Local(_) | Definition::Field(_)) { return is_name_ref_in_import(r).then_some(ReferenceCategory::Import); @@ -910,3 +925,10 @@ fn is_name_ref_in_import(name_ref: &ast::NameRef) -> bool { .and_then(|it| it.parent_path().top_path().syntax().parent()) .map_or(false, |it| it.kind() == SyntaxKind::USE_TREE) } + +fn is_name_ref_in_test(sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameRef) -> bool { + name_ref.syntax().ancestors().any(|node| match ast::Fn::cast(node) { + Some(it) => sema.to_def(&it).map_or(false, |func| func.is_test(sema.db)), + None => false, + }) +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index 7774b0834dca5..92c09089e1f13 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs @@ -124,7 +124,7 @@ pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast Arc { - let _p = profile::span("library_symbols"); + let _p = tracing::span!(tracing::Level::INFO, "library_symbols").entered(); let mut symbol_collector = SymbolCollector::new(db.upcast()); @@ -142,14 +142,14 @@ fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Ar } fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc { - let _p = profile::span("module_symbols"); + let _p = tracing::span!(tracing::Level::INFO, "module_symbols").entered(); let symbols = SymbolCollector::collect_module(db.upcast(), module); Arc::new(SymbolIndex::new(symbols)) } pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc]> { - let _p = profile::span("crate_symbols"); + let _p = tracing::span!(tracing::Level::INFO, "crate_symbols").entered(); krate.modules(db.upcast()).into_iter().map(|module| db.module_symbols(module)).collect() } @@ -200,7 +200,7 @@ impl std::ops::Deref for Snap { // | VS Code | kbd:[Ctrl+T] // |=== pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec { - let _p = profile::span("world_symbols").detail(|| query.query.clone()); + let _p = tracing::span!(tracing::Level::INFO, "world_symbols", query = ?query.query).entered(); let indices: Vec<_> = if query.libs { db.library_roots() @@ -320,7 +320,7 @@ impl Query { indices: &'sym [Arc], cb: impl FnMut(&'sym FileSymbol), ) { - let _p = profile::span("symbol_index::Query::search"); + let _p = tracing::span!(tracing::Level::INFO, "symbol_index::Query::search").entered(); let mut op = fst::map::OpBuilder::new(); match self.mode { SearchMode::Exact => { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml index 3ed48457a2842..69768041389ac 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml @@ -16,6 +16,7 @@ cov-mark = "2.0.0-pre.1" either.workspace = true itertools.workspace = true serde_json.workspace = true +tracing.workspace = true once_cell = "1.17.0" # local deps @@ -39,4 +40,4 @@ sourcegen.workspace = true in-rust-tree = [] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 5e950ecb0d102..66ebf593505d2 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -3,7 +3,7 @@ use hir::InFile; use ide_db::base_db::FileRange; use syntax::{ ast::{self, HasArgList}, - AstNode, SyntaxNodePtr, + AstNode, AstPtr, }; use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; @@ -24,7 +24,7 @@ pub(crate) fn mismatched_tuple_struct_pat_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0023"), message, - invalid_args_range(ctx, d.expr_or_pat.map(Into::into), d.expected, d.found), + invalid_args_range(ctx, d.expr_or_pat, d.expected, d.found), ) } @@ -40,17 +40,17 @@ pub(crate) fn mismatched_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0107"), message, - invalid_args_range(ctx, d.call_expr.map(Into::into), d.expected, d.found), + invalid_args_range(ctx, d.call_expr.map(AstPtr::wrap_left), d.expected, d.found), ) } fn invalid_args_range( ctx: &DiagnosticsContext<'_>, - source: InFile, + source: InFile>>, expected: usize, found: usize, ) -> FileRange { - adjusted_display_range::>(ctx, source, &|expr| { + adjusted_display_range(ctx, source, &|expr| { let (text_range, r_paren_token, expected_arg) = match expr { Either::Left(ast::Expr::CallExpr(call)) => { let arg_list = call.arg_list()?; @@ -68,7 +68,7 @@ fn invalid_args_range( arg_list.args().nth(expected).map(|it| it.syntax().text_range()), ) } - Either::Right(pat) => { + Either::Right(ast::Pat::TupleStructPat(pat)) => { let r_paren = pat.r_paren_token()?; let l_paren = pat.l_paren_token()?; ( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs index 5a20246cdd196..8d77e566edc9c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -128,6 +128,36 @@ fn missing_record_expr_field_fixes( mod tests { use crate::tests::{check_diagnostics, check_fix, check_no_fix}; + #[test] + fn dont_work_for_field_with_disabled_cfg() { + check_diagnostics( + r#" +struct Test { + #[cfg(feature = "hello")] + test: u32, + other: u32 +} + +fn main() { + let a = Test { + #[cfg(feature = "hello")] + test: 1, + other: 1 + }; + + let Test { + #[cfg(feature = "hello")] + test, + mut other, + .. + } = a; + + other += 1; +} +"#, + ); + } + #[test] fn no_such_field_diagnostics() { check_diagnostics( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs index 251a645292ed5..6be2c54e6030e 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs @@ -19,7 +19,7 @@ pub(crate) fn trait_impl_incorrect_safety( }, adjusted_display_range::( ctx, - InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() }, + InFile { file_id: d.file_id, value: d.impl_ }, &|impl_| { if d.should_be_safe { Some(match (impl_.unsafe_token(), impl_.impl_token()) { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs index 56188cddf0b2e..58d1b7f31d2fe 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs @@ -25,7 +25,7 @@ pub(crate) fn trait_impl_missing_assoc_item( format!("not all trait items implemented, missing: {missing}"), adjusted_display_range::( ctx, - InFile { file_id: d.file_id, value: d.impl_.syntax_node_ptr() }, + InFile { file_id: d.file_id, value: d.impl_ }, &|impl_| impl_.trait_().map(|t| t.syntax().text_range()), ), ) diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index 23042e222b584..750189beecb1d 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1,3 +1,4 @@ +use either::Either; use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, HirFileIdExt, InFile, Type}; use ide_db::{famous_defs::FamousDefs, source_change::SourceChange}; use syntax::{ @@ -13,33 +14,24 @@ use crate::{adjusted_display_range, fix, Assist, Diagnostic, DiagnosticCode, Dia // This diagnostic is triggered when the type of an expression or pattern does not match // the expected type. pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Diagnostic { - let display_range = match &d.expr_or_pat.value { - expr if ast::Expr::can_cast(expr.kind()) => adjusted_display_range::( - ctx, - InFile { file_id: d.expr_or_pat.file_id, value: expr.syntax_node_ptr() }, - &|expr| { - let salient_token_range = match expr { - ast::Expr::IfExpr(it) => it.if_token()?.text_range(), - ast::Expr::LoopExpr(it) => it.loop_token()?.text_range(), - ast::Expr::ForExpr(it) => it.for_token()?.text_range(), - ast::Expr::WhileExpr(it) => it.while_token()?.text_range(), - ast::Expr::BlockExpr(it) => it.stmt_list()?.r_curly_token()?.text_range(), - ast::Expr::MatchExpr(it) => it.match_token()?.text_range(), - ast::Expr::MethodCallExpr(it) => it.name_ref()?.ident_token()?.text_range(), - ast::Expr::FieldExpr(it) => it.name_ref()?.ident_token()?.text_range(), - ast::Expr::AwaitExpr(it) => it.await_token()?.text_range(), - _ => return None, - }; - - cov_mark::hit!(type_mismatch_range_adjustment); - Some(salient_token_range) - }, - ), - pat => ctx.sema.diagnostics_display_range(InFile { - file_id: d.expr_or_pat.file_id, - value: pat.syntax_node_ptr(), - }), - }; + let display_range = adjusted_display_range(ctx, d.expr_or_pat, &|node| { + let Either::Left(expr) = node else { return None }; + let salient_token_range = match expr { + ast::Expr::IfExpr(it) => it.if_token()?.text_range(), + ast::Expr::LoopExpr(it) => it.loop_token()?.text_range(), + ast::Expr::ForExpr(it) => it.for_token()?.text_range(), + ast::Expr::WhileExpr(it) => it.while_token()?.text_range(), + ast::Expr::BlockExpr(it) => it.stmt_list()?.r_curly_token()?.text_range(), + ast::Expr::MatchExpr(it) => it.match_token()?.text_range(), + ast::Expr::MethodCallExpr(it) => it.name_ref()?.ident_token()?.text_range(), + ast::Expr::FieldExpr(it) => it.name_ref()?.ident_token()?.text_range(), + ast::Expr::AwaitExpr(it) => it.await_token()?.text_range(), + _ => return None, + }; + + cov_mark::hit!(type_mismatch_range_adjustment); + Some(salient_token_range) + }); let mut diag = Diagnostic::new( DiagnosticCode::RustcHardError("E0308"), format!( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 321459412182f..0e7a5720d4d25 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -8,7 +8,7 @@ use ide_db::{ use syntax::{ast, AstNode, AstPtr}; use text_edit::TextEdit; -use crate::{adjusted_display_range_new, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: unresolved-field // @@ -29,7 +29,7 @@ pub(crate) fn unresolved_field( d.name.display(ctx.sema.db), d.receiver.display(ctx.sema.db) ), - adjusted_display_range_new(ctx, d.expr, &|expr| { + adjusted_display_range(ctx, d.expr, &|expr| { Some( match expr { ast::Expr::MethodCallExpr(it) => it.name_ref(), diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 41fb67290852c..9f8fee67f31c1 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -11,7 +11,7 @@ use syntax::{ }; use text_edit::TextEdit; -use crate::{adjusted_display_range_new, Diagnostic, DiagnosticCode, DiagnosticsContext}; +use crate::{adjusted_display_range, Diagnostic, DiagnosticCode, DiagnosticsContext}; // Diagnostic: unresolved-method // @@ -34,7 +34,7 @@ pub(crate) fn unresolved_method( d.name.display(ctx.sema.db), d.receiver.display(ctx.sema.db) ), - adjusted_display_range_new(ctx, d.expr, &|expr| { + adjusted_display_range(ctx, d.expr, &|expr| { Some( match expr { ast::Expr::MethodCallExpr(it) => it.name_ref(), diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs index 7743b060c8626..5ad7069e317a9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs @@ -44,30 +44,30 @@ mod handlers { pub(crate) mod private_assoc_item; pub(crate) mod private_field; pub(crate) mod replace_filter_map_next_with_find_map; - pub(crate) mod trait_impl_orphan; pub(crate) mod trait_impl_incorrect_safety; pub(crate) mod trait_impl_missing_assoc_item; + pub(crate) mod trait_impl_orphan; pub(crate) mod trait_impl_redundant_assoc_item; - pub(crate) mod typed_hole; pub(crate) mod type_mismatch; + pub(crate) mod typed_hole; + pub(crate) mod undeclared_label; pub(crate) mod unimplemented_builtin_macro; + pub(crate) mod unreachable_label; pub(crate) mod unresolved_assoc_item; pub(crate) mod unresolved_extern_crate; pub(crate) mod unresolved_field; - pub(crate) mod unresolved_method; pub(crate) mod unresolved_import; pub(crate) mod unresolved_macro_call; + pub(crate) mod unresolved_method; pub(crate) mod unresolved_module; pub(crate) mod unresolved_proc_macro; - pub(crate) mod undeclared_label; - pub(crate) mod unreachable_label; pub(crate) mod unused_variables; // The handlers below are unusual, the implement the diagnostics as well. pub(crate) mod field_shorthand; - pub(crate) mod useless_braces; - pub(crate) mod unlinked_file; pub(crate) mod json_is_not_rust; + pub(crate) mod unlinked_file; + pub(crate) mod useless_braces; } #[cfg(test)] @@ -89,7 +89,6 @@ use ide_db::{ use once_cell::sync::Lazy; use stdx::never; use syntax::{ - algo::find_node_at_range, ast::{self, AstNode}, AstPtr, SyntaxNode, SyntaxNodePtr, TextRange, }; @@ -293,7 +292,7 @@ pub fn diagnostics( resolve: &AssistResolveStrategy, file_id: FileId, ) -> Vec { - let _p = profile::span("diagnostics"); + let _p = tracing::span!(tracing::Level::INFO, "diagnostics").entered(); let sema = Semantics::new(db); let parse = db.parse(file_id); let mut res = Vec::new(); @@ -571,24 +570,6 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist { } fn adjusted_display_range( - ctx: &DiagnosticsContext<'_>, - diag_ptr: InFile, - adj: &dyn Fn(N) -> Option, -) -> FileRange { - let FileRange { file_id, range } = ctx.sema.diagnostics_display_range(diag_ptr); - - let source_file = ctx.sema.db.parse(file_id); - FileRange { - file_id, - range: find_node_at_range::(&source_file.syntax_node(), range) - .filter(|it| it.syntax().text_range() == range) - .and_then(adj) - .unwrap_or(range), - } -} - -// FIXME Replace the one above with this one? -fn adjusted_display_range_new( ctx: &DiagnosticsContext<'_>, diag_ptr: InFile>, adj: &dyn Fn(N) -> Option, diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs index 742db32564de3..f394a491b5124 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs @@ -173,7 +173,7 @@ fn minicore_smoke_test() { fn check(minicore: MiniCore) { let source = minicore.source_code(); let mut config = DiagnosticsConfig::test_sample(); - // This should be ignored since we conditionaly remove code which creates single item use with braces + // This should be ignored since we conditionally remove code which creates single item use with braces config.disabled.insert("unused_braces".to_string()); check_diagnostics_with_config(config, &source); } diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs index d756e7a63eb9b..b5bf510aeed48 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/lib.rs @@ -69,11 +69,11 @@ // // foo($a, $b) ==>> ($a).foo($b) // ``` +mod fragments; mod from_comment; mod matching; mod nester; mod parsing; -mod fragments; mod replacing; mod resolving; mod search; diff --git a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs index b863e144f0aca..2bc0721123178 100755 --- a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs +++ b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs @@ -494,7 +494,7 @@ fn main() { 2, 3, ], - strustS => StructS { + structS => StructS { a: 31, }, } diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index d64295bdd6907..4fed1f9158ce2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -226,6 +226,7 @@ mod tests { .map(|(FileRange { file_id, range }, _)| FileRange { file_id, range }) .sorted_by_key(cmp) .collect::>(); + assert_eq!(expected, navs); } @@ -236,6 +237,60 @@ mod tests { assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}") } + #[test] + fn goto_def_in_included_file() { + check( + r#" +//- minicore:include +//- /main.rs + +include!("a.rs"); + +fn main() { + foo(); +} + +//- /a.rs +fn func_in_include() { + //^^^^^^^^^^^^^^^ +} + +fn foo() { + func_in_include$0(); +} +"#, + ); + } + + #[test] + fn goto_def_in_included_file_nested() { + check( + r#" +//- minicore:include +//- /main.rs + +macro_rules! passthrough { + ($($tt:tt)*) => { $($tt)* } +} + +passthrough!(include!("a.rs")); + +fn main() { + foo(); +} + +//- /a.rs +fn func_in_include() { + //^^^^^^^^^^^^^^^ +} + +fn foo() { + func_in_include$0(); +} +"#, + ); + } + #[test] fn goto_def_if_items_same_name() { check( diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs index c3a403b10704b..979ca4575d067 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -55,7 +55,7 @@ pub(crate) fn highlight_related( config: HighlightRelatedConfig, pos @ FilePosition { offset, file_id }: FilePosition, ) -> Option> { - let _p = profile::span("highlight_related"); + let _p = tracing::span!(tracing::Level::INFO, "highlight_related").entered(); let syntax = sema.parse(file_id).syntax().clone(); let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind { @@ -519,6 +519,7 @@ mod tests { ReferenceCategory::Read => "read", ReferenceCategory::Write => "write", ReferenceCategory::Import => "import", + ReferenceCategory::Test => "test", } .to_string() }), diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 77a06a97e22d2..19b181ae3b61e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -120,6 +120,7 @@ pub(crate) fn hover( Some(res) } +#[allow(clippy::field_reassign_with_default)] fn hover_simple( sema: &Semantics<'_, RootDatabase>, FilePosition { file_id, offset }: FilePosition, diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 348308d7100ad..9f4427090e9e8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -7196,8 +7196,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 6012..6220, - focus_range: 6077..6083, + full_range: 6156..6364, + focus_range: 6221..6227, name: "Future", kind: Trait, container_name: "future", @@ -7210,8 +7210,8 @@ impl Iterator for S { file_id: FileId( 1, ), - full_range: 6850..7316, - focus_range: 6894..6902, + full_range: 6994..7460, + focus_range: 7038..7046, name: "Iterator", kind: Trait, container_name: "iterator", diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index 79fff15f050b8..8311e770b4b41 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -25,13 +25,13 @@ mod bind_pat; mod binding_mode; mod chaining; mod closing_brace; -mod closure_ret; mod closure_captures; +mod closure_ret; mod discriminant; mod fn_lifetime_fn; +mod implicit_drop; mod implicit_static; mod param_name; -mod implicit_drop; mod range_exclusive; #[derive(Clone, Debug, PartialEq, Eq)] @@ -454,7 +454,7 @@ pub(crate) fn inlay_hints( range_limit: Option, config: &InlayHintsConfig, ) -> Vec { - let _p = profile::span("inlay_hints"); + let _p = tracing::span!(tracing::Level::INFO, "inlay_hints").entered(); let sema = Semantics::new(db); let file = sema.parse(file_id); let file = file.syntax(); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs index 5a206643acf6a..3104b85768f47 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -177,7 +177,7 @@ mod tests { #[test] fn try_operator() { - // We currently show drop inlay hint for every `?` operator that may potentialy drop something. We probably need to + // We currently show drop inlay hint for every `?` operator that may potentially drop something. We probably need to // make it configurable as it doesn't seem very useful. check_with_config( ONLY_DROP_CONFIG, diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 81682e07e0952..e9f42d478554f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -21,24 +21,25 @@ macro_rules! eprintln { mod fixture; mod markup; -mod prime_caches; mod navigation_target; +mod prime_caches; mod annotations; mod call_hierarchy; -mod signature_help; mod doc_links; -mod highlight_related; mod expand_macro; mod extend_selection; +mod fetch_crates; mod file_structure; mod folding_ranges; mod goto_declaration; mod goto_definition; mod goto_implementation; mod goto_type_definition; +mod highlight_related; mod hover; mod inlay_hints; +mod interpret_function; mod join_lines; mod markdown_remove; mod matching_brace; @@ -48,6 +49,8 @@ mod parent_module; mod references; mod rename; mod runnables; +mod shuffle_crate_graph; +mod signature_help; mod ssr; mod static_index; mod status; @@ -56,12 +59,9 @@ mod syntax_tree; mod typing; mod view_crate_graph; mod view_hir; -mod view_mir; -mod interpret_function; mod view_item_tree; -mod shuffle_crate_graph; -mod fetch_crates; mod view_memory_layout; +mod view_mir; use std::ffi::OsStr; @@ -79,7 +79,7 @@ use syntax::SourceFile; use triomphe::Arc; use view_memory_layout::{view_memory_layout, RecursiveMemoryLayout}; -use crate::navigation_target::{ToNav, TryToNav}; +use crate::navigation_target::ToNav; pub use crate::{ annotations::{Annotation, AnnotationConfig, AnnotationKind, AnnotationLocation}, @@ -104,7 +104,7 @@ pub use crate::{ SymbolInformationKind, }, move_item::Direction, - navigation_target::{NavigationTarget, UpmappingResult}, + navigation_target::{NavigationTarget, TryToNav, UpmappingResult}, prime_caches::ParallelPrimeCachesProgress, references::ReferenceSearchResult, rename::RenameError, diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index c8d7b7e25bb71..bfd91feeb3900 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -76,7 +76,7 @@ pub(crate) trait ToNav { fn to_nav(&self, db: &RootDatabase) -> UpmappingResult; } -pub(crate) trait TryToNav { +pub trait TryToNav { fn try_to_nav(&self, db: &RootDatabase) -> Option>; } diff --git a/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs index d704d12a05b23..a95d1771ce0b3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs +++ b/src/tools/rust-analyzer/crates/ide/src/prime_caches.rs @@ -33,7 +33,7 @@ pub(crate) fn parallel_prime_caches( num_worker_threads: u8, cb: &(dyn Fn(ParallelPrimeCachesProgress) + Sync), ) { - let _p = profile::span("prime_caches"); + let _p = tracing::span!(tracing::Level::INFO, "prime_caches").entered(); let graph = db.crate_graph(); let mut crates_to_prime = { diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs index 78fe84f70d3a6..bdda25a111f81 100644 --- a/src/tools/rust-analyzer/crates/ide/src/references.rs +++ b/src/tools/rust-analyzer/crates/ide/src/references.rs @@ -57,7 +57,7 @@ pub(crate) fn find_all_refs( position: FilePosition, search_scope: Option, ) -> Option> { - let _p = profile::span("find_all_refs"); + let _p = tracing::span!(tracing::Level::INFO, "find_all_refs").entered(); let syntax = sema.parse(position.file_id).syntax().clone(); let make_searcher = |literal_search: bool| { move |def: Definition| { @@ -307,6 +307,51 @@ mod tests { use crate::{fixture, SearchScope}; + #[test] + fn exclude_tests() { + check( + r#" +fn test_func() {} + +fn func() { + test_func$0(); +} + +#[test] +fn test() { + test_func(); +} +"#, + expect![[r#" + test_func Function FileId(0) 0..17 3..12 + + FileId(0) 35..44 + FileId(0) 75..84 Test + "#]], + ); + + check( + r#" +fn test_func() {} + +fn func() { + test_func$0(); +} + +#[::core::prelude::v1::test] +fn test() { + test_func(); +} +"#, + expect![[r#" + test_func Function FileId(0) 0..17 3..12 + + FileId(0) 35..44 + FileId(0) 96..105 Test + "#]], + ); + } + #[test] fn test_struct_literal_after_space() { check( @@ -454,6 +499,7 @@ fn main() { "#]], ); } + #[test] fn test_variant_tuple_before_paren() { check( @@ -1435,7 +1481,7 @@ fn test$0() { expect![[r#" test Function FileId(0) 0..33 11..15 - FileId(0) 24..28 + FileId(0) 24..28 Test "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs index 3607c486d7d39..dfcbaf54d4f92 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs @@ -3,11 +3,11 @@ pub(crate) mod tags; mod highlights; mod injector; -mod highlight; +mod escape; mod format; -mod macro_; +mod highlight; mod inject; -mod escape; +mod macro_; mod html; #[cfg(test)] @@ -186,7 +186,7 @@ pub(crate) fn highlight( file_id: FileId, range_to_highlight: Option, ) -> Vec { - let _p = profile::span("highlight"); + let _p = tracing::span!(tracing::Level::INFO, "highlight").entered(); let sema = Semantics::new(db); // Determine the root based on the given range. diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs index 5b7a25408a828..800bc994adab2 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs @@ -292,7 +292,7 @@ fn expand_subtree( Err(e) => { // XXX: It *might* make sense to emit a dummy integer value like `0` here. // That would type inference a bit more robust in cases like - // `v[${count(t)}]` where index doesn't matter, but also coult also lead to + // `v[${count(t)}]` where index doesn't matter, but also could lead to // wrong infefrence for cases like `tup.${count(t)}` where index itself // does matter. if err.is_none() { diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index f968a89a441f2..62fdce36892f2 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -8,11 +8,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod parser; mod expander; +mod parser; mod syntax_bridge; -mod tt_iter; mod to_parser_input; +mod tt_iter; #[cfg(test)] mod benchmark; diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs index 8b57d7eeaf588..d6c3bd1892693 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs @@ -234,7 +234,7 @@ where let mut stack = NonEmptyVec::new(entry); while let Some((token, abs_range)) = conv.bump() { - let tt::Subtree { delimiter, token_trees: result } = stack.last_mut(); + let tt::Subtree { delimiter, token_trees } = stack.last_mut(); let tt = match token.as_leaf() { Some(leaf) => tt::TokenTree::Leaf(leaf.clone()), @@ -243,7 +243,7 @@ where COMMENT => { let span = conv.span_for(abs_range); if let Some(tokens) = conv.convert_doc_comment(&token, span) { - result.extend(tokens); + token_trees.extend(tokens); } continue; } @@ -317,7 +317,7 @@ where span: conv .span_for(TextRange::at(abs_range.start(), TextSize::of('\''))), }); - result.push(apostrophe.into()); + token_trees.push(apostrophe.into()); let ident = tt::Leaf::from(tt::Ident { text: SmolStr::new(&token.to_text(conv)[1..]), @@ -326,7 +326,7 @@ where abs_range.end(), )), }); - result.push(ident.into()); + token_trees.push(ident.into()); continue; } _ => continue, @@ -337,7 +337,7 @@ where }, }; - result.push(tt); + token_trees.push(tt); } // If we get here, we've consumed all input tokens. @@ -622,7 +622,7 @@ where struct Converter { current: Option, - current_leafs: Vec>, + current_leaves: Vec>, preorder: PreorderWithTokens, range: TextRange, punct_offset: Option<(SyntaxToken, TextSize)>, @@ -650,7 +650,7 @@ impl Converter { append, remove, call_site, - current_leafs: vec![], + current_leaves: vec![], }; let first = this.next_token(); this.current = first; @@ -665,7 +665,7 @@ impl Converter { self.preorder.skip_subtree(); if let Some(mut v) = self.append.remove(&n.into()) { v.reverse(); - self.current_leafs.extend(v); + self.current_leaves.extend(v); return None; } } @@ -673,7 +673,7 @@ impl Converter { WalkEvent::Leave(ele) => { if let Some(mut v) = self.append.remove(&ele) { v.reverse(); - self.current_leafs.extend(v); + self.current_leaves.extend(v); return None; } } @@ -758,8 +758,8 @@ where } } - if let Some(leaf) = self.current_leafs.pop() { - if self.current_leafs.is_empty() { + if let Some(leaf) = self.current_leaves.pop() { + if self.current_leaves.is_empty() { self.current = self.next_token(); } return Some((SynToken::Leaf(leaf), TextRange::empty(TextSize::new(0)))); diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs index 19da297b58ccc..53fda3ae4fd26 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs @@ -30,12 +30,12 @@ mod attributes; mod expressions; +mod generic_args; +mod generic_params; mod items; mod params; mod paths; mod patterns; -mod generic_args; -mod generic_params; mod types; use crate::{ diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs index caf2a005a7d8b..243a219525a8a 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs @@ -1,5 +1,5 @@ -mod consts; mod adt; +mod consts; mod traits; mod use_item; diff --git a/src/tools/rust-analyzer/crates/parser/src/lib.rs b/src/tools/rust-analyzer/crates/parser/src/lib.rs index ed0aec3cab32a..3ca285e787e81 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lib.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lib.rs @@ -26,15 +26,15 @@ extern crate ra_ap_rustc_lexer as rustc_lexer; #[cfg(feature = "in-rust-tree")] extern crate rustc_lexer; -mod lexed_str; -mod token_set; -mod syntax_kind; mod event; -mod parser; mod grammar; mod input; +mod lexed_str; mod output; +mod parser; mod shortcuts; +mod syntax_kind; +mod token_set; #[cfg(test)] mod tests; diff --git a/src/tools/rust-analyzer/crates/parser/src/tests.rs b/src/tools/rust-analyzer/crates/parser/src/tests.rs index 2fec765bd7871..c65219b28dce6 100644 --- a/src/tools/rust-analyzer/crates/parser/src/tests.rs +++ b/src/tools/rust-analyzer/crates/parser/src/tests.rs @@ -1,6 +1,6 @@ +mod prefix_entries; mod sourcegen_inline_tests; mod top_entries; -mod prefix_entries; use std::{ fmt::Write, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs index 208051113a7d2..379d184dd684e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs @@ -113,7 +113,7 @@ impl ProcMacroServer { } pub fn load_dylib(&self, dylib: MacroDylib) -> Result, ServerError> { - let _p = profile::span("ProcMacroClient::load_dylib"); + let _p = tracing::span!(tracing::Level::INFO, "ProcMacroClient::load_dylib").entered(); let macros = self.process.lock().unwrap_or_else(|e| e.into_inner()).find_proc_macros(&dylib.path)?; @@ -184,7 +184,7 @@ impl ProcMacro { .process .lock() .unwrap_or_else(|e| e.into_inner()) - .send_task(msg::Request::ExpandMacro(task))?; + .send_task(msg::Request::ExpandMacro(Box::new(task)))?; match response { msg::Response::ExpandMacro(it) => { diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs index 557ddba5c78fe..e28fe387b84bd 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs @@ -29,7 +29,7 @@ pub enum Request { /// Since [`NO_VERSION_CHECK_VERSION`] ListMacros { dylib_path: PathBuf }, /// Since [`NO_VERSION_CHECK_VERSION`] - ExpandMacro(ExpandMacro), + ExpandMacro(Box), /// Since [`VERSION_CHECK_VERSION`] ApiVersionCheck {}, /// Since [`RUST_ANALYZER_SPAN_SUPPORT`] diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs index 5ff1f36c545e6..5f81c0a96d967 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs @@ -106,9 +106,9 @@ fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&' /// pub fn read_version(dylib_path: &AbsPath) -> io::Result { let dylib_file = File::open(dylib_path)?; - let dylib_mmaped = unsafe { Mmap::map(&dylib_file) }?; + let dylib_mmapped = unsafe { Mmap::map(&dylib_file) }?; - let dot_rustc = read_section(&dylib_mmaped, ".rustc")?; + let dot_rustc = read_section(&dylib_mmapped, ".rustc")?; // check if magic is valid if &dot_rustc[0..4] != b"rust" { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs index af9a03826ffc0..a36200cdb4c35 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs @@ -45,9 +45,11 @@ fn run() -> io::Result<()> { msg::Response::ListMacros(srv.list_macros(&dylib_path)) } msg::Request::ExpandMacro(task) => match srv.span_mode() { - msg::SpanMode::Id => msg::Response::ExpandMacro(srv.expand(task).map(|(it, _)| it)), + msg::SpanMode::Id => { + msg::Response::ExpandMacro(srv.expand(*task).map(|(it, _)| it)) + } msg::SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended( - srv.expand(task).map(|(tree, span_data_table)| msg::ExpandMacroExtended { + srv.expand(*task).map(|(tree, span_data_table)| msg::ExpandMacroExtended { tree, span_data_table, }), diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs index e6903fb8d4aed..ff62980e4ffe3 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs @@ -100,7 +100,8 @@ fn main() { .current_dir(&staging_dir) .args(["pkgid", name]) .output() - .unwrap().stdout, + .unwrap() + .stdout, ) .unwrap(); let pkgid = pkgid.trim(); @@ -108,10 +109,11 @@ fn main() { let mut artifact_path = None; for message in Message::parse_stream(output.stdout.as_slice()) { if let Message::CompilerArtifact(artifact) = message.unwrap() { - if artifact.target.kind.contains(&"proc-macro".to_string()) { - if artifact.package_id.repr.starts_with(&repr) || artifact.package_id.repr == pkgid { - artifact_path = Some(PathBuf::from(&artifact.filenames[0])); - } + if artifact.target.kind.contains(&"proc-macro".to_string()) + && (artifact.package_id.repr.starts_with(&repr) + || artifact.package_id.repr == pkgid) + { + artifact_path = Some(PathBuf::from(&artifact.filenames[0])); } } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 67b9f57a1636c..460a96c07f367 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -21,8 +21,8 @@ extern crate proc_macro; extern crate rustc_driver as _; mod dylib; -mod server; mod proc_macros; +mod server; use std::{ collections::{hash_map::Entry, HashMap}, diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs index 1854322ddb5c3..ff8fd295d884a 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server.rs @@ -13,9 +13,9 @@ use proc_macro::bridge; mod token_stream; pub use token_stream::TokenStream; -pub mod token_id; pub mod rust_analyzer_span; mod symbol; +pub mod token_id; pub use symbol::*; use tt::Spacing; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs index bcf3600d27366..b864a5e4fd63e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs @@ -1,4 +1,4 @@ -//! proc-macro server backend based on rust-analyzer's internal span represention +//! proc-macro server backend based on rust-analyzer's internal span representation //! This backend is used solely by rust-analyzer as it ties into rust-analyzer internals. //! //! It is an unfortunate result of how the proc-macro API works that we need to look into the diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs index 12526ad4f3ae6..c83e09af0d6e1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs @@ -206,7 +206,7 @@ impl server::TokenStream for TokenIdServer { stream: if subtree.token_trees.is_empty() { None } else { - Some(subtree.token_trees.into_iter().collect()) + Some(TokenStream { token_trees: subtree.token_trees }) }, span: bridge::DelimSpan::from_single(subtree.delimiter.open), }), diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml index 5350023c88fac..a87b67f5c69f3 100644 --- a/src/tools/rust-analyzer/crates/profile/Cargo.toml +++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml @@ -13,6 +13,7 @@ doctest = false [dependencies] once_cell = "1.17.0" +tracing.workspace = true cfg-if = "1.0.0" la-arena.workspace = true libc.workspace = true @@ -33,4 +34,4 @@ jemalloc = ["jemalloc-ctl"] # default = [ "cpu_profiler" ] [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/profile/src/hprof.rs b/src/tools/rust-analyzer/crates/profile/src/hprof.rs deleted file mode 100644 index ea89a89c5c5ca..0000000000000 --- a/src/tools/rust-analyzer/crates/profile/src/hprof.rs +++ /dev/null @@ -1,326 +0,0 @@ -//! Simple hierarchical profiler -use std::{ - cell::RefCell, - collections::{BTreeMap, HashSet}, - env, fmt, - io::{stderr, Write}, - sync::{ - atomic::{AtomicBool, Ordering}, - RwLock, - }, - time::{Duration, Instant}, -}; - -use once_cell::sync::Lazy; - -use crate::tree::{Idx, Tree}; - -/// Filtering syntax -/// env RA_PROFILE=* // dump everything -/// env RA_PROFILE=foo|bar|baz // enabled only selected entries -/// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 ms -pub fn init() { - countme::enable(env::var("RA_COUNT").is_ok()); - let spec = env::var("RA_PROFILE").unwrap_or_default(); - init_from(&spec); -} - -pub fn init_from(spec: &str) { - let filter = if spec.is_empty() { Filter::disabled() } else { Filter::from_spec(spec) }; - filter.install(); -} - -type Label = &'static str; - -/// This function starts a profiling scope in the current execution stack with a given description. -/// It returns a `Profile` struct that measures elapsed time between this method invocation and `Profile` struct drop. -/// It supports nested profiling scopes in case when this function is invoked multiple times at the execution stack. -/// In this case the profiling information will be nested at the output. -/// Profiling information is being printed in the stderr. -/// -/// # Example -/// ``` -/// profile::init_from("profile1|profile2@2"); -/// profiling_function1(); -/// -/// fn profiling_function1() { -/// let _p = profile::span("profile1"); -/// profiling_function2(); -/// } -/// -/// fn profiling_function2() { -/// let _p = profile::span("profile2"); -/// } -/// ``` -/// This will print in the stderr the following: -/// ```text -/// 0ms - profile -/// 0ms - profile2 -/// ``` -#[inline] -pub fn span(label: Label) -> ProfileSpan { - debug_assert!(!label.is_empty()); - - let enabled = PROFILING_ENABLED.load(Ordering::Relaxed); - if enabled && with_profile_stack(|stack| stack.push(label)) { - ProfileSpan(Some(ProfilerImpl { label, detail: None })) - } else { - ProfileSpan(None) - } -} - -#[inline] -pub fn heartbeat_span() -> HeartbeatSpan { - let enabled = PROFILING_ENABLED.load(Ordering::Relaxed); - HeartbeatSpan::new(enabled) -} - -#[inline] -pub fn heartbeat() { - let enabled = PROFILING_ENABLED.load(Ordering::Relaxed); - if enabled { - with_profile_stack(|it| it.heartbeat(1)); - } -} - -pub struct ProfileSpan(Option); - -struct ProfilerImpl { - label: Label, - detail: Option, -} - -impl ProfileSpan { - pub fn detail(mut self, detail: impl FnOnce() -> String) -> ProfileSpan { - if let Some(profiler) = &mut self.0 { - profiler.detail = Some(detail()); - } - self - } -} - -impl Drop for ProfilerImpl { - #[inline] - fn drop(&mut self) { - with_profile_stack(|it| it.pop(self.label, self.detail.take())); - } -} - -pub struct HeartbeatSpan { - enabled: bool, -} - -impl HeartbeatSpan { - #[inline] - pub fn new(enabled: bool) -> Self { - if enabled { - with_profile_stack(|it| it.heartbeats(true)); - } - Self { enabled } - } -} - -impl Drop for HeartbeatSpan { - fn drop(&mut self) { - if self.enabled { - with_profile_stack(|it| it.heartbeats(false)); - } - } -} - -static PROFILING_ENABLED: AtomicBool = AtomicBool::new(false); -static FILTER: Lazy> = Lazy::new(Default::default); - -fn with_profile_stack(f: impl FnOnce(&mut ProfileStack) -> T) -> T { - thread_local!(static STACK: RefCell = RefCell::new(ProfileStack::new())); - STACK.with(|it| f(&mut it.borrow_mut())) -} - -#[derive(Default, Clone, Debug)] -struct Filter { - depth: usize, - allowed: HashSet, - longer_than: Duration, - heartbeat_longer_than: Duration, - version: usize, -} - -impl Filter { - fn disabled() -> Filter { - Filter::default() - } - - fn from_spec(mut spec: &str) -> Filter { - let longer_than = if let Some(idx) = spec.rfind('>') { - let longer_than = spec[idx + 1..].parse().expect("invalid profile longer_than"); - spec = &spec[..idx]; - Duration::from_millis(longer_than) - } else { - Duration::new(0, 0) - }; - let heartbeat_longer_than = longer_than; - - let depth = if let Some(idx) = spec.rfind('@') { - let depth: usize = spec[idx + 1..].parse().expect("invalid profile depth"); - spec = &spec[..idx]; - depth - } else { - 999 - }; - let allowed = - if spec == "*" { HashSet::new() } else { spec.split('|').map(String::from).collect() }; - Filter { depth, allowed, longer_than, heartbeat_longer_than, version: 0 } - } - - fn install(mut self) { - PROFILING_ENABLED.store(self.depth > 0, Ordering::SeqCst); - let mut old = FILTER.write().unwrap(); - self.version = old.version + 1; - *old = self; - } -} - -struct ProfileStack { - frames: Vec, - filter: Filter, - messages: Tree, - heartbeats: bool, -} - -struct Frame { - t: Instant, - heartbeats: u32, -} - -#[derive(Default)] -struct Message { - duration: Duration, - label: Label, - detail: Option, -} - -impl ProfileStack { - fn new() -> ProfileStack { - ProfileStack { - frames: Vec::new(), - messages: Tree::default(), - filter: Default::default(), - heartbeats: false, - } - } - - fn push(&mut self, label: Label) -> bool { - if self.frames.is_empty() { - if let Ok(f) = FILTER.try_read() { - if f.version > self.filter.version { - self.filter = f.clone(); - } - }; - } - if self.frames.len() > self.filter.depth { - return false; - } - let allowed = &self.filter.allowed; - if self.frames.is_empty() && !allowed.is_empty() && !allowed.contains(label) { - return false; - } - - self.frames.push(Frame { t: Instant::now(), heartbeats: 0 }); - self.messages.start(); - true - } - - fn pop(&mut self, label: Label, detail: Option) { - let frame = self.frames.pop().unwrap(); - let duration = frame.t.elapsed(); - - if self.heartbeats { - self.heartbeat(frame.heartbeats); - let avg_span = duration / (frame.heartbeats + 1); - if avg_span > self.filter.heartbeat_longer_than { - eprintln!("Too few heartbeats {label} ({}/{duration:?})?", frame.heartbeats); - } - } - - self.messages.finish(Message { duration, label, detail }); - if self.frames.is_empty() { - let longer_than = self.filter.longer_than; - // Convert to millis for comparison to avoid problems with rounding - // (otherwise we could print `0ms` despite user's `>0` filter when - // `duration` is just a few nanos). - if duration.as_millis() > longer_than.as_millis() { - if let Some(root) = self.messages.root() { - print(&self.messages, root, 0, longer_than, &mut stderr().lock()); - } - } - self.messages.clear(); - } - } - - fn heartbeats(&mut self, yes: bool) { - self.heartbeats = yes; - } - fn heartbeat(&mut self, n: u32) { - if let Some(frame) = self.frames.last_mut() { - frame.heartbeats += n; - } - } -} - -fn print( - tree: &Tree, - curr: Idx, - level: u32, - longer_than: Duration, - out: &mut impl Write, -) { - let current_indent = " ".repeat(level as usize); - let detail = tree[curr].detail.as_ref().map(|it| format!(" @ {it}")).unwrap_or_default(); - writeln!( - out, - "{}{} - {}{}", - current_indent, - ms(tree[curr].duration), - tree[curr].label, - detail, - ) - .expect("printing profiling info"); - - let mut accounted_for = Duration::default(); - let mut short_children = BTreeMap::new(); // Use `BTreeMap` to get deterministic output. - for child in tree.children(curr) { - accounted_for += tree[child].duration; - - if tree[child].duration.as_millis() > longer_than.as_millis() { - print(tree, child, level + 1, longer_than, out); - } else { - let (total_duration, cnt) = - short_children.entry(tree[child].label).or_insert((Duration::default(), 0)); - *total_duration += tree[child].duration; - *cnt += 1; - } - } - - for (child_msg, (duration, count)) in &short_children { - writeln!(out, " {current_indent}{} - {child_msg} ({count} calls)", ms(*duration)) - .expect("printing profiling info"); - } - - let unaccounted = tree[curr].duration - accounted_for; - if tree.children(curr).next().is_some() && unaccounted > longer_than { - writeln!(out, " {current_indent}{} - ???", ms(unaccounted)) - .expect("printing profiling info"); - } -} - -#[allow(non_camel_case_types)] -struct ms(Duration); - -impl fmt::Display for ms { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0.as_millis() { - 0 => f.write_str(" 0 "), - n => write!(f, "{n:5}ms"), - } - } -} diff --git a/src/tools/rust-analyzer/crates/profile/src/lib.rs b/src/tools/rust-analyzer/crates/profile/src/lib.rs index fdd724e2aab45..38c5b3fc9c725 100644 --- a/src/tools/rust-analyzer/crates/profile/src/lib.rs +++ b/src/tools/rust-analyzer/crates/profile/src/lib.rs @@ -2,17 +2,14 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod stop_watch; -mod memory_usage; #[cfg(feature = "cpu_profiler")] mod google_cpu_profiler; -mod hprof; -mod tree; +mod memory_usage; +mod stop_watch; use std::cell::RefCell; pub use crate::{ - hprof::{heartbeat, heartbeat_span, init, init_from, span}, memory_usage::{Bytes, MemoryUsage}, stop_watch::{StopWatch, StopWatchSpan}, }; diff --git a/src/tools/rust-analyzer/crates/profile/src/tree.rs b/src/tools/rust-analyzer/crates/profile/src/tree.rs deleted file mode 100644 index 1290fba36fab3..0000000000000 --- a/src/tools/rust-analyzer/crates/profile/src/tree.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! A simple tree implementation which tries to not allocate all over the place. -use std::ops; - -use la_arena::Arena; - -#[derive(Default)] -pub(crate) struct Tree { - nodes: Arena>, - current_path: Vec<(Idx, Option>)>, -} - -pub(crate) type Idx = la_arena::Idx>; - -impl Tree { - pub(crate) fn start(&mut self) - where - T: Default, - { - let me = self.nodes.alloc(Node::new(T::default())); - if let Some((parent, last_child)) = self.current_path.last_mut() { - let slot = match *last_child { - Some(last_child) => &mut self.nodes[last_child].next_sibling, - None => &mut self.nodes[*parent].first_child, - }; - let prev = slot.replace(me); - assert!(prev.is_none()); - *last_child = Some(me); - } - - self.current_path.push((me, None)); - } - - pub(crate) fn finish(&mut self, data: T) { - let (me, _last_child) = self.current_path.pop().unwrap(); - self.nodes[me].data = data; - } - - pub(crate) fn root(&self) -> Option> { - self.nodes.iter().next().map(|(idx, _)| idx) - } - - pub(crate) fn children(&self, idx: Idx) -> impl Iterator> + '_ { - NodeIter { nodes: &self.nodes, next: self.nodes[idx].first_child } - } - pub(crate) fn clear(&mut self) { - self.nodes.clear(); - self.current_path.clear(); - } -} - -impl ops::Index> for Tree { - type Output = T; - fn index(&self, index: Idx) -> &T { - &self.nodes[index].data - } -} - -pub(crate) struct Node { - data: T, - first_child: Option>, - next_sibling: Option>, -} - -impl Node { - fn new(data: T) -> Node { - Node { data, first_child: None, next_sibling: None } - } -} - -struct NodeIter<'a, T> { - nodes: &'a Arena>, - next: Option>, -} - -impl Iterator for NodeIter<'_, T> { - type Item = Idx; - - fn next(&mut self) -> Option> { - self.next.map(|next| { - self.next = self.nodes[next].next_sibling; - next - }) - } -} diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs index 5f9b708289d16..5114c9c016ded 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs @@ -17,15 +17,15 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod manifest_path; +mod build_scripts; mod cargo_workspace; mod cfg_flag; +mod manifest_path; mod project_json; -mod sysroot; -mod workspace; mod rustc_cfg; -mod build_scripts; +mod sysroot; pub mod target_data_layout; +mod workspace; #[cfg(test)] mod tests; diff --git a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs index c5d55f7d2171f..cf12d5b71df56 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs @@ -26,7 +26,7 @@ pub(crate) fn get( extra_env: &FxHashMap, config: RustcCfgConfig<'_>, ) -> Vec { - let _p = profile::span("rustc_cfg::get"); + let _p = tracing::span!(tracing::Level::INFO, "rustc_cfg::get").entered(); let mut res = Vec::with_capacity(6 * 2 + 1); // Some nightly-only cfgs, which are required for stdlib diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index 88974e889e8bc..8c5ea0619ac7e 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -60,7 +60,7 @@ pub enum ProjectWorkspace { cargo: CargoWorkspace, build_scripts: WorkspaceBuildScripts, sysroot: Result>, - rustc: Result<(CargoWorkspace, WorkspaceBuildScripts), Option>, + rustc: Result, Option>, /// Holds cfg flags for the current target. We get those by running /// `rustc --print cfg`. /// @@ -119,7 +119,7 @@ impl fmt::Debug for ProjectWorkspace { .field("sysroot", &sysroot.is_ok()) .field( "n_rustc_compiler_crates", - &rustc.as_ref().map_or(0, |(rc, _)| rc.packages().len()), + &rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(rc, _)| rc.packages().len()), ) .field("n_rustc_cfg", &rustc_cfg.len()) .field("n_cfg_overrides", &cfg_overrides.len()) @@ -265,7 +265,7 @@ impl ProjectWorkspace { cargo_toml.parent(), &config.extra_env, ); - Ok((workspace, buildscripts)) + Ok(Box::new((workspace, buildscripts))) } Err(e) => { tracing::error!( @@ -603,7 +603,7 @@ impl ProjectWorkspace { PackageRoot { is_local, include, exclude } }) .chain(mk_sysroot(sysroot.as_ref(), Some(cargo.workspace_root()))) - .chain(rustc.iter().flat_map(|(rustc, _)| { + .chain(rustc.iter().map(|a| a.as_ref()).flat_map(|(rustc, _)| { rustc.packages().map(move |krate| PackageRoot { is_local: false, include: vec![rustc[krate].manifest.parent().to_path_buf()], @@ -631,7 +631,8 @@ impl ProjectWorkspace { sysroot_package_len + project.n_crates() } ProjectWorkspace::Cargo { cargo, sysroot, rustc, .. } => { - let rustc_package_len = rustc.as_ref().map_or(0, |(it, _)| it.packages().len()); + let rustc_package_len = + rustc.as_ref().map(|a| a.as_ref()).map_or(0, |(it, _)| it.packages().len()); let sysroot_package_len = sysroot.as_ref().map_or(0, |it| it.num_packages()); cargo.packages().len() + sysroot_package_len + rustc_package_len } @@ -647,7 +648,7 @@ impl ProjectWorkspace { load: &mut dyn FnMut(&AbsPath) -> Option, extra_env: &FxHashMap, ) -> (CrateGraph, ProcMacroPaths) { - let _p = profile::span("ProjectWorkspace::to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered(); let (mut crate_graph, proc_macros) = match self { ProjectWorkspace::Json { project, sysroot, rustc_cfg, toolchain } => { @@ -672,7 +673,7 @@ impl ProjectWorkspace { target_layout, } => cargo_to_crate_graph( load, - rustc.as_ref().ok(), + rustc.as_ref().map(|a| a.as_ref()).ok(), cargo, sysroot.as_ref().ok(), rustc_cfg.clone(), @@ -891,7 +892,7 @@ fn cargo_to_crate_graph( target_layout: TargetLayoutLoadResult, toolchain: Option<&Version>, ) -> (CrateGraph, ProcMacroPaths) { - let _p = profile::span("cargo_to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "cargo_to_crate_graph").entered(); let mut res = (CrateGraph::default(), ProcMacroPaths::default()); let crate_graph = &mut res.0; let proc_macros = &mut res.1; @@ -1088,7 +1089,7 @@ fn detached_files_to_crate_graph( sysroot: Option<&Sysroot>, target_layout: TargetLayoutLoadResult, ) -> (CrateGraph, ProcMacroPaths) { - let _p = profile::span("detached_files_to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "detached_files_to_crate_graph").entered(); let mut crate_graph = CrateGraph::default(); let (public_deps, _libproc_macro) = match sysroot { Some(sysroot) => sysroot_to_crate_graph( @@ -1384,7 +1385,7 @@ fn sysroot_to_crate_graph( load: &mut dyn FnMut(&AbsPath) -> Option, toolchain: Option<&Version>, ) -> (SysrootPublicDeps, Option) { - let _p = profile::span("sysroot_to_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "sysroot_to_crate_graph").entered(); match sysroot.mode() { SysrootMode::Workspace(cargo) => { let (mut cg, mut pm) = cargo_to_crate_graph( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index db5cabaf76941..a212041e66b46 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -23,7 +23,7 @@ anyhow.workspace = true crossbeam-channel = "0.5.5" dissimilar.workspace = true itertools.workspace = true -scip = "0.3.1" +scip = "0.3.3" lsp-types = { version = "=0.95.0", features = ["proposed"] } parking_lot = "0.12.1" xflags = "0.3.0" @@ -37,11 +37,10 @@ mimalloc = { version = "0.1.30", default-features = false, optional = true } lsp-server.workspace = true tracing.workspace = true tracing-subscriber.workspace = true -tracing-log = "0.2.0" tracing-tree.workspace = true triomphe.workspace = true nohash-hasher.workspace = true -always-assert = "0.1.2" +always-assert = "0.2.0" walkdir = "2.3.2" cfg.workspace = true diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs deleted file mode 100644 index 1f923f6cf8dda..0000000000000 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! Simple logger that logs either to stderr or to a file, using `tracing_subscriber` -//! filter syntax and `tracing_appender` for non blocking output. - -use std::{ - fmt, - fs::File, - io::{self, Stderr}, - sync::Arc, -}; - -use anyhow::Context; -use tracing::{level_filters::LevelFilter, Event, Subscriber}; -use tracing_log::NormalizeEvent; -use tracing_subscriber::{ - filter::Targets, - fmt::{ - format::Writer, writer::BoxMakeWriter, FmtContext, FormatEvent, FormatFields, - FormattedFields, MakeWriter, - }, - layer::SubscriberExt, - registry::LookupSpan, - util::SubscriberInitExt, - Registry, -}; -use tracing_tree::HierarchicalLayer; - -pub(crate) struct LoggerConfig { - pub(crate) log_file: Option, - pub(crate) filter: String, - pub(crate) chalk_filter: Option, -} - -struct MakeWriterStderr; - -impl MakeWriter<'_> for MakeWriterStderr { - type Writer = Stderr; - - fn make_writer(&self) -> Self::Writer { - io::stderr() - } -} - -impl LoggerConfig { - pub(crate) fn init(self) -> anyhow::Result<()> { - let mut filter: Targets = self - .filter - .parse() - .with_context(|| format!("invalid log filter: `{}`", self.filter))?; - - let mut chalk_layer = None; - if let Some(chalk_filter) = self.chalk_filter { - let level: LevelFilter = - chalk_filter.parse().with_context(|| "invalid chalk log filter")?; - chalk_layer = Some( - HierarchicalLayer::default() - .with_indent_lines(true) - .with_ansi(false) - .with_indent_amount(2) - .with_writer(io::stderr), - ); - filter = filter - .with_target("chalk_solve", level) - .with_target("chalk_ir", level) - .with_target("chalk_recursive", level); - }; - - let writer = match self.log_file { - Some(file) => BoxMakeWriter::new(Arc::new(file)), - None => BoxMakeWriter::new(io::stderr), - }; - let ra_fmt_layer = - tracing_subscriber::fmt::layer().event_format(LoggerFormatter).with_writer(writer); - - let registry = Registry::default().with(filter).with(ra_fmt_layer); - match chalk_layer { - Some(chalk_layer) => registry.with(chalk_layer).init(), - None => registry.init(), - } - Ok(()) - } -} - -#[derive(Debug)] -struct LoggerFormatter; - -impl FormatEvent for LoggerFormatter -where - S: Subscriber + for<'a> LookupSpan<'a>, - N: for<'a> FormatFields<'a> + 'static, -{ - fn format_event( - &self, - ctx: &FmtContext<'_, S, N>, - mut writer: Writer<'_>, - event: &Event<'_>, - ) -> fmt::Result { - // Write level and target - let level = *event.metadata().level(); - - // If this event is issued from `log` crate, then the value of target is - // always "log". `tracing-log` has hard coded it for some reason, so we - // need to extract it using `normalized_metadata` method which is part of - // `tracing_log::NormalizeEvent`. - let target = match event.normalized_metadata() { - // This event is issued from `log` crate - Some(log) => log.target(), - None => event.metadata().target(), - }; - write!(writer, "[{level} {target}] ")?; - - // Write spans and fields of each span - ctx.visit_spans(|span| { - write!(writer, "{}", span.name())?; - - let ext = span.extensions(); - - // `FormattedFields` is a formatted representation of the span's - // fields, which is stored in its extensions by the `fmt` layer's - // `new_span` method. The fields will have been formatted - // by the same field formatter that's provided to the event - // formatter in the `FmtContext`. - let fields = &ext.get::>().expect("will never be `None`"); - - if !fields.is_empty() { - write!(writer, "{{{fields}}}")?; - } - write!(writer, ": ")?; - - Ok(()) - })?; - - // Write fields on the event - ctx.field_format().format_fields(writer.by_ref(), event)?; - - writeln!(writer) - } -} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs index 04387291907b7..66b680571a97d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs @@ -7,14 +7,14 @@ #[cfg(feature = "in-rust-tree")] extern crate rustc_driver as _; -mod logger; mod rustc_wrapper; -use std::{env, fs, path::PathBuf, process}; +use std::{env, fs, path::PathBuf, process, sync::Arc}; use anyhow::Context; use lsp_server::Connection; use rust_analyzer::{cli::flags, config::Config, from_json}; +use tracing_subscriber::fmt::writer::BoxMakeWriter; use vfs::AbsPathBuf; #[cfg(feature = "mimalloc")] @@ -123,26 +123,21 @@ fn setup_logging(log_file_flag: Option) -> anyhow::Result<()> { None => None, }; - logger::LoggerConfig { - log_file, + let writer = match log_file { + Some(file) => BoxMakeWriter::new(Arc::new(file)), + None => BoxMakeWriter::new(std::io::stderr), + }; + + rust_analyzer::tracing::Config { + writer, // Deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually // useful information in there for debugging. filter: env::var("RA_LOG").ok().unwrap_or_else(|| "error".to_string()), - // The meaning of CHALK_DEBUG I suspected is to tell chalk crates - // (i.e. chalk-solve, chalk-ir, chalk-recursive) how to filter tracing - // logs. But now we can only have just one filter, which means we have to - // merge chalk filter to our main filter (from RA_LOG env). - // - // The acceptable syntax of CHALK_DEBUG is `target[span{field=value}]=level`. - // As the value should only affect chalk crates, we'd better manually - // specify the target. And for simplicity, CHALK_DEBUG only accept the value - // that specify level. chalk_filter: env::var("CHALK_DEBUG").ok(), + profile_filter: env::var("RA_PROFILE").ok(), } .init()?; - profile::init(); - Ok(()) } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs index de00c4192b46a..00670f2cb4c8d 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli.rs @@ -1,16 +1,16 @@ //! Various batch processing tasks, intended primarily for debugging. -pub mod flags; -mod parse; -mod symbols; -mod highlight; mod analysis_stats; mod diagnostics; -mod ssr; +pub mod flags; +mod highlight; mod lsif; -mod scip; +mod parse; mod run_tests; mod rustc_tests; +mod scip; +mod ssr; +mod symbols; mod progress_report; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index f42e14f2e51ea..31bdd2a0e82b1 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -58,12 +58,14 @@ impl flags::AnalysisStats { Rand32::new(seed) }; - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = match self.no_sysroot { - true => None, - false => Some(RustLibSource::Discover), + let cargo_config = CargoConfig { + sysroot: match self.no_sysroot { + true => None, + false => Some(RustLibSource::Discover), + }, + sysroot_query_metadata: self.query_sysroot_metadata, + ..Default::default() }; - cargo_config.sysroot_query_metadata = self.query_sysroot_metadata; let no_progress = &|_| (); let mut db_load_sw = self.stop_watch(); @@ -302,13 +304,13 @@ impl flags::AnalysisStats { let mut fail = 0; for &c in consts { all += 1; - let Err(e) = c.render_eval(db) else { + let Err(error) = c.render_eval(db) else { continue; }; if verbosity.is_spammy() { let full_name = full_name_of_item(db, c.module(db), c.name(db).unwrap_or(Name::missing())); - println!("Const eval for {full_name} failed due {e:?}"); + println!("Const eval for {full_name} failed due {error:?}"); } fail += 1; } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs index 0182cf5402e56..6d2e97be20e50 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs @@ -13,8 +13,8 @@ use crate::cli::flags; impl flags::Diagnostics { pub fn run(self) -> anyhow::Result<()> { - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let with_proc_macro_server = if let Some(p) = &self.proc_macro_srv { let path = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(p)); ProcMacroServerChoice::Explicit(path) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs index cc9e2a7ce26f8..252b1e1a48581 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs @@ -71,7 +71,7 @@ xflags::xflags! { optional --with-deps /// Don't load sysroot crates (`std`, `core` & friends). optional --no-sysroot - /// Run cargo metadata on the sysroot to analyze its third-pary dependencies. + /// Run cargo metadata on the sysroot to analyze its third-party dependencies. /// Requires --no-sysroot to not be set. optional --query-sysroot-metadata diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs index 2138ecead53f4..64f965e22ac70 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs @@ -287,8 +287,8 @@ impl flags::Lsif { pub fn run(self) -> anyhow::Result<()> { eprintln!("Generating LSIF started..."); let now = Instant::now(); - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let no_progress = &|_| (); let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/parse.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/parse.rs index 5ef8cdff4cf25..757f2dd70cad9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/parse.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/parse.rs @@ -5,7 +5,7 @@ use crate::cli::{flags, read_stdin}; impl flags::Parse { pub fn run(self) -> anyhow::Result<()> { - let _p = profile::span("parsing"); + let _p = tracing::span!(tracing::Level::INFO, "parsing").entered(); let text = read_stdin()?; let file = SourceFile::parse(&text).tree(); if !self.no_dump { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs index e1704199151a6..d07dcdec25105 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs @@ -13,8 +13,8 @@ use crate::cli::{flags, full_name_of_item, Result}; impl flags::RunTests { pub fn run(self) -> Result<()> { - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 522eb53128fb7..be7e434acac25 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -59,8 +59,8 @@ impl Tester { path.push("ra-rustc-test.rs"); let tmp_file = AbsPathBuf::try_from(path).unwrap(); std::fs::write(&tmp_file, "")?; - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let workspace = ProjectWorkspace::DetachedFiles { files: vec![tmp_file.clone()], sysroot: Ok(Sysroot::discover( diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index c9cf40db3a4cb..81622a4617ab9 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -143,11 +143,14 @@ impl flags::Scip { .map(|hover| hover.markup.as_str()) .filter(|it| !it.is_empty()) .map(|it| vec![it.to_owned()]); + let position_encoding = + scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into(); let signature_documentation = token.signature.clone().map(|text| scip_types::Document { relative_path: relative_path.clone(), language: "rust".to_string(), text, + position_encoding, ..Default::default() }); let symbol_info = scip_types::SymbolInformation { @@ -181,13 +184,16 @@ impl flags::Scip { continue; } + let position_encoding = + scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into(); documents.push(scip_types::Document { relative_path, language: "rust".to_string(), occurrences, symbols, - special_fields: Default::default(), text: String::new(), + position_encoding, + special_fields: Default::default(), }); } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs index f87dcb889a48b..8f11d82f8fd93 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs @@ -10,8 +10,8 @@ use crate::cli::flags; impl flags::Ssr { pub fn run(self) -> anyhow::Result<()> { use ide_db::base_db::SourceDatabaseExt; - let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustLibSource::Discover); + let cargo_config = + CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 3c1b464c3c1f5..815f6ea12e86c 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -32,6 +32,7 @@ use project_model::{ }; use rustc_hash::{FxHashMap, FxHashSet}; use serde::{de::DeserializeOwned, Deserialize}; +use stdx::format_to_acc; use vfs::{AbsPath, AbsPathBuf}; use crate::{ @@ -494,6 +495,9 @@ config_data! { /// Exclude imports from find-all-references. references_excludeImports: bool = "false", + /// Exclude tests from find-all-references. + references_excludeTests: bool = "false", + /// Allow renaming of items not belonging to the loaded workspaces. rename_allowExternalItems: bool = "false", @@ -1545,6 +1549,10 @@ impl Config { self.data.references_excludeImports } + pub fn find_all_refs_exclude_tests(&self) -> bool { + self.data.references_excludeTests + } + pub fn snippet_cap(&self) -> bool { self.experimental("snippetTextEdit") } @@ -1737,7 +1745,7 @@ impl Config { } pub fn main_loop_num_threads(&self) -> usize { - self.data.numThreads.unwrap_or(num_cpus::get_physical().try_into().unwrap_or(1)) + self.data.numThreads.unwrap_or(num_cpus::get_physical()) } pub fn typing_autoclose_angle(&self) -> bool { @@ -2556,14 +2564,13 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json #[cfg(test)] fn manual(fields: &[(&'static str, &'static str, &[&str], &str)]) -> String { - fields - .iter() - .map(|(field, _ty, doc, default)| { - let name = format!("rust-analyzer.{}", field.replace('_', ".")); - let doc = doc_comment_to_string(doc); - if default.contains('\n') { - format!( - r#"[[{name}]]{name}:: + fields.iter().fold(String::new(), |mut acc, (field, _ty, doc, default)| { + let name = format!("rust-analyzer.{}", field.replace('_', ".")); + let doc = doc_comment_to_string(doc); + if default.contains('\n') { + format_to_acc!( + acc, + r#"[[{name}]]{name}:: + -- Default: @@ -2573,16 +2580,17 @@ Default: {doc} -- "# - ) - } else { - format!("[[{name}]]{name} (default: `{default}`)::\n+\n--\n{doc}--\n") - } - }) - .collect::() + ) + } else { + format_to_acc!(acc, "[[{name}]]{name} (default: `{default}`)::\n+\n--\n{doc}--\n") + } + }) } fn doc_comment_to_string(doc: &[&str]) -> String { - doc.iter().map(|it| it.strip_prefix(' ').unwrap_or(it)).map(|it| format!("{it}\n")).collect() + doc.iter() + .map(|it| it.strip_prefix(' ').unwrap_or(it)) + .fold(String::new(), |mut acc, it| format_to_acc!(acc, "{it}\n")) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs index ab3881f438b2a..c91b22999dede 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs @@ -128,7 +128,7 @@ pub(crate) fn fetch_native_diagnostics( snapshot: GlobalStateSnapshot, subscriptions: Vec, ) -> Vec<(FileId, Vec)> { - let _p = profile::span("fetch_native_diagnostics"); + let _p = tracing::span!(tracing::Level::INFO, "fetch_native_diagnostics").entered(); let _ctx = stdx::panic_context::enter("fetch_native_diagnostics".to_owned()); let convert_diagnostic = diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs index 7da4311888181..fa856a796a8ef 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs @@ -1,5 +1,8 @@ //! See [RequestDispatcher]. -use std::{fmt, panic, thread}; +use std::{ + fmt::{self, Debug}, + panic, thread, +}; use ide::Cancelled; use lsp_server::ExtractError; @@ -49,6 +52,8 @@ impl RequestDispatcher<'_> { Some(it) => it, None => return self, }; + let _guard = tracing::span!(tracing::Level::INFO, "request", method = ?req.method, "request_id" = ?req.id).entered(); + tracing::debug!(?params); let result = { let _pctx = stdx::panic_context::enter(panic_context); f(self.global_state, params) @@ -74,6 +79,8 @@ impl RequestDispatcher<'_> { Some(it) => it, None => return self, }; + let _guard = tracing::span!(tracing::Level::INFO, "request", method = ?req.method, "request_id" = ?req.id).entered(); + tracing::debug!(?params); let global_state_snapshot = self.global_state.snapshot(); let result = panic::catch_unwind(move || { @@ -192,6 +199,8 @@ impl RequestDispatcher<'_> { Some(it) => it, None => return self, }; + let _guard = tracing::span!(tracing::Level::INFO, "request", method = ?req.method, "request_id" = ?req.id).entered(); + tracing::debug!(?params); let world = self.global_state.snapshot(); if MAIN_POOL { @@ -313,12 +322,16 @@ impl NotificationDispatcher<'_> { ) -> anyhow::Result<&mut Self> where N: lsp_types::notification::Notification, - N::Params: DeserializeOwned + Send, + N::Params: DeserializeOwned + Send + Debug, { let not = match self.not.take() { Some(it) => it, None => return Ok(self), }; + + let _guard = + tracing::span!(tracing::Level::INFO, "notification", method = ?not.method).entered(); + let params = match not.extract::(N::METHOD) { Ok(it) => it, Err(ExtractError::JsonError { method, error }) => { @@ -329,6 +342,9 @@ impl NotificationDispatcher<'_> { return Ok(self); } }; + + tracing::debug!(?params); + let _pctx = stdx::panic_context::enter(format!( "\nversion: {}\nnotification: {}", version(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs index 232c03ae6c4fe..2f226d01155bd 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs @@ -215,7 +215,7 @@ impl GlobalState { } pub(crate) fn process_changes(&mut self) -> bool { - let _p = profile::span("GlobalState::process_changes"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::process_changes").entered(); let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default(); let (change, modified_rust_files, workspace_structure_change) = { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs index c556fdee504b8..1f24e95010571 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs @@ -54,7 +54,7 @@ pub(crate) fn handle_did_open_text_document( state: &mut GlobalState, params: DidOpenTextDocumentParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_did_open_text_document"); + let _p = tracing::span!(tracing::Level::INFO, "handle_did_open_text_document").entered(); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { let already_exists = state @@ -79,7 +79,7 @@ pub(crate) fn handle_did_change_text_document( state: &mut GlobalState, params: DidChangeTextDocumentParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_did_change_text_document"); + let _p = tracing::span!(tracing::Level::INFO, "handle_did_change_text_document").entered(); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { let data = match state.mem_docs.get_mut(&path) { @@ -113,7 +113,7 @@ pub(crate) fn handle_did_close_text_document( state: &mut GlobalState, params: DidCloseTextDocumentParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_did_close_text_document"); + let _p = tracing::span!(tracing::Level::INFO, "handle_did_close_text_document").entered(); if let Ok(path) = from_proto::vfs_path(¶ms.text_document.uri) { if state.mem_docs.remove(&path).is_err() { @@ -247,7 +247,7 @@ pub(crate) fn handle_did_change_watched_files( } fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { - let _p = profile::span("run_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "run_flycheck").entered(); let file_id = state.vfs.read().0.file_id(&vfs_path); if let Some(file_id) = file_id { @@ -326,13 +326,13 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool { } pub(crate) fn handle_cancel_flycheck(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { - let _p = profile::span("handle_stop_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "handle_stop_flycheck").entered(); state.flycheck.iter().for_each(|flycheck| flycheck.cancel()); Ok(()) } pub(crate) fn handle_clear_flycheck(state: &mut GlobalState, _: ()) -> anyhow::Result<()> { - let _p = profile::span("handle_clear_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "handle_clear_flycheck").entered(); state.diagnostics.clear_check_all(); Ok(()) } @@ -341,7 +341,7 @@ pub(crate) fn handle_run_flycheck( state: &mut GlobalState, params: RunFlycheckParams, ) -> anyhow::Result<()> { - let _p = profile::span("handle_run_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "handle_run_flycheck").entered(); if let Some(text_document) = params.text_document { if let Ok(vfs_path) = from_proto::vfs_path(&text_document.uri) { if run_flycheck(state, vfs_path) { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index f3c2df24d951b..2be2ba5c44657 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -70,7 +70,7 @@ pub(crate) fn handle_analyzer_status( snap: GlobalStateSnapshot, params: lsp_ext::AnalyzerStatusParams, ) -> anyhow::Result { - let _p = profile::span("handle_analyzer_status"); + let _p = tracing::span!(tracing::Level::INFO, "handle_analyzer_status").entered(); let mut buf = String::new(); @@ -114,7 +114,7 @@ pub(crate) fn handle_analyzer_status( } pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> anyhow::Result { - let _p = profile::span("handle_memory_usage"); + let _p = tracing::span!(tracing::Level::INFO, "handle_memory_usage").entered(); let mem = state.analysis_host.per_query_memory_usage(); let mut out = String::new(); @@ -135,7 +135,7 @@ pub(crate) fn handle_syntax_tree( snap: GlobalStateSnapshot, params: lsp_ext::SyntaxTreeParams, ) -> anyhow::Result { - let _p = profile::span("handle_syntax_tree"); + let _p = tracing::span!(tracing::Level::INFO, "handle_syntax_tree").entered(); let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(id)?; let text_range = params.range.and_then(|r| from_proto::text_range(&line_index, r).ok()); @@ -147,7 +147,7 @@ pub(crate) fn handle_view_hir( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_hir"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_hir").entered(); let position = from_proto::file_position(&snap, params)?; let res = snap.analysis.view_hir(position)?; Ok(res) @@ -157,7 +157,7 @@ pub(crate) fn handle_view_mir( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_mir"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_mir").entered(); let position = from_proto::file_position(&snap, params)?; let res = snap.analysis.view_mir(position)?; Ok(res) @@ -167,7 +167,7 @@ pub(crate) fn handle_interpret_function( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_interpret_function"); + let _p = tracing::span!(tracing::Level::INFO, "handle_interpret_function").entered(); let position = from_proto::file_position(&snap, params)?; let res = snap.analysis.interpret_function(position)?; Ok(res) @@ -185,7 +185,7 @@ pub(crate) fn handle_view_item_tree( snap: GlobalStateSnapshot, params: lsp_ext::ViewItemTreeParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_item_tree"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_item_tree").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let res = snap.analysis.view_item_tree(file_id)?; Ok(res) @@ -195,7 +195,7 @@ pub(crate) fn handle_view_crate_graph( snap: GlobalStateSnapshot, params: ViewCrateGraphParams, ) -> anyhow::Result { - let _p = profile::span("handle_view_crate_graph"); + let _p = tracing::span!(tracing::Level::INFO, "handle_view_crate_graph").entered(); let dot = snap.analysis.view_crate_graph(params.full)?.map_err(anyhow::Error::msg)?; Ok(dot) } @@ -204,7 +204,7 @@ pub(crate) fn handle_expand_macro( snap: GlobalStateSnapshot, params: lsp_ext::ExpandMacroParams, ) -> anyhow::Result> { - let _p = profile::span("handle_expand_macro"); + let _p = tracing::span!(tracing::Level::INFO, "handle_expand_macro").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let offset = from_proto::offset(&line_index, params.position)?; @@ -217,7 +217,7 @@ pub(crate) fn handle_selection_range( snap: GlobalStateSnapshot, params: lsp_types::SelectionRangeParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_selection_range"); + let _p = tracing::span!(tracing::Level::INFO, "handle_selection_range").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let res: anyhow::Result> = params @@ -260,7 +260,7 @@ pub(crate) fn handle_matching_brace( snap: GlobalStateSnapshot, params: lsp_ext::MatchingBraceParams, ) -> anyhow::Result> { - let _p = profile::span("handle_matching_brace"); + let _p = tracing::span!(tracing::Level::INFO, "handle_matching_brace").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; params @@ -283,7 +283,7 @@ pub(crate) fn handle_join_lines( snap: GlobalStateSnapshot, params: lsp_ext::JoinLinesParams, ) -> anyhow::Result> { - let _p = profile::span("handle_join_lines"); + let _p = tracing::span!(tracing::Level::INFO, "handle_join_lines").entered(); let config = snap.config.join_lines(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; @@ -308,7 +308,7 @@ pub(crate) fn handle_on_enter( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_on_enter"); + let _p = tracing::span!(tracing::Level::INFO, "handle_on_enter").entered(); let position = from_proto::file_position(&snap, params)?; let edit = match snap.analysis.on_enter(position)? { None => return Ok(None), @@ -323,7 +323,7 @@ pub(crate) fn handle_on_type_formatting( snap: GlobalStateSnapshot, params: lsp_types::DocumentOnTypeFormattingParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_on_type_formatting"); + let _p = tracing::span!(tracing::Level::INFO, "handle_on_type_formatting").entered(); let mut position = from_proto::file_position(&snap, params.text_document_position)?; let line_index = snap.file_line_index(position.file_id)?; @@ -364,7 +364,7 @@ pub(crate) fn handle_document_symbol( snap: GlobalStateSnapshot, params: lsp_types::DocumentSymbolParams, ) -> anyhow::Result> { - let _p = profile::span("handle_document_symbol"); + let _p = tracing::span!(tracing::Level::INFO, "handle_document_symbol").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; @@ -453,7 +453,7 @@ pub(crate) fn handle_workspace_symbol( snap: GlobalStateSnapshot, params: WorkspaceSymbolParams, ) -> anyhow::Result> { - let _p = profile::span("handle_workspace_symbol"); + let _p = tracing::span!(tracing::Level::INFO, "handle_workspace_symbol").entered(); let config = snap.config.workspace_symbol(); let (all_symbols, libs) = decide_search_scope_and_kind(¶ms, &config); @@ -545,7 +545,7 @@ pub(crate) fn handle_will_rename_files( snap: GlobalStateSnapshot, params: lsp_types::RenameFilesParams, ) -> anyhow::Result> { - let _p = profile::span("handle_will_rename_files"); + let _p = tracing::span!(tracing::Level::INFO, "handle_will_rename_files").entered(); let source_changes: Vec = params .files @@ -607,7 +607,7 @@ pub(crate) fn handle_goto_definition( snap: GlobalStateSnapshot, params: lsp_types::GotoDefinitionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_definition"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_definition").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.goto_definition(position)? { None => return Ok(None), @@ -622,7 +622,7 @@ pub(crate) fn handle_goto_declaration( snap: GlobalStateSnapshot, params: lsp_types::request::GotoDeclarationParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_declaration"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_declaration").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params.clone())?; let nav_info = match snap.analysis.goto_declaration(position)? { None => return handle_goto_definition(snap, params), @@ -637,7 +637,7 @@ pub(crate) fn handle_goto_implementation( snap: GlobalStateSnapshot, params: lsp_types::request::GotoImplementationParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_implementation"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_implementation").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.goto_implementation(position)? { None => return Ok(None), @@ -652,7 +652,7 @@ pub(crate) fn handle_goto_type_definition( snap: GlobalStateSnapshot, params: lsp_types::request::GotoTypeDefinitionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_goto_type_definition"); + let _p = tracing::span!(tracing::Level::INFO, "handle_goto_type_definition").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.goto_type_definition(position)? { None => return Ok(None), @@ -667,7 +667,7 @@ pub(crate) fn handle_parent_module( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_parent_module"); + let _p = tracing::span!(tracing::Level::INFO, "handle_parent_module").entered(); if let Ok(file_path) = ¶ms.text_document.uri.to_file_path() { if file_path.file_name().unwrap_or_default() == "Cargo.toml" { // search workspaces for parent packages or fallback to workspace root @@ -734,7 +734,7 @@ pub(crate) fn handle_runnables( snap: GlobalStateSnapshot, params: lsp_ext::RunnablesParams, ) -> anyhow::Result> { - let _p = profile::span("handle_runnables"); + let _p = tracing::span!(tracing::Level::INFO, "handle_runnables").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let offset = params.position.and_then(|it| from_proto::offset(&line_index, it).ok()); @@ -829,7 +829,7 @@ pub(crate) fn handle_related_tests( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_related_tests"); + let _p = tracing::span!(tracing::Level::INFO, "handle_related_tests").entered(); let position = from_proto::file_position(&snap, params)?; let tests = snap.analysis.related_tests(position, None)?; @@ -847,7 +847,7 @@ pub(crate) fn handle_completion( snap: GlobalStateSnapshot, params: lsp_types::CompletionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_completion"); + let _p = tracing::span!(tracing::Level::INFO, "handle_completion").entered(); let text_document_position = params.text_document_position.clone(); let position = from_proto::file_position(&snap, params.text_document_position)?; let completion_trigger_character = @@ -875,7 +875,7 @@ pub(crate) fn handle_completion_resolve( snap: GlobalStateSnapshot, mut original_completion: CompletionItem, ) -> anyhow::Result { - let _p = profile::span("handle_completion_resolve"); + let _p = tracing::span!(tracing::Level::INFO, "handle_completion_resolve").entered(); if !all_edits_are_disjoint(&original_completion, &[]) { return Err(invalid_params_error( @@ -931,7 +931,7 @@ pub(crate) fn handle_folding_range( snap: GlobalStateSnapshot, params: FoldingRangeParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_folding_range"); + let _p = tracing::span!(tracing::Level::INFO, "handle_folding_range").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let folds = snap.analysis.folding_ranges(file_id)?; let text = snap.analysis.file_text(file_id)?; @@ -948,7 +948,7 @@ pub(crate) fn handle_signature_help( snap: GlobalStateSnapshot, params: lsp_types::SignatureHelpParams, ) -> anyhow::Result> { - let _p = profile::span("handle_signature_help"); + let _p = tracing::span!(tracing::Level::INFO, "handle_signature_help").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let help = match snap.analysis.signature_help(position)? { Some(it) => it, @@ -963,7 +963,7 @@ pub(crate) fn handle_hover( snap: GlobalStateSnapshot, params: lsp_ext::HoverParams, ) -> anyhow::Result> { - let _p = profile::span("handle_hover"); + let _p = tracing::span!(tracing::Level::INFO, "handle_hover").entered(); let range = match params.position { PositionOrRange::Position(position) => Range::new(position, position), PositionOrRange::Range(range) => range, @@ -1000,7 +1000,7 @@ pub(crate) fn handle_prepare_rename( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("handle_prepare_rename"); + let _p = tracing::span!(tracing::Level::INFO, "handle_prepare_rename").entered(); let position = from_proto::file_position(&snap, params)?; let change = snap.analysis.prepare_rename(position)?.map_err(to_proto::rename_error)?; @@ -1014,7 +1014,7 @@ pub(crate) fn handle_rename( snap: GlobalStateSnapshot, params: RenameParams, ) -> anyhow::Result> { - let _p = profile::span("handle_rename"); + let _p = tracing::span!(tracing::Level::INFO, "handle_rename").entered(); let position = from_proto::file_position(&snap, params.text_document_position)?; let mut change = snap @@ -1051,10 +1051,11 @@ pub(crate) fn handle_references( snap: GlobalStateSnapshot, params: lsp_types::ReferenceParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_references"); + let _p = tracing::span!(tracing::Level::INFO, "handle_references").entered(); let position = from_proto::file_position(&snap, params.text_document_position)?; let exclude_imports = snap.config.find_all_refs_exclude_imports(); + let exclude_tests = snap.config.find_all_refs_exclude_tests(); let refs = match snap.analysis.find_all_refs(position, None)? { None => return Ok(None), @@ -1078,7 +1079,8 @@ pub(crate) fn handle_references( .flat_map(|(file_id, refs)| { refs.into_iter() .filter(|&(_, category)| { - !exclude_imports || category != Some(ReferenceCategory::Import) + (!exclude_imports || category != Some(ReferenceCategory::Import)) + && (!exclude_tests || category != Some(ReferenceCategory::Test)) }) .map(move |(range, _)| FileRange { file_id, range }) }) @@ -1094,7 +1096,7 @@ pub(crate) fn handle_formatting( snap: GlobalStateSnapshot, params: lsp_types::DocumentFormattingParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_formatting"); + let _p = tracing::span!(tracing::Level::INFO, "handle_formatting").entered(); run_rustfmt(&snap, params.text_document, None) } @@ -1103,7 +1105,7 @@ pub(crate) fn handle_range_formatting( snap: GlobalStateSnapshot, params: lsp_types::DocumentRangeFormattingParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_range_formatting"); + let _p = tracing::span!(tracing::Level::INFO, "handle_range_formatting").entered(); run_rustfmt(&snap, params.text_document, Some(params.range)) } @@ -1112,7 +1114,7 @@ pub(crate) fn handle_code_action( snap: GlobalStateSnapshot, params: lsp_types::CodeActionParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_code_action"); + let _p = tracing::span!(tracing::Level::INFO, "handle_code_action").entered(); if !snap.config.code_action_literals() { // We intentionally don't support command-based actions, as those either @@ -1186,7 +1188,7 @@ pub(crate) fn handle_code_action_resolve( snap: GlobalStateSnapshot, mut code_action: lsp_ext::CodeAction, ) -> anyhow::Result { - let _p = profile::span("handle_code_action_resolve"); + let _p = tracing::span!(tracing::Level::INFO, "handle_code_action_resolve").entered(); let params = match code_action.data.take() { Some(it) => it, None => return Err(invalid_params_error("code action without data".to_string()).into()), @@ -1276,7 +1278,7 @@ pub(crate) fn handle_code_lens( snap: GlobalStateSnapshot, params: lsp_types::CodeLensParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_code_lens"); + let _p = tracing::span!(tracing::Level::INFO, "handle_code_lens").entered(); let lens_config = snap.config.lens(); if lens_config.none() { @@ -1319,6 +1321,9 @@ pub(crate) fn handle_code_lens_resolve( snap: GlobalStateSnapshot, code_lens: CodeLens, ) -> anyhow::Result { + if code_lens.data.is_none() { + return Ok(code_lens); + } let Some(annotation) = from_proto::annotation(&snap, code_lens.clone())? else { return Ok(code_lens); }; @@ -1327,13 +1332,14 @@ pub(crate) fn handle_code_lens_resolve( let mut acc = Vec::new(); to_proto::code_lens(&mut acc, &snap, annotation)?; - let res = match acc.pop() { + let mut res = match acc.pop() { Some(it) if acc.is_empty() => it, _ => { never!(); code_lens } }; + res.data = None; Ok(res) } @@ -1342,7 +1348,7 @@ pub(crate) fn handle_document_highlight( snap: GlobalStateSnapshot, params: lsp_types::DocumentHighlightParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_document_highlight"); + let _p = tracing::span!(tracing::Level::INFO, "handle_document_highlight").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let line_index = snap.file_line_index(position.file_id)?; @@ -1364,7 +1370,7 @@ pub(crate) fn handle_ssr( snap: GlobalStateSnapshot, params: lsp_ext::SsrParams, ) -> anyhow::Result { - let _p = profile::span("handle_ssr"); + let _p = tracing::span!(tracing::Level::INFO, "handle_ssr").entered(); let selections = params .selections .iter() @@ -1384,7 +1390,7 @@ pub(crate) fn handle_inlay_hints( snap: GlobalStateSnapshot, params: InlayHintParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_inlay_hints"); + let _p = tracing::span!(tracing::Level::INFO, "handle_inlay_hints").entered(); let document_uri = ¶ms.text_document.uri; let FileRange { file_id, range } = from_proto::file_range( &snap, @@ -1414,7 +1420,7 @@ pub(crate) fn handle_inlay_hints_resolve( snap: GlobalStateSnapshot, mut original_hint: InlayHint, ) -> anyhow::Result { - let _p = profile::span("handle_inlay_hints_resolve"); + let _p = tracing::span!(tracing::Level::INFO, "handle_inlay_hints_resolve").entered(); let data = match original_hint.data.take() { Some(it) => it, @@ -1461,7 +1467,7 @@ pub(crate) fn handle_call_hierarchy_prepare( snap: GlobalStateSnapshot, params: CallHierarchyPrepareParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_call_hierarchy_prepare"); + let _p = tracing::span!(tracing::Level::INFO, "handle_call_hierarchy_prepare").entered(); let position = from_proto::file_position(&snap, params.text_document_position_params)?; let nav_info = match snap.analysis.call_hierarchy(position)? { @@ -1483,7 +1489,7 @@ pub(crate) fn handle_call_hierarchy_incoming( snap: GlobalStateSnapshot, params: CallHierarchyIncomingCallsParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_call_hierarchy_incoming"); + let _p = tracing::span!(tracing::Level::INFO, "handle_call_hierarchy_incoming").entered(); let item = params.item; let doc = TextDocumentIdentifier::new(item.uri); @@ -1518,7 +1524,7 @@ pub(crate) fn handle_call_hierarchy_outgoing( snap: GlobalStateSnapshot, params: CallHierarchyOutgoingCallsParams, ) -> anyhow::Result>> { - let _p = profile::span("handle_call_hierarchy_outgoing"); + let _p = tracing::span!(tracing::Level::INFO, "handle_call_hierarchy_outgoing").entered(); let item = params.item; let doc = TextDocumentIdentifier::new(item.uri); @@ -1553,7 +1559,7 @@ pub(crate) fn handle_semantic_tokens_full( snap: GlobalStateSnapshot, params: SemanticTokensParams, ) -> anyhow::Result> { - let _p = profile::span("handle_semantic_tokens_full"); + let _p = tracing::span!(tracing::Level::INFO, "handle_semantic_tokens_full").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let text = snap.analysis.file_text(file_id)?; @@ -1583,7 +1589,7 @@ pub(crate) fn handle_semantic_tokens_full_delta( snap: GlobalStateSnapshot, params: SemanticTokensDeltaParams, ) -> anyhow::Result> { - let _p = profile::span("handle_semantic_tokens_full_delta"); + let _p = tracing::span!(tracing::Level::INFO, "handle_semantic_tokens_full_delta").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let text = snap.analysis.file_text(file_id)?; @@ -1626,7 +1632,7 @@ pub(crate) fn handle_semantic_tokens_range( snap: GlobalStateSnapshot, params: SemanticTokensRangeParams, ) -> anyhow::Result> { - let _p = profile::span("handle_semantic_tokens_range"); + let _p = tracing::span!(tracing::Level::INFO, "handle_semantic_tokens_range").entered(); let frange = from_proto::file_range(&snap, ¶ms.text_document, params.range)?; let text = snap.analysis.file_text(frange.file_id)?; @@ -1652,7 +1658,7 @@ pub(crate) fn handle_open_docs( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result { - let _p = profile::span("handle_open_docs"); + let _p = tracing::span!(tracing::Level::INFO, "handle_open_docs").entered(); let position = from_proto::file_position(&snap, params)?; let ws_and_sysroot = snap.workspaces.iter().find_map(|ws| match ws { @@ -1691,7 +1697,7 @@ pub(crate) fn handle_open_cargo_toml( snap: GlobalStateSnapshot, params: lsp_ext::OpenCargoTomlParams, ) -> anyhow::Result> { - let _p = profile::span("handle_open_cargo_toml"); + let _p = tracing::span!(tracing::Level::INFO, "handle_open_cargo_toml").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let cargo_spec = match CargoTargetSpec::for_file(&snap, file_id)? { @@ -1709,7 +1715,7 @@ pub(crate) fn handle_move_item( snap: GlobalStateSnapshot, params: lsp_ext::MoveItemParams, ) -> anyhow::Result> { - let _p = profile::span("handle_move_item"); + let _p = tracing::span!(tracing::Level::INFO, "handle_move_item").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let range = from_proto::file_range(&snap, ¶ms.text_document, params.range)?; @@ -1731,7 +1737,7 @@ pub(crate) fn handle_view_recursive_memory_layout( snap: GlobalStateSnapshot, params: lsp_types::TextDocumentPositionParams, ) -> anyhow::Result> { - let _p = profile::span("view_recursive_memory_layout"); + let _p = tracing::span!(tracing::Level::INFO, "view_recursive_memory_layout").entered(); let file_id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; let line_index = snap.file_line_index(file_id)?; let offset = from_proto::offset(&line_index, params.position)?; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index d94f7cefa60ee..acc02d6447c63 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -60,7 +60,7 @@ fn integrated_highlighting_benchmark() { analysis.highlight_as_html(file_id, false).unwrap(); } - profile::init_from("*>100"); + crate::tracing::hprof::init("*>100"); { let _it = stdx::timeit("change"); @@ -152,8 +152,7 @@ fn integrated_completion_benchmark() { analysis.completions(&config, position, None).unwrap(); } - profile::init_from("*>5"); - // let _s = profile::heartbeat_span(); + crate::tracing::hprof::init("*>5"); let completion_offset = { let _it = stdx::timeit("change"); @@ -168,7 +167,7 @@ fn integrated_completion_benchmark() { }; { - let _p = profile::span("unqualified path completion"); + let _p = tracing::span!(tracing::Level::INFO, "unqualified path completion").entered(); let _span = profile::cpu_span(); let analysis = host.analysis(); let config = CompletionConfig { @@ -209,7 +208,7 @@ fn integrated_completion_benchmark() { }; { - let _p = profile::span("dot completion"); + let _p = tracing::span!(tracing::Level::INFO, "dot completion").entered(); let _span = profile::cpu_span(); let analysis = host.analysis(); let config = CompletionConfig { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs index 29bc0b80d8a1d..b1809f58ae700 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs @@ -13,11 +13,6 @@ pub mod cli; -#[allow(unused)] -macro_rules! eprintln { - ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; -} - mod caps; mod cargo_target_spec; mod diagnostics; @@ -37,6 +32,12 @@ mod handlers { pub(crate) mod request; } +pub mod tracing { + pub mod config; + pub use config::Config; + pub mod hprof; +} + pub mod config; pub mod lsp; use self::lsp::ext as lsp_ext; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs index ac7e1a95e622f..9e0d42faed43f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp.rs @@ -2,11 +2,11 @@ use core::fmt; -pub(crate) mod utils; -pub(crate) mod semantic_tokens; pub mod ext; pub(crate) mod from_proto; +pub(crate) mod semantic_tokens; pub(crate) mod to_proto; +pub(crate) mod utils; #[derive(Debug)] pub(crate) struct LspError { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index fe381fbeb3f03..d363ac69fdc33 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -92,6 +92,7 @@ pub(crate) fn document_highlight_kind( ReferenceCategory::Read => Some(lsp_types::DocumentHighlightKind::READ), ReferenceCategory::Write => Some(lsp_types::DocumentHighlightKind::WRITE), ReferenceCategory::Import => None, + ReferenceCategory::Test => None, } } @@ -311,16 +312,14 @@ fn completion_item( set_score(&mut lsp_item, max_relevance, item.relevance); if config.completion().enable_imports_on_the_fly && !item.import_to_add.is_empty() { - let imports: Vec<_> = item + let imports = item .import_to_add .into_iter() - .filter_map(|(import_path, import_name)| { - Some(lsp_ext::CompletionImport { - full_import_path: import_path, - imported_name: import_name, - }) + .map(|(import_path, import_name)| lsp_ext::CompletionImport { + full_import_path: import_path, + imported_name: import_name, }) - .collect(); + .collect::>(); if !imports.is_empty() { let data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports }; lsp_item.data = Some(to_value(data).unwrap()); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 0173805d44779..f3ead6d04f7d7 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -60,6 +60,17 @@ enum Event { Flycheck(flycheck::Message), } +impl fmt::Display for Event { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Event::Lsp(_) => write!(f, "Event::Lsp"), + Event::Task(_) => write!(f, "Event::Task"), + Event::Vfs(_) => write!(f, "Event::Vfs"), + Event::Flycheck(_) => write!(f, "Event::Flycheck"), + } + } +} + #[derive(Debug)] pub(crate) enum Task { Response(lsp_server::Response), @@ -196,7 +207,8 @@ impl GlobalState { fn handle_event(&mut self, event: Event) -> anyhow::Result<()> { let loop_start = Instant::now(); // NOTE: don't count blocking select! call as a loop-turn time - let _p = profile::span("GlobalState::handle_event"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event", event = %event) + .entered(); let event_dbg_msg = format!("{event:?}"); tracing::debug!("{:?} handle_event({})", loop_start, event_dbg_msg); @@ -215,7 +227,8 @@ impl GlobalState { lsp_server::Message::Response(resp) => self.complete_request(resp), }, Event::Task(task) => { - let _p = profile::span("GlobalState::handle_event/task"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/task") + .entered(); let mut prime_caches_progress = Vec::new(); self.handle_task(&mut prime_caches_progress, task); @@ -269,7 +282,8 @@ impl GlobalState { } } Event::Vfs(message) => { - let _p = profile::span("GlobalState::handle_event/vfs"); + let _p = + tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/vfs").entered(); self.handle_vfs_msg(message); // Coalesce many VFS event into a single loop turn while let Ok(message) = self.loader.receiver.try_recv() { @@ -277,7 +291,8 @@ impl GlobalState { } } Event::Flycheck(message) => { - let _p = profile::span("GlobalState::handle_event/flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/flycheck") + .entered(); self.handle_flycheck_msg(message); // Coalesce many flycheck updates into a single loop turn while let Ok(message) = self.flycheck_receiver.try_recv() { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs index 969211f44007c..65c00cc08d1a1 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs @@ -70,7 +70,8 @@ impl GlobalState { } pub(crate) fn update_configuration(&mut self, config: Config) { - let _p = profile::span("GlobalState::update_configuration"); + let _p = + tracing::span!(tracing::Level::INFO, "GlobalState::update_configuration").entered(); let old_config = mem::replace(&mut self.config, Arc::new(config)); if self.config.lru_parse_query_capacity() != old_config.lru_parse_query_capacity() { self.analysis_host.update_lru_capacity(self.config.lru_parse_query_capacity()); @@ -355,7 +356,7 @@ impl GlobalState { } pub(crate) fn switch_workspaces(&mut self, cause: Cause) { - let _p = profile::span("GlobalState::switch_workspaces"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::switch_workspaces").entered(); tracing::info!(%cause, "will switch workspaces"); let Some((workspaces, force_reload_crate_graph)) = @@ -502,7 +503,7 @@ impl GlobalState { let mut crate_graph_file_dependencies = FxHashSet::default(); let mut load = |path: &AbsPath| { - let _p = profile::span("switch_workspaces::load"); + let _p = tracing::span!(tracing::Level::INFO, "switch_workspaces::load").entered(); let vfs_path = vfs::VfsPath::from(path.to_path_buf()); crate_graph_file_dependencies.insert(vfs_path.clone()); match vfs.file_id(&vfs_path) { @@ -585,7 +586,7 @@ impl GlobalState { } fn reload_flycheck(&mut self) { - let _p = profile::span("GlobalState::reload_flycheck"); + let _p = tracing::span!(tracing::Level::INFO, "GlobalState::reload_flycheck").entered(); let config = self.config.flycheck(); let sender = self.flycheck_sender.clone(); let invocation_strategy = match config { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs new file mode 100644 index 0000000000000..fcdbd1e6d9b56 --- /dev/null +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs @@ -0,0 +1,108 @@ +//! Simple logger that logs either to stderr or to a file, using `tracing_subscriber` +//! filter syntax and `tracing_appender` for non blocking output. + +use std::io; + +use anyhow::Context; +use tracing::{level_filters::LevelFilter, Level}; +use tracing_subscriber::{ + filter::{self, Targets}, + fmt::{format::FmtSpan, MakeWriter}, + layer::SubscriberExt, + util::SubscriberInitExt, + Layer, Registry, +}; +use tracing_tree::HierarchicalLayer; + +use crate::tracing::hprof; + +pub struct Config { + pub writer: T, + pub filter: String, + /// The meaning of CHALK_DEBUG is to tell chalk crates + /// (i.e. chalk-solve, chalk-ir, chalk-recursive) how to filter tracing + /// logs. But now we can only have just one filter, which means we have to + /// merge chalk filter to our main filter (from RA_LOG env). + /// + /// The acceptable syntax of CHALK_DEBUG is `target[span{field=value}]=level`. + /// As the value should only affect chalk crates, we'd better manually + /// specify the target. And for simplicity, CHALK_DEBUG only accept the value + /// that specify level. + pub chalk_filter: Option, + /// Filtering syntax, set in a shell: + /// ``` + /// env RA_PROFILE=* // dump everything + /// env RA_PROFILE=foo|bar|baz // enabled only selected entries + /// env RA_PROFILE=*@3>10 // dump everything, up to depth 3, if it takes more than 10 + /// ``` + pub profile_filter: Option, +} + +impl Config +where + T: for<'writer> MakeWriter<'writer> + Send + Sync + 'static, +{ + pub fn init(self) -> anyhow::Result<()> { + let filter: Targets = self + .filter + .parse() + .with_context(|| format!("invalid log filter: `{}`", self.filter))?; + + let writer = self.writer; + + let ra_fmt_layer = tracing_subscriber::fmt::layer() + .with_span_events(FmtSpan::CLOSE) + .with_writer(writer) + .with_filter(filter); + + let mut chalk_layer = None; + if let Some(chalk_filter) = self.chalk_filter { + let level: LevelFilter = + chalk_filter.parse().with_context(|| "invalid chalk log filter")?; + + let chalk_filter = Targets::new() + .with_target("chalk_solve", level) + .with_target("chalk_ir", level) + .with_target("chalk_recursive", level); + chalk_layer = Some( + HierarchicalLayer::default() + .with_indent_lines(true) + .with_ansi(false) + .with_indent_amount(2) + .with_writer(io::stderr) + .with_filter(chalk_filter), + ); + }; + + let mut profiler_layer = None; + if let Some(spec) = self.profile_filter { + let (write_filter, allowed_names) = hprof::WriteFilter::from_spec(&spec); + + // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like + // span depth or duration are not filtered here: that only occurs at write time. + let profile_filter = filter::filter_fn(move |metadata| { + let allowed = match &allowed_names { + Some(names) => names.contains(metadata.name()), + None => true, + }; + + metadata.is_span() + && allowed + && metadata.level() >= &Level::INFO + && !metadata.target().starts_with("salsa") + && !metadata.target().starts_with("chalk") + }); + + let layer = hprof::SpanTree::default() + .aggregate(true) + .spec_filter(write_filter) + .with_filter(profile_filter); + + profiler_layer = Some(layer); + } + + Registry::default().with(ra_fmt_layer).with(chalk_layer).with(profiler_layer).try_init()?; + + Ok(()) + } +} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs new file mode 100644 index 0000000000000..c99b551df8526 --- /dev/null +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs @@ -0,0 +1,272 @@ +//! Consumer of `tracing` data, which prints a hierarchical profile. +//! +//! Based on https://github.com/davidbarsky/tracing-tree, but does less, while +//! actually printing timings for spans by default. The code here is vendored from +//! https://github.com/matklad/tracing-span-tree. +//! +//! Usage: +//! +//! ```rust +//! let layer = hprof::SpanTree::default(); +//! Registry::default().with(layer).init(); +//! ``` +//! +//! Example output: +//! +//! ```text +//! 8.37ms top_level +//! 1.09ms middle +//! 1.06ms leaf +//! 1.06ms middle +//! 3.12ms middle +//! 1.06ms leaf +//! 3.06ms middle +//! ``` +//! +//! Same data, but with `.aggregate(true)`: +//! +//! ```text +//! 8.39ms top_level +//! 8.35ms 4 middle +//! 2.13ms 2 leaf +//! ``` + +use std::{ + fmt::Write, + mem, + time::{Duration, Instant}, +}; + +use rustc_hash::FxHashSet; +use tracing::{ + field::{Field, Visit}, + span::Attributes, + Event, Id, Level, Subscriber, +}; +use tracing_subscriber::{ + filter, + layer::{Context, SubscriberExt}, + registry::LookupSpan, + Layer, Registry, +}; + +use crate::tracing::hprof; + +pub fn init(spec: &str) { + let (write_filter, allowed_names) = WriteFilter::from_spec(spec); + + // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like + // span depth or duration are not filtered here: that only occurs at write time. + let profile_filter = filter::filter_fn(move |metadata| { + let allowed = match &allowed_names { + Some(names) => names.contains(metadata.name()), + None => true, + }; + + metadata.is_span() + && allowed + && metadata.level() >= &Level::INFO + && !metadata.target().starts_with("salsa") + && !metadata.target().starts_with("chalk") + }); + + let layer = hprof::SpanTree::default() + .aggregate(true) + .spec_filter(write_filter) + .with_filter(profile_filter); + + let subscriber = Registry::default().with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); +} + +#[derive(Default, Debug)] +pub(crate) struct SpanTree { + aggregate: bool, + write_filter: WriteFilter, +} + +impl SpanTree { + /// Merge identical sibling spans together. + pub(crate) fn aggregate(self, yes: bool) -> SpanTree { + SpanTree { aggregate: yes, ..self } + } + + /// Add a write-time filter for span duration or tree depth. + pub(crate) fn spec_filter(self, write_filter: WriteFilter) -> SpanTree { + SpanTree { write_filter, ..self } + } +} + +struct Data { + start: Instant, + children: Vec, + fields: String, +} + +impl Data { + fn new(attrs: &Attributes<'_>) -> Self { + let mut data = Self { start: Instant::now(), children: Vec::new(), fields: String::new() }; + + let mut visitor = DataVisitor { string: &mut data.fields }; + attrs.record(&mut visitor); + data + } + + fn into_node(self, name: &'static str) -> Node { + Node { + name, + fields: self.fields, + count: 1, + duration: self.start.elapsed(), + children: self.children, + } + } +} + +pub struct DataVisitor<'a> { + string: &'a mut String, +} + +impl<'a> Visit for DataVisitor<'a> { + fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) { + write!(self.string, "{} = {:?} ", field.name(), value).unwrap(); + } +} + +impl Layer for SpanTree +where + S: Subscriber + for<'span> LookupSpan<'span>, +{ + fn on_new_span(&self, attrs: &Attributes<'_>, id: &Id, ctx: Context<'_, S>) { + let span = ctx.span(id).unwrap(); + + let data = Data::new(attrs); + span.extensions_mut().insert(data); + } + + fn on_event(&self, _event: &Event<'_>, _ctx: Context<'_, S>) {} + + fn on_close(&self, id: Id, ctx: Context<'_, S>) { + let span = ctx.span(&id).unwrap(); + let data = span.extensions_mut().remove::().unwrap(); + let mut node = data.into_node(span.name()); + + match span.parent() { + Some(parent_span) => { + parent_span.extensions_mut().get_mut::().unwrap().children.push(node); + } + None => { + if self.aggregate { + node.aggregate() + } + node.print(&self.write_filter) + } + } + } +} + +#[derive(Default)] +struct Node { + name: &'static str, + fields: String, + count: u32, + duration: Duration, + children: Vec, +} + +impl Node { + fn print(&self, filter: &WriteFilter) { + self.go(0, filter) + } + + fn go(&self, level: usize, filter: &WriteFilter) { + if self.duration > filter.longer_than && level < filter.depth { + let duration = ms(self.duration); + let current_indent = level * 2; + + let mut out = String::new(); + let _ = write!(out, "{:current_indent$} {duration} {:<6}", "", self.name); + + if !self.fields.is_empty() { + let _ = write!(out, " @ {}", self.fields); + } + + if self.count > 1 { + let _ = write!(out, " ({} calls)", self.count); + } + + eprintln!("{}", out); + + for child in &self.children { + child.go(level + 1, filter) + } + } + } + + fn aggregate(&mut self) { + if self.children.is_empty() { + return; + } + + self.children.sort_by_key(|it| it.name); + let mut idx = 0; + for i in 1..self.children.len() { + if self.children[idx].name == self.children[i].name { + let child = mem::take(&mut self.children[i]); + self.children[idx].duration += child.duration; + self.children[idx].count += child.count; + self.children[idx].children.extend(child.children); + } else { + idx += 1; + assert!(idx <= i); + self.children.swap(idx, i); + } + } + self.children.truncate(idx + 1); + for child in &mut self.children { + child.aggregate() + } + } +} + +#[derive(Default, Clone, Debug)] +pub(crate) struct WriteFilter { + depth: usize, + longer_than: Duration, +} + +impl WriteFilter { + pub(crate) fn from_spec(mut spec: &str) -> (WriteFilter, Option>) { + let longer_than = if let Some(idx) = spec.rfind('>') { + let longer_than = spec[idx + 1..].parse().expect("invalid profile longer_than"); + spec = &spec[..idx]; + Duration::from_millis(longer_than) + } else { + Duration::new(0, 0) + }; + + let depth = if let Some(idx) = spec.rfind('@') { + let depth: usize = spec[idx + 1..].parse().expect("invalid profile depth"); + spec = &spec[..idx]; + depth + } else { + 999 + }; + let allowed = if spec == "*" { + None + } else { + Some(FxHashSet::from_iter(spec.split('|').map(String::from))) + }; + (WriteFilter { depth, longer_than }, allowed) + } +} + +#[allow(non_camel_case_types)] +struct ms(Duration); + +impl std::fmt::Display for ms { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let n = self.0.as_millis(); + write!(f, "{n:5}ms") + } +} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 58a99cc4471a9..19890110d53db 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -31,6 +31,7 @@ use lsp_types::{ }; use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams}; use serde_json::json; +use stdx::format_to_acc; use test_utils::skip_slow_tests; use crate::{ @@ -38,9 +39,6 @@ use crate::{ testdir::TestDir, }; -const PROFILE: &str = ""; -// const PROFILE: &'static str = "*@3>100"; - #[test] fn completes_items_from_standard_library() { if skip_slow_tests() { @@ -594,8 +592,10 @@ fn diagnostics_dont_block_typing() { return; } - let librs: String = (0..10).map(|i| format!("mod m{i};")).collect(); - let libs: String = (0..10).map(|i| format!("//- /src/m{i}.rs\nfn foo() {{}}\n\n")).collect(); + let librs: String = (0..10).fold(String::new(), |mut acc, i| format_to_acc!(acc, "mod m{i};")); + let libs: String = (0..10).fold(String::new(), |mut acc, i| { + format_to_acc!(acc, "//- /src/m{i}.rs\nfn foo() {{}}\n\n") + }); let server = Project::with_fixture(&format!( r#" //- /Cargo.toml diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs index e16990eabd092..d699374f9cde6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs @@ -9,11 +9,11 @@ use std::{ use crossbeam_channel::{after, select, Receiver}; use lsp_server::{Connection, Message, Notification, Request}; use lsp_types::{notification::Exit, request::Shutdown, TextDocumentIdentifier, Url}; -use rust_analyzer::{config::Config, lsp, main_loop}; +use rust_analyzer::{config::Config, lsp, main_loop, tracing}; use serde::Serialize; use serde_json::{json, to_string_pretty, Value}; use test_utils::FixtureWithProjectMeta; -use tracing_subscriber::{prelude::*, Layer}; +use tracing_subscriber::fmt::TestWriter; use vfs::AbsPathBuf; use crate::testdir::TestDir; @@ -91,12 +91,14 @@ impl Project<'_> { static INIT: Once = Once::new(); INIT.call_once(|| { - let filter: tracing_subscriber::filter::Targets = - std::env::var("RA_LOG").ok().and_then(|it| it.parse().ok()).unwrap_or_default(); - let layer = - tracing_subscriber::fmt::Layer::new().with_test_writer().with_filter(filter); - tracing_subscriber::Registry::default().with(layer).init(); - profile::init_from(crate::PROFILE); + let _ = tracing::Config { + writer: TestWriter::default(), + // Deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually + // useful information in there for debugging. + filter: std::env::var("RA_LOG").ok().unwrap_or_else(|| "error".to_string()), + chalk_filter: std::env::var("CHALK_DEBUG").ok(), + profile_filter: std::env::var("RA_PROFILE").ok(), + }; }); let FixtureWithProjectMeta { fixture, mini_core, proc_macro_names, toolchain } = diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs index db192cf8fe53a..d3146ab7671cc 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/tidy.rs @@ -154,6 +154,7 @@ fn check_licenses() { Apache-2.0 Apache-2.0 OR BSL-1.0 Apache-2.0 OR MIT +Apache-2.0 WITH LLVM-exception Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT Apache-2.0/MIT BSD-3-Clause diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs index f6569050b4a00..6796dc41886f5 100644 --- a/src/tools/rust-analyzer/crates/span/src/lib.rs +++ b/src/tools/rust-analyzer/crates/span/src/lib.rs @@ -1,7 +1,4 @@ //! File and span related types. -// FIXME: This should be moved into its own crate to get rid of the dependency inversion, base-db -// has business depending on tt, tt should depend on a span crate only (which unforunately will have -// to depend on salsa) use std::fmt::{self, Write}; use salsa::InternId; diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml index e6014cf812e56..2e3f9113b066a 100644 --- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml @@ -13,7 +13,7 @@ doctest = false [dependencies] backtrace = { version = "0.3.67", optional = true } -always-assert = { version = "0.1.2", features = ["log"] } +always-assert = { version = "0.2.0", features = ["tracing"] } jod-thread = "0.1.2" libc.workspace = true crossbeam-channel = "0.5.5" diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs index cd5285295a2f4..07b7827228182 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs @@ -6,13 +6,13 @@ use std::io as sio; use std::process::Command; use std::{cmp::Ordering, ops, time::Instant}; +pub mod anymap; mod macros; -pub mod process; -pub mod panic_context; pub mod non_empty_vec; +pub mod panic_context; +pub mod process; pub mod rand; pub mod thread; -pub mod anymap; pub use always_assert::{always, never}; pub use itertools; diff --git a/src/tools/rust-analyzer/crates/stdx/src/macros.rs b/src/tools/rust-analyzer/crates/stdx/src/macros.rs index d71e418c89bc6..85d9008fe123e 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/macros.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/macros.rs @@ -1,15 +1,5 @@ //! Convenience macros. -#[macro_export] -macro_rules! eprintln { - ($($tt:tt)*) => {{ - if $crate::is_ci() { - panic!("Forgot to remove debug-print?") - } - std::eprintln!($($tt)*) - }} -} - /// Appends formatted string to a `String`. #[macro_export] macro_rules! format_to { @@ -24,6 +14,22 @@ macro_rules! format_to { }; } +/// Appends formatted string to a `String` and returns the `String`. +/// +/// Useful for folding iterators into a `String`. +#[macro_export] +macro_rules! format_to_acc { + ($buf:expr, $lit:literal $($arg:tt)*) => { + { + use ::std::fmt::Write as _; + // We can't do ::std::fmt::Write::write_fmt($buf, format_args!($lit $($arg)*)) + // unfortunately, as that loses out on autoref behavior. + _ = $buf.write_fmt(format_args!($lit $($arg)*)); + $buf + } + }; +} + /// Generates `From` impls for `Enum E { Foo(Foo), Bar(Bar) }` enums /// /// # Example diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml index 9f78614bba66b..a0fd73ee13f57 100644 --- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml +++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml @@ -22,6 +22,7 @@ once_cell = "1.17.0" indexmap.workspace = true smol_str.workspace = true triomphe.workspace = true +tracing.workspace = true ra-ap-rustc_lexer.workspace = true diff --git a/src/tools/rust-analyzer/crates/syntax/src/algo.rs b/src/tools/rust-analyzer/crates/syntax/src/algo.rs index c4548b1647472..01f2af419ed89 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/algo.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/algo.rs @@ -120,7 +120,7 @@ pub struct TreeDiff { impl TreeDiff { pub fn into_text_edit(&self, builder: &mut TextEditBuilder) { - let _p = profile::span("into_text_edit"); + let _p = tracing::span!(tracing::Level::INFO, "into_text_edit").entered(); for (anchor, to) in &self.insertions { let offset = match anchor { @@ -149,7 +149,7 @@ impl TreeDiff { /// /// This function tries to find a fine-grained diff. pub fn diff(from: &SyntaxNode, to: &SyntaxNode) -> TreeDiff { - let _p = profile::span("diff"); + let _p = tracing::span!(tracing::Level::INFO, "diff").entered(); let mut diff = TreeDiff { replacements: FxHashMap::default(), diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast.rs b/src/tools/rust-analyzer/crates/syntax/src/ast.rs index cc90d2dd1d55b..e9ab7a4320b0c 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast.rs @@ -1,15 +1,15 @@ //! Abstract Syntax Tree, layered on top of untyped `SyntaxNode`s -mod generated; -mod traits; -mod token_ext; -mod node_ext; -mod expr_ext; -mod operators; pub mod edit; pub mod edit_in_place; +mod expr_ext; +mod generated; pub mod make; +mod node_ext; +mod operators; pub mod prec; +mod token_ext; +mod traits; use std::marker::PhantomData; diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs index 247dfe0b459a5..c9944b75b0964 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs @@ -538,9 +538,13 @@ impl ast::UseTree { /// `foo::bar` -> `{foo::bar}` /// /// `{foo::bar}` -> `{foo::bar}` - pub fn wrap_in_tree_list(&self) { - if self.path().is_none() { - return; + pub fn wrap_in_tree_list(&self) -> Option<()> { + if self.use_tree_list().is_some() + && self.path().is_none() + && self.star_token().is_none() + && self.rename().is_none() + { + return None; } let subtree = self.clone_subtree().clone_for_update(); ted::remove_all_iter(self.syntax().children_with_tokens()); @@ -548,6 +552,7 @@ impl ast::UseTree { self.syntax(), make::use_tree_list(once(subtree)).clone_for_update().syntax(), ); + Some(()) } } @@ -960,10 +965,10 @@ impl ast::IdentPat { } pub trait HasVisibilityEdit: ast::HasVisibility { - fn set_visibility(&self, visbility: ast::Visibility) { + fn set_visibility(&self, visibility: ast::Visibility) { match self.visibility() { Some(current_visibility) => { - ted::replace(current_visibility.syntax(), visbility.syntax()) + ted::replace(current_visibility.syntax(), visibility.syntax()) } None => { let vis_before = self @@ -972,7 +977,7 @@ pub trait HasVisibilityEdit: ast::HasVisibility { .find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR)) .unwrap_or_else(|| self.syntax().first_child_or_token().unwrap()); - ted::insert(ted::Position::before(vis_before), visbility.syntax()); + ted::insert(ted::Position::before(vis_before), visibility.syntax()); } } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 62d64319e3858..d5eda8f15e4a0 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -9,10 +9,11 @@ //! API should require to assemble every node piecewise. The trick of //! `parse(format!())` we use internally is an implementation detail -- long //! term, it will be replaced with direct tree manipulation. + use itertools::Itertools; use parser::T; use rowan::NodeOrToken; -use stdx::{format_to, never}; +use stdx::{format_to, format_to_acc, never}; use crate::{ast, utils::is_raw_identifier, AstNode, SourceFile, SyntaxKind, SyntaxToken}; @@ -759,15 +760,12 @@ pub fn match_arm_with_guard( } pub fn match_arm_list(arms: impl IntoIterator) -> ast::MatchArmList { - let arms_str = arms - .into_iter() - .map(|arm| { - let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like()); - let comma = if needs_comma { "," } else { "" }; - let arm = arm.syntax(); - format!(" {arm}{comma}\n") - }) - .collect::(); + let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| { + let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like()); + let comma = if needs_comma { "," } else { "" }; + let arm = arm.syntax(); + format_to_acc!(acc, " {arm}{comma}\n") + }); return from_text(&arms_str); fn from_text(text: &str) -> ast::MatchArmList { diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index ce01ee1c3594b..6e5e4127f4d43 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -384,7 +384,7 @@ impl ast::UseTreeList { // the below remove the innermost {}, got `use crate::{{{A}}}` remove_brace_in_use_tree_list(&self); - // the below remove othe unnecessary {}, got `use crate::A` + // the below remove other unnecessary {}, got `use crate::A` while let Some(parent_use_tree_list) = self.parent_use_tree().parent_use_tree_list() { remove_brace_in_use_tree_list(&parent_use_tree_list); self = parent_use_tree_list; diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs index 21ed1310f56b7..62a0261d7a459 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs @@ -32,22 +32,22 @@ macro_rules! eprintln { ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; } -mod syntax_node; -mod syntax_error; mod parsing; -mod validation; mod ptr; -mod token_text; +mod syntax_error; +mod syntax_node; #[cfg(test)] mod tests; +mod token_text; +mod validation; pub mod algo; pub mod ast; #[doc(hidden)] pub mod fuzz; -pub mod utils; -pub mod ted; pub mod hacks; +pub mod ted; +pub mod utils; use std::marker::PhantomData; diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests.rs b/src/tools/rust-analyzer/crates/syntax/src/tests.rs index 8ae1242cf7fd4..4c0a538f712f5 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests.rs @@ -11,6 +11,7 @@ use std::{ use ast::HasName; use expect_test::expect_file; use rayon::prelude::*; +use stdx::format_to_acc; use test_utils::{bench, bench_fixture, project_root}; use crate::{ast, fuzz, AstNode, SourceFile, SyntaxError}; @@ -104,10 +105,9 @@ fn self_hosting_parsing() { .collect::>(); if !errors.is_empty() { - let errors = errors - .into_iter() - .map(|(path, err)| format!("{}: {:?}\n", path.display(), err[0])) - .collect::(); + let errors = errors.into_iter().fold(String::new(), |mut acc, (path, err)| { + format_to_acc!(acc, "{}: {:?}\n", path.display(), err[0]) + }); panic!("Parsing errors:\n{errors}\n"); } } diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml index 56067d8341789..2ff1fad6c29d9 100644 --- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml @@ -15,10 +15,11 @@ doctest = false # Avoid adding deps here, this crate is widely used in tests it should compile fast! dissimilar = "1.0.7" text-size.workspace = true +tracing.workspace = true rustc-hash.workspace = true stdx.workspace = true profile.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index b015dd69b528a..9c25d88cb8428 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -28,7 +28,7 @@ //! env: option //! eq: sized //! error: fmt -//! fmt: result, transmute, coerce_unsized +//! fmt: option, result, transmute, coerce_unsized //! fn: //! from: sized //! future: pin @@ -987,6 +987,10 @@ pub mod fmt { Arguments { pieces, fmt: None, args } } + pub const fn new_const(pieces: &'a [&'static str]) -> Arguments<'a> { + Arguments { pieces, fmt: None, args: &[] } + } + pub fn new_v1_formatted( pieces: &'a [&'static str], args: &'a [rt::Argument<'a>], @@ -1346,6 +1350,9 @@ pub mod iter { // region:panic mod panic { pub macro panic_2021 { + () => ( + $crate::panicking::panic("explicit panic") + ), ($($t:tt)+) => ( $crate::panicking::panic_fmt($crate::const_format_args!($($t)+)) ), @@ -1357,6 +1364,11 @@ mod panicking { pub const fn panic_fmt(_fmt: crate::fmt::Arguments<'_>) -> ! { loop {} } + + #[lang = "panic"] + pub const fn panic(expr: &'static str) -> ! { + panic_fmt(crate::fmt::Arguments::new_const(&[expr])) + } } // endregion:panic diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 3251dd752682e..bc558c202472e 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -239,13 +239,13 @@ The primary goal of `onEnter` is to handle automatic indentation when opening a This is not yet implemented. The secondary goal is to handle fixing up syntax, like continuing doc strings and comments, and escaping `\n` in string literals. -As proper cursor positioning is raison-d'etat for `onEnter`, it uses `SnippetTextEdit`. +As proper cursor positioning is raison d'être for `onEnter`, it uses `SnippetTextEdit`. ### Unresolved Question * How to deal with synchronicity of the request? One option is to require the client to block until the server returns the response. - Another option is to do a OT-style merging of edits from client and server. + Another option is to do a operational transforms style merging of edits from client and server. A third option is to do a record-replay: client applies heuristic on enter immediately, then applies all user's keypresses. When the server is ready with the response, the client rollbacks all the changes and applies the recorded actions on top of the correct response. * How to deal with multiple carets? diff --git a/src/tools/rust-analyzer/docs/dev/style.md b/src/tools/rust-analyzer/docs/dev/style.md index 786127639ce75..4c5299bde3e91 100644 --- a/src/tools/rust-analyzer/docs/dev/style.md +++ b/src/tools/rust-analyzer/docs/dev/style.md @@ -99,14 +99,7 @@ Including a description and GIF suitable for the changelog means less work for t ## Clippy -We don't enforce Clippy. -A number of default lints have high false positive rate. -Selectively patching false-positives with `allow(clippy)` is probably worse than entirely disabling a problematic lint. -There's a `cargo lint` command which runs a subset of low-FPR lints. -Careful tweaking of `lint` is welcome. -Of course, applying Clippy suggestions is welcome as long as they indeed improve the code. - -**Rationale:** see [rust-lang/clippy#5537](https://github.com/rust-lang/rust-clippy/issues/5537). +We use Clippy to improve the code, but if some lints annoy you, allow them in the [Cargo.toml](../../Cargo.toml) [workspace.lints.clippy] section. # Code diff --git a/src/tools/rust-analyzer/docs/dev/syntax.md b/src/tools/rust-analyzer/docs/dev/syntax.md index fd6f220f4fa90..6c4daecc58ff7 100644 --- a/src/tools/rust-analyzer/docs/dev/syntax.md +++ b/src/tools/rust-analyzer/docs/dev/syntax.md @@ -128,7 +128,7 @@ Interior nodes are shared as well (for example in `(1 + 1) * (1 + 1)`). Note that, the result of the interning is an `Arc`. That is, it's not an index into interning table, so you don't have to have the table around to do anything with the tree. Each tree is fully self-contained (although different trees might share parts). -Currently, the interner is created per-file, but it will be easy to use a per-thread or per-some-contex one. +Currently, the interner is created per-file, but it will be easy to use a per-thread or per-some-context one. We use a `TextSize`, a newtyped `u32`, to store the length of the text. diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index f887bb9df31c8..cfa7503d73900 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -777,6 +777,11 @@ Internal config, path to proc-macro server executable. -- Exclude imports from find-all-references. -- +[[rust-analyzer.references.excludeTests]]rust-analyzer.references.excludeTests (default: `false`):: ++ +-- +Exclude tests from find-all-references. +-- [[rust-analyzer.rename.allowExternalItems]]rust-analyzer.rename.allowExternalItems (default: `false`):: + -- diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc index 069a62ddbfe96..9e9ea25779047 100644 --- a/src/tools/rust-analyzer/docs/user/manual.adoc +++ b/src/tools/rust-analyzer/docs/user/manual.adoc @@ -369,7 +369,7 @@ EOF See https://sharksforarms.dev/posts/neovim-rust/ for more tips on getting started. -Check out https://github.com/simrat39/rust-tools.nvim for a batteries included rust-analyzer setup for Neovim. +Check out https://github.com/mrcjkb/rustaceanvim for a batteries included rust-analyzer setup for Neovim. ==== vim-lsp diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 5ed5146ea1b11..841e364ed8457 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -1505,6 +1505,11 @@ "default": false, "type": "boolean" }, + "rust-analyzer.references.excludeTests": { + "markdownDescription": "Exclude tests from find-all-references.", + "default": false, + "type": "boolean" + }, "rust-analyzer.rename.allowExternalItems": { "markdownDescription": "Allow renaming of items not belonging to the loaded workspaces.", "default": false, diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index 599cfb4ff77a1..c386b9e5d8fb5 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -25,16 +25,7 @@ export async function deactivate() { export async function activate( context: vscode.ExtensionContext, ): Promise { - if (vscode.extensions.getExtension("rust-lang.rust")) { - vscode.window - .showWarningMessage( - `You have both the rust-analyzer (rust-lang.rust-analyzer) and Rust (rust-lang.rust) ` + - "plugins enabled. These are known to conflict and cause various functions of " + - "both plugins to not work correctly. You should disable one of them.", - "Got it", - ) - .then(() => {}, console.error); - } + checkConflictingExtensions(); const ctx = new Ctx(context, createCommands(), fetchWorkspace()); // VS Code doesn't show a notification when an extension fails to activate @@ -200,3 +191,26 @@ function createCommands(): Record { revealDependency: { enabled: commands.revealDependency }, }; } + +function checkConflictingExtensions() { + if (vscode.extensions.getExtension("rust-lang.rust")) { + vscode.window + .showWarningMessage( + `You have both the rust-analyzer (rust-lang.rust-analyzer) and Rust (rust-lang.rust) ` + + "plugins enabled. These are known to conflict and cause various functions of " + + "both plugins to not work correctly. You should disable one of them.", + "Got it", + ) + .then(() => {}, console.error); + } + + if (vscode.extensions.getExtension("panicbit.cargo")) { + vscode.window + .showWarningMessage( + `You have both the rust-analyzer (rust-lang.rust-analyzer) and Cargo (panicbit.cargo) plugins enabled` + + 'you can disable it or set {"cargo.automaticCheck": false} in settings.json to avoid invoking cargo twice', + "Got it", + ) + .then(() => {}, console.error); + } +} diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/error.rs b/src/tools/rust-analyzer/lib/lsp-server/src/error.rs index ebdd153b5b317..da55393339028 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/error.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/error.rs @@ -14,7 +14,7 @@ impl ProtocolError { ProtocolError("disconnected channel".into(), true) } - /// Whether this error occured due to a disconnected channel. + /// Whether this error occurred due to a disconnected channel. pub fn channel_is_disconnected(&self) -> bool { self.1 } diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs b/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs index f717f8e0d4ba6..e476f8c2d1345 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/lib.rs @@ -6,11 +6,11 @@ #![warn(rust_2018_idioms, unused_lifetimes)] -mod msg; -mod stdio; mod error; -mod socket; +mod msg; mod req_queue; +mod socket; +mod stdio; use std::{ io, diff --git a/src/tools/rust-analyzer/rustfmt.toml b/src/tools/rust-analyzer/rustfmt.toml index 71007de81b9f6..20bf59547b86a 100644 --- a/src/tools/rust-analyzer/rustfmt.toml +++ b/src/tools/rust-analyzer/rustfmt.toml @@ -1,2 +1,2 @@ -reorder_modules = false +reorder_modules = true use_small_heuristics = "Max" diff --git a/src/tools/rust-analyzer/xtask/src/main.rs b/src/tools/rust-analyzer/xtask/src/main.rs index 49f8ae79baf0e..2d40ceb737dff 100644 --- a/src/tools/rust-analyzer/xtask/src/main.rs +++ b/src/tools/rust-analyzer/xtask/src/main.rs @@ -12,11 +12,11 @@ mod flags; -mod install; -mod release; mod dist; -mod publish; +mod install; mod metrics; +mod publish; +mod release; use anyhow::bail; use std::{ diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 6dc3eac44d43d..f0af401d3da4b 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -47,7 +47,7 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, _db: &Diagnostic) {} + fn emit_diagnostic(&mut self, _db: Diagnostic) {} } fn silent_emitter() -> Box { @@ -64,7 +64,7 @@ struct SilentOnIgnoredFilesEmitter { } impl SilentOnIgnoredFilesEmitter { - fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { + fn handle_non_ignoreable_error(&mut self, db: Diagnostic) { self.has_non_ignorable_parser_errors = true; self.can_reset.store(false, Ordering::Release); self.emitter.emit_diagnostic(db); @@ -86,7 +86,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter { None } - fn emit_diagnostic(&mut self, db: &Diagnostic) { + fn emit_diagnostic(&mut self, db: Diagnostic) { if db.level() == DiagnosticLevel::Fatal { return self.handle_non_ignoreable_error(db); } @@ -365,7 +365,7 @@ mod tests { None } - fn emit_diagnostic(&mut self, _db: &Diagnostic) { + fn emit_diagnostic(&mut self, _db: Diagnostic) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } } @@ -424,7 +424,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); - emitter.emit_diagnostic(&fatal_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -449,7 +449,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } @@ -473,7 +473,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -512,9 +512,9 @@ mod tests { let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); - emitter.emit_diagnostic(&bar_diagnostic); - emitter.emit_diagnostic(&foo_diagnostic); - emitter.emit_diagnostic(&fatal_diagnostic); + emitter.emit_diagnostic(bar_diagnostic); + emitter.emit_diagnostic(foo_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b06c072a2b0fd..acb70328ba210 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -132,6 +132,7 @@ const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[ ("dissimilar", "Apache-2.0"), ("notify", "CC0-1.0"), ("pulldown-cmark-to-cmark", "Apache-2.0"), + ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 ("scip", "Apache-2.0"), ("snap", "BSD-3-Clause"), @@ -458,13 +459,17 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "mach", "memchr", "object", + "proc-macro2", + "quote", "regalloc2", "region", "rustc-hash", "slice-group-by", "smallvec", "stable_deref_trait", + "syn", "target-lexicon", + "unicode-ident", "version_check", "wasmtime-jit-icache-coherence", "winapi", @@ -479,6 +484,8 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", + "zerocopy", + "zerocopy-derive", // tidy-alphabetical-end ]; diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 451276b5ac157..03f8a701627d3 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -13,7 +13,8 @@ use std::path::{Path, PathBuf}; // desirable, because large numbers of files are unwieldy in general. See issue // #73494. const ENTRY_LIMIT: usize = 900; -const ISSUES_ENTRY_LIMIT: usize = 1807; +// FIXME: The following limits should be reduced eventually. +const ISSUES_ENTRY_LIMIT: usize = 1794; const ROOT_ENTRY_LIMIT: usize = 870; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/src/version b/src/version index 79e15fd49370a..54227249d1ff9 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.77.0 +1.78.0 diff --git a/tests/assembly/is_aligned.rs b/tests/assembly/is_aligned.rs index d152d200adfd7..c4a7823ce1ad4 100644 --- a/tests/assembly/is_aligned.rs +++ b/tests/assembly/is_aligned.rs @@ -2,8 +2,8 @@ // only-x86_64 // ignore-sgx // revisions: opt-speed opt-size -// [opt-speed] compile-flags: -Copt-level=1 -// [opt-size] compile-flags: -Copt-level=s +// [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no +// [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no #![crate_type="rlib"] #![feature(core_intrinsics)] diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index dee0fa9f4a410..6105ea430ddd3 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -174,6 +174,9 @@ // revisions: armv7r_none_eabihf // [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf // [armv7r_none_eabihf] needs-llvm-components: arm +// revisions: armv8r_none_eabihf +// [armv8r_none_eabihf] compile-flags: --target armv8r-none-eabihf +// [armv8r_none_eabihf] needs-llvm-components: arm // FIXME: disabled since it fails on CI saying the csky component is missing /* revisions: csky_unknown_linux_gnuabiv2 @@ -489,9 +492,6 @@ // revisions: wasm64_unknown_unknown // [wasm64_unknown_unknown] compile-flags: --target wasm64-unknown-unknown // [wasm64_unknown_unknown] needs-llvm-components: webassembly -// revisions: wasm32_wasi_preview2 -// [wasm32_wasi_preview2] compile-flags: --target wasm32-wasi-preview2 -// [wasm32_wasi_preview2] needs-llvm-components: webassembly // revisions: x86_64_fortanix_unknown_sgx // [x86_64_fortanix_unknown_sgx] compile-flags: --target x86_64-fortanix-unknown-sgx // [x86_64_fortanix_unknown_sgx] needs-llvm-components: x86 diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs index e78226d4083a4..41edab7f8793a 100644 --- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -26,7 +26,9 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn std::ptr::drop_in_place::> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn as Trait>::foo //~ MONO_ITEM fn as Trait>::bar - let _ = &s1 as &Trait; + let r1 = &s1 as &Trait; + r1.foo(); + r1.bar(); let s1 = Struct { _a: 0u64 }; //~ MONO_ITEM fn std::ptr::drop_in_place::> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs index d953582cce9b6..c8a4552b11ac6 100644 --- a/tests/codegen-units/item-collection/trait-method-default-impl.rs +++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs @@ -57,5 +57,8 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn >::bar::<()> 0u32.bar(0i16, ()); + 0i8.foo(); + 0i32.foo(); + 0 } diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs index 34f52ce4e619e..f578b00f27668 100644 --- a/tests/codegen-units/item-collection/unsizing.rs +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -75,5 +75,7 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn ::foo let _wrapper_sized = wrapper_sized as Wrapper; + false.foo(); + 0 } diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs new file mode 100644 index 0000000000000..6718d2b66272c --- /dev/null +++ b/tests/codegen/async-closure-debug.rs @@ -0,0 +1,21 @@ +// Just make sure that async closures don't ICE. +// +// compile-flags: -C debuginfo=2 --edition=2018 +// ignore-msvc + +// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "async_closure_test" +// CHECK-DAG: [[CLOSURE:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[GEN_FN]] +// CHECK-DAG: [[UPVAR:!.*]] = !DIDerivedType(tag: DW_TAG_member, name: "upvar", scope: [[CLOSURE]] + +#![feature(async_closure)] + +fn async_closure_test(upvar: &str) -> impl async Fn() + '_ { + async move || { + let hello = String::from("hello"); + println!("{hello}, {upvar}"); + } +} + +fn main() { + let _async_closure = async_closure_test("world"); +} diff --git a/tests/codegen/cffi/ffi-returns-twice.rs b/tests/codegen/cffi/ffi-returns-twice.rs deleted file mode 100644 index 0fbe03f0bb6f1..0000000000000 --- a/tests/codegen/cffi/ffi-returns-twice.rs +++ /dev/null @@ -1,11 +0,0 @@ -// compile-flags: -C no-prepopulate-passes -#![crate_type = "lib"] -#![feature(ffi_returns_twice)] - -pub fn bar() { unsafe { foo() } } - -extern "C" { - // CHECK: declare{{( dso_local)?}} void @foo(){{.*}}[[ATTRS:#[0-9]+]] - // CHECK: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} } - #[ffi_returns_twice] pub fn foo(); -} diff --git a/tests/codegen/direct-access-external-data.rs b/tests/codegen/direct-access-external-data.rs new file mode 100644 index 0000000000000..ec4bfc33518db --- /dev/null +++ b/tests/codegen/direct-access-external-data.rs @@ -0,0 +1,21 @@ +// only-loongarch64-unknown-linux-gnu + +// revisions: DEFAULT DIRECT INDIRECT +// [DEFAULT] compile-flags: -C relocation-model=static +// [DIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=yes +// [INDIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=no + +#![crate_type = "rlib"] + +// DEFAULT: @VAR = external {{.*}} global i32 +// DIRECT: @VAR = external dso_local {{.*}} global i32 +// INDIRECT: @VAR = external {{.*}} global i32 + +extern "C" { + static VAR: i32; +} + +#[no_mangle] +pub fn get() -> i32 { + unsafe { VAR } +} diff --git a/tests/codegen/infallible-unwrap-in-opt-z.rs b/tests/codegen/infallible-unwrap-in-opt-z.rs index 5c57b41532fbb..e8ab77f8d20de 100644 --- a/tests/codegen/infallible-unwrap-in-opt-z.rs +++ b/tests/codegen/infallible-unwrap-in-opt-z.rs @@ -21,6 +21,6 @@ pub fn read_up_to_8(buf: &[u8]) -> u64 { // CHECK-LABEL: @checking_unwrap_expectation( #[no_mangle] pub fn checking_unwrap_expectation(buf: &[u8]) -> &[u8; 4] { - // CHECK: call void @_ZN4core6result13unwrap_failed17h + // CHECK: call void @{{.*core6result13unwrap_failed}} buf.try_into().unwrap() } diff --git a/tests/codegen/is_val_statically_known.rs b/tests/codegen/is_val_statically_known.rs index 44187d4f667dd..8f084f6c54bdc 100644 --- a/tests/codegen/is_val_statically_known.rs +++ b/tests/codegen/is_val_statically_known.rs @@ -46,3 +46,41 @@ pub fn _bool_false(b: bool) -> i32 { // CHECK: ret i32 2 _bool(b) } + +#[inline] +pub fn _iref(a: &u8) -> i32 { + if unsafe { is_val_statically_known(a) } { 5 } else { 4 } +} + +// CHECK-LABEL: @_iref_borrow( +#[no_mangle] +pub fn _iref_borrow() -> i32 { + // CHECK: ret i32 4 + _iref(&0) +} + +// CHECK-LABEL: @_iref_arg( +#[no_mangle] +pub fn _iref_arg(a: &u8) -> i32 { + // CHECK: ret i32 4 + _iref(a) +} + +#[inline] +pub fn _slice_ref(a: &[u8]) -> i32 { + if unsafe { is_val_statically_known(a) } { 7 } else { 6 } +} + +// CHECK-LABEL: @_slice_ref_borrow( +#[no_mangle] +pub fn _slice_ref_borrow() -> i32 { + // CHECK: ret i32 6 + _slice_ref(&[0;3]) +} + +// CHECK-LABEL: @_slice_ref_arg( +#[no_mangle] +pub fn _slice_ref_arg(a: &[u8]) -> i32 { + // CHECK: ret i32 6 + _slice_ref(a) +} diff --git a/tests/codegen/pow_of_two.rs b/tests/codegen/pow_of_two.rs deleted file mode 100644 index 372360dfd12c7..0000000000000 --- a/tests/codegen/pow_of_two.rs +++ /dev/null @@ -1,55 +0,0 @@ -// compile-flags: --crate-type=lib -Zmerge-functions=disabled -O -C overflow-checks=false - -// CHECK-LABEL: @a( -#[no_mangle] -pub fn a(exp: u32) -> u64 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 - // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} - // CHECK: ret i64 %{{[^ ]+}} - 2u64.pow(exp) -} - -// CHECK-LABEL: @b( -#[no_mangle] -pub fn b(exp: u32) -> i64 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 - // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} - // CHECK: ret i64 %{{[^ ]+}} - 2i64.pow(exp) -} - -// CHECK-LABEL: @c( -#[no_mangle] -pub fn c(exp: u32) -> u32 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 16 - // CHECK: %{{[^ ]+}} = shl nuw nsw i32 %exp, 1 - // CHECK: %{{[^ ]+}} = shl nuw i32 1, %{{[^ ]+}} - // CHECK: %{{[^ ]+}} = select i1 %{{[^ ]+}}, i32 0, i32 %{{[^ ]+}} - // CHECK: ret i32 %{{[^ ]+}} - 4u32.pow(exp) -} - -// CHECK-LABEL: @d( -#[no_mangle] -pub fn d(exp: u32) -> u32 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6 - // CHECK: %{{[^ ]+}} = mul nuw nsw i32 %exp, 5 - // CHECK: %{{[^ ]+}} = shl nuw nsw i32 1, %{{[^ ]+}} - // CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}} - // CHECK: ret i32 %{{[^ ]+}} - 32u32.pow(exp) -} - -// CHECK-LABEL: @e( -#[no_mangle] -pub fn e(exp: u32) -> i32 { - // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6 - // CHECK: %{{[^ ]+}} = mul nuw {{(nsw )?}}i32 %exp, 5 - // CHECK: %{{[^ ]+}} = shl nuw {{(nsw )?}}i32 1, %{{[^ ]+}} - // CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}} - // CHECK: ret i32 %{{[^ ]+}} - 32i32.pow(exp) -} -// note: d and e are expected to yield the same IR diff --git a/tests/coverage/bad_counter_ids.cov-map b/tests/coverage/bad_counter_ids.cov-map index 3b51e3ef9de66..7eff7f5f02f3c 100644 --- a/tests/coverage/bad_counter_ids.cov-map +++ b/tests/coverage/bad_counter_ids.cov-map @@ -1,81 +1,81 @@ Function name: bad_counter_ids::eq_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 23, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 24, 01, 02, 1f, 00, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 35, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 36, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Function name: bad_counter_ids::eq_bad_message -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 28, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 29, 01, 02, 0f, 02, 02, 20, 00, 2b, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 40, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 41, 1) to (start + 2, 15) - Code(Expression(0, Sub)) at (prev + 2, 32) to (start + 0, 43) = (c0 - Zero) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: bad_counter_ids::eq_good -Raw bytes (14): 0x[01, 01, 00, 02, 01, 0f, 01, 02, 1f, 05, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 02, 1f, 05, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 16, 1) to (start + 2, 31) - Code(Counter(1)) at (prev + 3, 1) to (start + 0, 2) Function name: bad_counter_ids::eq_good_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 14, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 15, 01, 02, 0f, 00, 02, 20, 00, 2b, 05, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 20, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 21, 1) to (start + 2, 15) - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Counter(1)) at (prev + 1, 1) to (start + 0, 2) Function name: bad_counter_ids::ne_bad -Raw bytes (14): 0x[01, 01, 00, 02, 01, 2d, 01, 02, 1f, 00, 03, 01, 00, 02] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 2e, 01, 02, 1f, 00, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 45, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 46, 1) to (start + 2, 31) - Code(Zero) at (prev + 3, 1) to (start + 0, 2) Function name: bad_counter_ids::ne_bad_message -Raw bytes (19): 0x[01, 01, 00, 03, 01, 32, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02] +Raw bytes (19): 0x[01, 01, 00, 03, 01, 33, 01, 02, 0f, 05, 02, 20, 00, 2b, 00, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 50, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 51, 1) to (start + 2, 15) - Code(Counter(1)) at (prev + 2, 32) to (start + 0, 43) - Code(Zero) at (prev + 1, 1) to (start + 0, 2) Function name: bad_counter_ids::ne_good -Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 19, 01, 02, 1f, 02, 03, 01, 00, 02] +Raw bytes (16): 0x[01, 01, 01, 01, 00, 02, 01, 1a, 01, 02, 1f, 02, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 2 -- Code(Counter(0)) at (prev + 25, 1) to (start + 2, 31) +- Code(Counter(0)) at (prev + 26, 1) to (start + 2, 31) - Code(Expression(0, Sub)) at (prev + 3, 1) to (start + 0, 2) = (c0 - Zero) Function name: bad_counter_ids::ne_good_message -Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1e, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02] +Raw bytes (21): 0x[01, 01, 01, 01, 00, 03, 01, 1f, 01, 02, 0f, 00, 02, 20, 00, 2b, 02, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Zero Number of file 0 mappings: 3 -- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 15) +- Code(Counter(0)) at (prev + 31, 1) to (start + 2, 15) - Code(Zero) at (prev + 2, 32) to (start + 0, 43) - Code(Expression(0, Sub)) at (prev + 1, 1) to (start + 0, 2) = (c0 - Zero) diff --git a/tests/coverage/bad_counter_ids.coverage b/tests/coverage/bad_counter_ids.coverage index 5474ec2f78552..39e6cae11ddac 100644 --- a/tests/coverage/bad_counter_ids.coverage +++ b/tests/coverage/bad_counter_ids.coverage @@ -1,5 +1,6 @@ LL| |#![feature(coverage_attribute)] - LL| |// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3 + LL| |// edition: 2021 + LL| |// compile-flags: -Copt-level=0 -Zmir-opt-level=3 LL| | LL| |// Regression test for . LL| |// diff --git a/tests/coverage/bad_counter_ids.rs b/tests/coverage/bad_counter_ids.rs index ef5460102b70c..e22b96468abd3 100644 --- a/tests/coverage/bad_counter_ids.rs +++ b/tests/coverage/bad_counter_ids.rs @@ -1,5 +1,6 @@ #![feature(coverage_attribute)] -// compile-flags: --edition=2021 -Copt-level=0 -Zmir-opt-level=3 +// edition: 2021 +// compile-flags: -Copt-level=0 -Zmir-opt-level=3 // Regression test for . // diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index 323d6e3c8aa52..571e5564b659c 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -1,20 +1,20 @@ Function name: closure_macro::load_configuration_files -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 1) to (start + 2, 2) +- Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) Function name: closure_macro::main -Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 22, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] +Raw bytes (43): 0x[01, 01, 02, 01, 05, 05, 02, 07, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 12, 00, 13, 02, 00, 12, 00, 13, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) Number of file 0 mappings: 7 -- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 33) +- Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) @@ -27,10 +27,19 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro::main::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 24, 12, 00, 54] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 10, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 36, 18) to (start + 0, 84) +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) +- expression 2 operands: lhs = Counter(2), rhs = Zero +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 16, 28) to (start + 3, 33) +- Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) +- Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) + = (c0 - c1) +- Code(Zero) at (prev + 0, 23) to (start + 0, 30) +- Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c1 + (c2 + Zero)) diff --git a/tests/coverage/closure_macro.coverage b/tests/coverage/closure_macro.coverage index a6eeb79a71c8f..716d75cb8d754 100644 --- a/tests/coverage/closure_macro.coverage +++ b/tests/coverage/closure_macro.coverage @@ -1,5 +1,4 @@ - LL| |// compile-flags: --edition=2018 - LL| |#![feature(coverage_attribute)] + LL| |// edition: 2018 LL| | LL| |macro_rules! bail { LL| | ($msg:literal $(,)?) => { @@ -14,16 +13,16 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { - LL| | // FIXME(85000): no coverage in closure macros - LL| | let message = format!($error_message, e); - LL| | if message.len() > 0 { - LL| | println!("{}", message); - LL| | Ok(String::from("ok")) + LL| 0| $value.or_else(|e| { + LL| 0| // This closure, which is declared in a macro, should be instrumented. + LL| 0| let message = format!($error_message, e); + LL| 0| if message.len() > 0 { + LL| 0| println!("{}", message); + LL| 0| Ok(String::from("ok")) LL| | } else { - LL| | bail!("error"); + LL| 0| bail!("error"); LL| | } - LL| | }) + LL| 0| }) LL| | }; LL| |} LL| | diff --git a/tests/coverage/closure_macro.rs b/tests/coverage/closure_macro.rs index c3ef916788091..6fe1212de8d0b 100644 --- a/tests/coverage/closure_macro.rs +++ b/tests/coverage/closure_macro.rs @@ -1,5 +1,4 @@ -// compile-flags: --edition=2018 -#![feature(coverage_attribute)] +// edition: 2018 macro_rules! bail { ($msg:literal $(,)?) => { @@ -15,7 +14,7 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { $value.or_else(|e| { - // FIXME(85000): no coverage in closure macros + // This closure, which is declared in a macro, should be instrumented. let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 5f5e064427890..49ec767eab33e 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -35,10 +35,19 @@ Number of file 0 mappings: 7 = (c1 + (c0 - c1)) Function name: closure_macro_async::test::{closure#0}::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 12, 00, 54] +Raw bytes (35): 0x[01, 01, 03, 01, 05, 05, 0b, 09, 00, 05, 01, 12, 1c, 03, 21, 05, 04, 11, 01, 27, 02, 03, 11, 00, 16, 00, 00, 17, 00, 1e, 07, 02, 09, 00, 0a] Number of files: 1 - file 0 => global file 1 -Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 37, 18) to (start + 0, 84) +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(2, Add) +- expression 2 operands: lhs = Counter(2), rhs = Zero +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 18, 28) to (start + 3, 33) +- Code(Counter(1)) at (prev + 4, 17) to (start + 1, 39) +- Code(Expression(0, Sub)) at (prev + 3, 17) to (start + 0, 22) + = (c0 - c1) +- Code(Zero) at (prev + 0, 23) to (start + 0, 30) +- Code(Expression(1, Add)) at (prev + 2, 9) to (start + 0, 10) + = (c1 + (c2 + Zero)) diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index d67c2ed524b38..1032e027cd97d 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -15,16 +15,16 @@ LL| | LL| |macro_rules! on_error { LL| | ($value:expr, $error_message:expr) => { - LL| | $value.or_else(|e| { - LL| | // FIXME(85000): no coverage in closure macros - LL| | let message = format!($error_message, e); - LL| | if message.len() > 0 { - LL| | println!("{}", message); - LL| | Ok(String::from("ok")) + LL| 0| $value.or_else(|e| { + LL| 0| // This closure, which is declared in a macro, should be instrumented. + LL| 0| let message = format!($error_message, e); + LL| 0| if message.len() > 0 { + LL| 0| println!("{}", message); + LL| 0| Ok(String::from("ok")) LL| | } else { - LL| | bail!("error"); + LL| 0| bail!("error"); LL| | } - LL| | }) + LL| 0| }) LL| | }; LL| |} LL| | diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index 116cb72b0f375..db656fca19836 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -16,7 +16,7 @@ macro_rules! bail { macro_rules! on_error { ($value:expr, $error_message:expr) => { $value.or_else(|e| { - // FIXME(85000): no coverage in closure macros + // This closure, which is declared in a macro, should be instrumented. let message = format!($error_message, e); if message.len() > 0 { println!("{}", message); diff --git a/tests/coverage/coverage_attr_closure.cov-map b/tests/coverage/coverage_attr_closure.cov-map new file mode 100644 index 0000000000000..2208b28fd4149 --- /dev/null +++ b/tests/coverage/coverage_attr_closure.cov-map @@ -0,0 +1,34 @@ +Function name: coverage_attr_closure::GLOBAL_CLOSURE_ON::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 06, 0f, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 6, 15) to (start + 2, 2) + +Function name: coverage_attr_closure::contains_closures_off::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1d, 13, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 29, 19) to (start + 2, 6) + +Function name: coverage_attr_closure::contains_closures_on +Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 02, 05, 01, 04, 06, 02, 05, 01, 04, 06, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 3 +- Code(Counter(0)) at (prev + 15, 1) to (start + 2, 5) +- Code(Counter(0)) at (prev + 4, 6) to (start + 2, 5) +- Code(Counter(0)) at (prev + 4, 6) to (start + 1, 2) + +Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused) +Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Zero) at (prev + 17, 19) to (start + 2, 6) + diff --git a/tests/coverage/coverage_attr_closure.coverage b/tests/coverage/coverage_attr_closure.coverage new file mode 100644 index 0000000000000..32c75b40d83c0 --- /dev/null +++ b/tests/coverage/coverage_attr_closure.coverage @@ -0,0 +1,43 @@ + LL| |#![feature(coverage_attribute, stmt_expr_attributes)] + LL| |#![allow(dead_code)] + LL| |// edition: 2021 + LL| | + LL| |static GLOBAL_CLOSURE_ON: fn(&str) = #[coverage(on)] + LL| 0||input: &str| { + LL| 0| println!("{input}"); + LL| 0|}; + LL| |static GLOBAL_CLOSURE_OFF: fn(&str) = #[coverage(off)] + LL| ||input: &str| { + LL| | println!("{input}"); + LL| |}; + LL| | + LL| |#[coverage(on)] + LL| 1|fn contains_closures_on() { + LL| 1| let _local_closure_on = #[coverage(on)] + LL| 1| |input: &str| { + LL| 0| println!("{input}"); + LL| 1| }; + LL| 1| let _local_closure_off = #[coverage(off)] + LL| 1| |input: &str| { + LL| | println!("{input}"); + LL| 1| }; + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn contains_closures_off() { + LL| | let _local_closure_on = #[coverage(on)] + LL| 0| |input: &str| { + LL| 0| println!("{input}"); + LL| 0| }; + LL| | let _local_closure_off = #[coverage(off)] + LL| | |input: &str| { + LL| | println!("{input}"); + LL| | }; + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | contains_closures_on(); + LL| | contains_closures_off(); + LL| |} + diff --git a/tests/coverage/coverage_attr_closure.rs b/tests/coverage/coverage_attr_closure.rs new file mode 100644 index 0000000000000..1904c89c9204d --- /dev/null +++ b/tests/coverage/coverage_attr_closure.rs @@ -0,0 +1,42 @@ +#![feature(coverage_attribute, stmt_expr_attributes)] +#![allow(dead_code)] +// edition: 2021 + +static GLOBAL_CLOSURE_ON: fn(&str) = #[coverage(on)] +|input: &str| { + println!("{input}"); +}; +static GLOBAL_CLOSURE_OFF: fn(&str) = #[coverage(off)] +|input: &str| { + println!("{input}"); +}; + +#[coverage(on)] +fn contains_closures_on() { + let _local_closure_on = #[coverage(on)] + |input: &str| { + println!("{input}"); + }; + let _local_closure_off = #[coverage(off)] + |input: &str| { + println!("{input}"); + }; +} + +#[coverage(off)] +fn contains_closures_off() { + let _local_closure_on = #[coverage(on)] + |input: &str| { + println!("{input}"); + }; + let _local_closure_off = #[coverage(off)] + |input: &str| { + println!("{input}"); + }; +} + +#[coverage(off)] +fn main() { + contains_closures_on(); + contains_closures_off(); +} diff --git a/tests/coverage/fn_sig_into_try.coverage b/tests/coverage/fn_sig_into_try.coverage index 71e15fc11eb8a..aac5c9d9a94ee 100644 --- a/tests/coverage/fn_sig_into_try.coverage +++ b/tests/coverage/fn_sig_into_try.coverage @@ -1,5 +1,5 @@ LL| |#![feature(coverage_attribute)] - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| |// Regression test for inconsistent handling of function signature spans that LL| |// are followed by code using the `?` operator. diff --git a/tests/coverage/fn_sig_into_try.rs b/tests/coverage/fn_sig_into_try.rs index 1f4cc67af8386..5d8e7929ef975 100644 --- a/tests/coverage/fn_sig_into_try.rs +++ b/tests/coverage/fn_sig_into_try.rs @@ -1,5 +1,5 @@ #![feature(coverage_attribute)] -// compile-flags: --edition=2021 +// edition: 2021 // Regression test for inconsistent handling of function signature spans that // are followed by code using the `?` operator. diff --git a/tests/coverage/issue-93054.cov-map b/tests/coverage/issue-93054.cov-map index c2c6e9a651673..024ef519fcffe 100644 --- a/tests/coverage/issue-93054.cov-map +++ b/tests/coverage/issue-93054.cov-map @@ -1,24 +1,24 @@ Function name: issue_93054::foo2 (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 16, 01, 00, 1d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 15, 01, 00, 1d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 22, 1) to (start + 0, 29) +- Code(Zero) at (prev + 21, 1) to (start + 0, 29) Function name: issue_93054::main -Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 01, 00, 0d] +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1d, 01, 00, 0d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 30, 1) to (start + 0, 13) +- Code(Counter(0)) at (prev + 29, 1) to (start + 0, 13) Function name: issue_93054::make (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 1a, 01, 02, 02] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 01, 02, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 26, 1) to (start + 2, 2) +- Code(Zero) at (prev + 25, 1) to (start + 2, 2) diff --git a/tests/coverage/issue-93054.coverage b/tests/coverage/issue-93054.coverage index 15f225326a427..6ae8ffb5cb4f2 100644 --- a/tests/coverage/issue-93054.coverage +++ b/tests/coverage/issue-93054.coverage @@ -1,11 +1,10 @@ LL| |#![allow(dead_code, unreachable_code)] + LL| |// edition: 2021 LL| | LL| |// Regression test for #93054: Functions using uninhabited types often only have a single, LL| |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. LL| |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. LL| | - LL| |// compile-flags: --edition=2021 - LL| | LL| |enum Never {} LL| | LL| |impl Never { diff --git a/tests/coverage/issue-93054.rs b/tests/coverage/issue-93054.rs index da546cfeef854..f16fc1e423962 100644 --- a/tests/coverage/issue-93054.rs +++ b/tests/coverage/issue-93054.rs @@ -1,11 +1,10 @@ #![allow(dead_code, unreachable_code)] +// edition: 2021 // Regression test for #93054: Functions using uninhabited types often only have a single, // unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail. // Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them. -// compile-flags: --edition=2021 - enum Never {} impl Never { diff --git a/tests/coverage/long_and_wide.coverage b/tests/coverage/long_and_wide.coverage index d7d29ca40cddd..cf4dd2811406c 100644 --- a/tests/coverage/long_and_wide.coverage +++ b/tests/coverage/long_and_wide.coverage @@ -1,4 +1,4 @@ - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| |// ignore-tidy-linelength LL| | LL| |// This file deliberately contains line and column numbers larger than 127, diff --git a/tests/coverage/long_and_wide.rs b/tests/coverage/long_and_wide.rs index a7cbcd4802791..87f2207bd7e67 100644 --- a/tests/coverage/long_and_wide.rs +++ b/tests/coverage/long_and_wide.rs @@ -1,4 +1,4 @@ -// compile-flags: --edition=2021 +// edition: 2021 // ignore-tidy-linelength // This file deliberately contains line and column numbers larger than 127, diff --git a/tests/coverage/macro_in_closure.cov-map b/tests/coverage/macro_in_closure.cov-map new file mode 100644 index 0000000000000..2feaab717b5cb --- /dev/null +++ b/tests/coverage/macro_in_closure.cov-map @@ -0,0 +1,16 @@ +Function name: macro_in_closure::NO_BLOCK::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 1c, 00, 2d] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 7, 28) to (start + 0, 45) + +Function name: macro_in_closure::WITH_BLOCK::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 09, 1e, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 9, 30) to (start + 2, 2) + diff --git a/tests/coverage/macro_in_closure.coverage b/tests/coverage/macro_in_closure.coverage new file mode 100644 index 0000000000000..7f6f873439dff --- /dev/null +++ b/tests/coverage/macro_in_closure.coverage @@ -0,0 +1,18 @@ + LL| |#![feature(coverage_attribute)] + LL| |// edition: 2021 + LL| | + LL| |// If a closure body consists entirely of a single bang-macro invocation, the + LL| |// body span ends up inside the macro-expansion, so we need to un-expand it + LL| |// back to the declaration site. + LL| 1|static NO_BLOCK: fn() = || println!("hello"); + LL| | + LL| 1|static WITH_BLOCK: fn() = || { + LL| 1| println!("hello"); + LL| 1|}; + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | NO_BLOCK(); + LL| | WITH_BLOCK(); + LL| |} + diff --git a/tests/coverage/macro_in_closure.rs b/tests/coverage/macro_in_closure.rs new file mode 100644 index 0000000000000..6948c9079c09c --- /dev/null +++ b/tests/coverage/macro_in_closure.rs @@ -0,0 +1,17 @@ +#![feature(coverage_attribute)] +// edition: 2021 + +// If a closure body consists entirely of a single bang-macro invocation, the +// body span ends up inside the macro-expansion, so we need to un-expand it +// back to the declaration site. +static NO_BLOCK: fn() = || println!("hello"); + +static WITH_BLOCK: fn() = || { + println!("hello"); +}; + +#[coverage(off)] +fn main() { + NO_BLOCK(); + WITH_BLOCK(); +} diff --git a/tests/coverage/sort_groups.coverage b/tests/coverage/sort_groups.coverage index c70d7b3b28253..77cbb09c74a73 100644 --- a/tests/coverage/sort_groups.coverage +++ b/tests/coverage/sort_groups.coverage @@ -1,4 +1,4 @@ - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| |// Demonstrate that `sort_subviews.py` can sort instantiation groups into a LL| |// predictable order, while preserving their heterogeneous contents. diff --git a/tests/coverage/sort_groups.rs b/tests/coverage/sort_groups.rs index 5adbbc6a87d1f..17fd862ca2cad 100644 --- a/tests/coverage/sort_groups.rs +++ b/tests/coverage/sort_groups.rs @@ -1,4 +1,4 @@ -// compile-flags: --edition=2021 +// edition: 2021 // Demonstrate that `sort_subviews.py` can sort instantiation groups into a // predictable order, while preserving their heterogeneous contents. diff --git a/tests/coverage/trivial.coverage b/tests/coverage/trivial.coverage index 4f417979ef97d..af4be7b8f3356 100644 --- a/tests/coverage/trivial.coverage +++ b/tests/coverage/trivial.coverage @@ -1,4 +1,4 @@ - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| 1|fn main() {} diff --git a/tests/coverage/trivial.rs b/tests/coverage/trivial.rs index d0a9b44fb3605..782472739a002 100644 --- a/tests/coverage/trivial.rs +++ b/tests/coverage/trivial.rs @@ -1,3 +1,3 @@ -// compile-flags: --edition=2021 +// edition: 2021 fn main() {} diff --git a/tests/coverage/unreachable.coverage b/tests/coverage/unreachable.coverage index 7015bb90aa38d..a58765f688be5 100644 --- a/tests/coverage/unreachable.coverage +++ b/tests/coverage/unreachable.coverage @@ -1,6 +1,6 @@ LL| |#![feature(core_intrinsics)] LL| |#![feature(coverage_attribute)] - LL| |// compile-flags: --edition=2021 + LL| |// edition: 2021 LL| | LL| |// LL| |// If we instrument a function for coverage, but all of its counter-increment diff --git a/tests/coverage/unreachable.rs b/tests/coverage/unreachable.rs index 6385bfa160d7d..6d0c7b3ca8db5 100644 --- a/tests/coverage/unreachable.rs +++ b/tests/coverage/unreachable.rs @@ -1,6 +1,6 @@ #![feature(core_intrinsics)] #![feature(coverage_attribute)] -// compile-flags: --edition=2021 +// edition: 2021 // // If we instrument a function for coverage, but all of its counter-increment diff --git a/tests/incremental/const-generics/issue-62536.rs b/tests/incremental/const-generics/issue-62536.rs index 93c1dbf44e938..022376768f2a5 100644 --- a/tests/incremental/const-generics/issue-62536.rs +++ b/tests/incremental/const-generics/issue-62536.rs @@ -1,4 +1,7 @@ // revisions:cfail1 + +#![allow(unused_variables)] + struct S([T; N]); fn f(x: T) -> S { panic!() } diff --git a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs index 8262a2a211b7e..5c8af47ccbe8f 100644 --- a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs +++ b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs @@ -1,6 +1,6 @@ // revisions: cfail #![feature(generic_const_exprs)] -#![allow(incomplete_features, unused_braces)] +#![allow(incomplete_features, unused_braces, unused_variables)] trait Delegates {} diff --git a/tests/incremental/dirty_clean.rs b/tests/incremental/dirty_clean.rs index 87a8696b1899f..e6379286805e1 100644 --- a/tests/incremental/dirty_clean.rs +++ b/tests/incremental/dirty_clean.rs @@ -26,11 +26,11 @@ mod y { use x; #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig", cfg="cfail2", )] pub fn y() { - //[cfail2]~^ ERROR `hir_owner_nodes(y)` should be dirty but is not + //[cfail2]~^ ERROR `opt_hir_owner_nodes(y)` should be dirty but is not //[cfail2]~| ERROR `generics_of(y)` should be dirty but is not //[cfail2]~| ERROR `predicates_of(y)` should be dirty but is not //[cfail2]~| ERROR `type_of(y)` should be dirty but is not diff --git a/tests/incremental/hash-module-order.rs b/tests/incremental/hash-module-order.rs index f9244d8adbf35..2e71884a531ae 100644 --- a/tests/incremental/hash-module-order.rs +++ b/tests/incremental/hash-module-order.rs @@ -12,14 +12,14 @@ #![feature(rustc_attrs)] #[cfg(rpass1)] -#[rustc_clean(cfg="rpass1",except="hir_owner_nodes")] +#[rustc_clean(cfg="rpass1",except="opt_hir_owner_nodes")] mod foo { struct First; struct Second; } #[cfg(rpass2)] -#[rustc_clean(cfg="rpass2",except="hir_owner_nodes")] +#[rustc_clean(cfg="rpass2",except="opt_hir_owner_nodes")] mod foo { struct Second; struct First; diff --git a/tests/incremental/hashes/call_expressions.rs b/tests/incremental/hashes/call_expressions.rs index a42cf6aa477c5..bad2e10e497d9 100644 --- a/tests/incremental/hashes/call_expressions.rs +++ b/tests/incremental/hashes/call_expressions.rs @@ -28,9 +28,9 @@ pub fn change_callee_function() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_callee_function() { callee2(1, 2) @@ -45,9 +45,9 @@ pub fn change_argument_function() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_argument_function() { callee1(1, 3) @@ -62,9 +62,9 @@ mod change_callee_indirectly_function { #[cfg(not(any(cfail1,cfail4)))] use super::callee2 as callee; - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn change_callee_indirectly_function() { callee(1, 2) @@ -86,9 +86,9 @@ pub fn change_callee_method() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_callee_method() { let s = Struct; @@ -105,9 +105,9 @@ pub fn change_argument_method() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_argument_method() { let s = Struct; @@ -124,9 +124,9 @@ pub fn change_ufcs_callee_method() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_ufcs_callee_method() { let s = Struct; @@ -143,9 +143,9 @@ pub fn change_argument_method_ufcs() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_argument_method_ufcs() { let s = Struct; @@ -162,11 +162,11 @@ pub fn change_to_ufcs() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] -// One might think this would be expanded in the hir_owner_nodes/Mir, but it actually +// One might think this would be expanded in the opt_hir_owner_nodes/Mir, but it actually // results in slightly different hir_owner/Mir. pub fn change_to_ufcs() { let s = Struct; @@ -186,9 +186,9 @@ pub mod change_ufcs_callee_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::Struct2 as Struct; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_ufcs_callee_indirectly() { let s = Struct; diff --git a/tests/incremental/hashes/closure_expressions.rs b/tests/incremental/hashes/closure_expressions.rs index 927bcd96e6f4b..0173d129b2392 100644 --- a/tests/incremental/hashes/closure_expressions.rs +++ b/tests/incremental/hashes/closure_expressions.rs @@ -24,9 +24,9 @@ pub fn change_closure_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_closure_body() { let _ = || 3u32; @@ -42,9 +42,9 @@ pub fn add_parameter() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_parameter() { let x = 0u32; @@ -60,9 +60,9 @@ pub fn change_parameter_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_parameter_pattern() { let _ = |(x,): (u32,)| x; @@ -77,9 +77,9 @@ pub fn add_move() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_move() { let _ = move || 1; @@ -95,9 +95,9 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg = "cfail6")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; @@ -114,9 +114,9 @@ pub fn change_parameter_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_parameter_type() { let closure = |x: u16| (x as u64) + 1; diff --git a/tests/incremental/hashes/consts.rs b/tests/incremental/hashes/consts.rs index 7cba3c159e600..138618a982d28 100644 --- a/tests/incremental/hashes/consts.rs +++ b/tests/incremental/hashes/consts.rs @@ -19,7 +19,7 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -39,13 +39,13 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_1: i16 = { #[cfg(cfail1)] @@ -57,7 +57,7 @@ const CONST_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_2: i16 = { #[cfg(cfail1)] @@ -67,7 +67,7 @@ const CONST_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_3: i16 = { #[cfg(cfail1)] @@ -77,7 +77,7 @@ const CONST_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_4: i16 = { #[cfg(cfail1)] @@ -99,11 +99,11 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/enum_constructors.rs b/tests/incremental/hashes/enum_constructors.rs index 0a88dd4e15537..1e0db8ffc9284 100644 --- a/tests/incremental/hashes/enum_constructors.rs +++ b/tests/incremental/hashes/enum_constructors.rs @@ -37,9 +37,9 @@ pub fn change_field_value_struct_like() -> Enum { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_struct_like() -> Enum { Enum::Struct { @@ -62,9 +62,9 @@ pub fn change_field_order_struct_like() -> Enum { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it // would if it were not all constants @@ -103,9 +103,9 @@ pub fn change_constructor_path_struct_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_struct_like() { let _ = Enum2::Struct { @@ -128,9 +128,9 @@ pub fn change_constructor_variant_struct_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_struct_like() { let _ = Enum2::Struct2 { @@ -148,9 +148,9 @@ pub mod change_constructor_path_indirectly_struct_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Struct { @@ -170,9 +170,9 @@ pub mod change_constructor_variant_indirectly_struct_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2::Struct2 as Variant; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Enum2 { Variant { @@ -191,9 +191,9 @@ pub fn change_field_value_tuple_like() -> Enum { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_tuple_like() -> Enum { Enum::Tuple(0, 1, 3) @@ -210,12 +210,12 @@ pub fn change_constructor_path_tuple_like() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_tuple_like() { @@ -233,12 +233,12 @@ pub fn change_constructor_variant_tuple_like() { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,typeck" + except="opt_hir_owner_nodes,typeck" )] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_tuple_like() { @@ -253,9 +253,9 @@ pub mod change_constructor_path_indirectly_tuple_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2 as TheEnum; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::Tuple(0, 1, 2) @@ -272,9 +272,9 @@ pub mod change_constructor_variant_indirectly_tuple_like { #[cfg(not(any(cfail1,cfail4)))] use super::Enum2::Tuple2 as Variant; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Enum2 { Variant(0, 1, 2) @@ -301,9 +301,9 @@ pub fn change_constructor_path_c_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_c_like() { let _x = Clike2::B; @@ -318,9 +318,9 @@ pub fn change_constructor_variant_c_like() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_variant_c_like() { let _x = Clike::C; @@ -334,9 +334,9 @@ pub mod change_constructor_path_indirectly_c_like { #[cfg(not(any(cfail1,cfail4)))] use super::Clike2 as TheEnum; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> TheEnum { TheEnum::B @@ -353,9 +353,9 @@ pub mod change_constructor_variant_indirectly_c_like { #[cfg(not(any(cfail1,cfail4)))] use super::Clike::B as Variant; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Clike { Variant diff --git a/tests/incremental/hashes/enum_defs.rs b/tests/incremental/hashes/enum_defs.rs index cb7a4e61e4f57..2293d15b97f27 100644 --- a/tests/incremental/hashes/enum_defs.rs +++ b/tests/incremental/hashes/enum_defs.rs @@ -31,7 +31,7 @@ enum EnumVisibility { A } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub enum EnumVisibility { A } @@ -45,9 +45,9 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameCStyleVariant { Variant1, @@ -64,9 +64,9 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameTupleStyleVariant { Variant1, @@ -83,9 +83,9 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameStructStyleVariant { Variant1, @@ -102,9 +102,9 @@ enum EnumChangeValueCStyleVariant0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant0 { Variant1, @@ -118,9 +118,9 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeValueCStyleVariant1 { Variant1, @@ -136,9 +136,9 @@ enum EnumAddCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddCStyleVariant { Variant1, @@ -155,9 +155,9 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveCStyleVariant { Variant1, @@ -172,9 +172,9 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTupleStyleVariant { Variant1, @@ -191,9 +191,9 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveTupleStyleVariant { Variant1, @@ -208,9 +208,9 @@ enum EnumAddStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddStructStyleVariant { Variant1, @@ -227,9 +227,9 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumRemoveStructStyleVariant { Variant1, @@ -244,9 +244,9 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, @@ -263,9 +263,9 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, @@ -284,9 +284,9 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, @@ -301,9 +301,9 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumChangeOrderTupleStyleVariant { Variant1( @@ -320,9 +320,9 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, @@ -337,9 +337,9 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), @@ -354,9 +354,9 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, @@ -411,9 +411,9 @@ enum EnumChangeNameOfTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfTypeParameter { Variant1(T), @@ -429,9 +429,9 @@ enum EnumAddTypeParameter { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTypeParameter { Variant1(S), @@ -447,9 +447,9 @@ enum EnumChangeNameOfLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumChangeNameOfLifetimeParameter<'b> { Variant1(&'b u32), @@ -465,9 +465,9 @@ enum EnumAddLifetimeParameter<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameter<'a, 'b> { Variant1(&'a u32), @@ -484,9 +484,9 @@ enum EnumAddLifetimeParameterBound<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBound<'a, 'b: 'a> { Variant1(&'a u32), @@ -501,9 +501,9 @@ enum EnumAddLifetimeBoundToParameter<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameter<'a, T: 'a> { Variant1(T), @@ -519,9 +519,9 @@ enum EnumAddTraitBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBound { Variant1(T), @@ -537,9 +537,9 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a { Variant1(&'a u32), @@ -556,9 +556,9 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a { Variant1(T), @@ -574,9 +574,9 @@ enum EnumAddTraitBoundWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of,predicates_of,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of,predicates_of,type_of")] #[rustc_clean(cfg="cfail6")] enum EnumAddTraitBoundWhere where T: Sync { Variant1(T), @@ -592,9 +592,9 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageTypeParameters { Variant1 { @@ -615,9 +615,9 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { @@ -642,9 +642,9 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum TupleStyle { Variant1( @@ -662,9 +662,9 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] enum StructStyle { Variant1 { @@ -687,9 +687,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum { Variant1(T) @@ -705,9 +705,9 @@ mod change_trait_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] enum Enum where T: Trait { Variant1(T) diff --git a/tests/incremental/hashes/exported_vs_not.rs b/tests/incremental/hashes/exported_vs_not.rs index 9ac9ae24f81bc..358ba1d93d1a7 100644 --- a/tests/incremental/hashes/exported_vs_not.rs +++ b/tests/incremental/hashes/exported_vs_not.rs @@ -10,7 +10,7 @@ #![crate_type="rlib"] // Case 1: The function body is not exported to metadata. If the body changes, -// the hash of the hir_owner_nodes node should change, but not the hash of +// the hash of the opt_hir_owner_nodes node should change, but not the hash of // either the hir_owner or the Metadata node. #[cfg(any(cfail1,cfail4))] @@ -19,9 +19,9 @@ pub fn body_not_exported_to_metadata() -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn body_not_exported_to_metadata() -> u32 { 2 @@ -40,9 +40,9 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] #[inline] pub fn body_exported_to_metadata_because_of_inline() -> u32 { @@ -62,9 +62,9 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] #[inline] pub fn body_exported_to_metadata_because_of_generic() -> u32 { diff --git a/tests/incremental/hashes/extern_mods.rs b/tests/incremental/hashes/extern_mods.rs index 93a8fcfea3214..efac5c91658c6 100644 --- a/tests/incremental/hashes/extern_mods.rs +++ b/tests/incremental/hashes/extern_mods.rs @@ -24,9 +24,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn change_function_name2(c: i64) -> i32; @@ -129,9 +129,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "rust-call" { pub fn change_calling_convention(c: (i32,)); @@ -159,9 +159,9 @@ extern "C" { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail6")] extern "C" { pub fn add_function1(c: i32); diff --git a/tests/incremental/hashes/for_loops.rs b/tests/incremental/hashes/for_loops.rs index 84a04ff913b84..e297fcdd329db 100644 --- a/tests/incremental/hashes/for_loops.rs +++ b/tests/incremental/hashes/for_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn change_iteration_variable_name() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_iteration_variable_name() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn change_iteration_variable_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_iteration_variable_pattern() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn change_iterable() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, promoted_mir, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_iterable() { let mut _x = 0; @@ -128,9 +128,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -153,9 +153,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -178,9 +178,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -205,9 +205,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -232,9 +232,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -259,9 +259,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -286,9 +286,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hashes/function_interfaces.rs b/tests/incremental/hashes/function_interfaces.rs index 2aaaf94492c2f..5ba4781c5f1ca 100644 --- a/tests/incremental/hashes/function_interfaces.rs +++ b/tests/incremental/hashes/function_interfaces.rs @@ -25,12 +25,12 @@ pub fn add_parameter() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn add_parameter(p: i32) {} @@ -41,9 +41,9 @@ pub fn add_parameter(p: i32) {} pub fn add_return_type() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn add_return_type() -> () {} @@ -55,12 +55,12 @@ pub fn type_of_parameter(p: i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter(p: i64) {} @@ -73,12 +73,12 @@ pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn type_of_parameter_ref(p: &mut i32) {} @@ -91,12 +91,12 @@ pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn order_of_parameters(p2: i64, p1: i32) {} @@ -109,12 +109,12 @@ pub fn make_unsafe() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub unsafe fn make_unsafe() {} @@ -125,9 +125,9 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail6")] pub extern "C" fn make_extern() {} @@ -139,12 +139,12 @@ pub fn type_parameter () {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, generics_of, type_of, predicates_of" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, generics_of, type_of, predicates_of" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of" )] #[rustc_clean(cfg = "cfail6")] pub fn type_parameter() {} @@ -155,9 +155,9 @@ pub fn type_parameter() {} pub fn lifetime_parameter () {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, generics_of,fn_sig")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, generics_of,fn_sig")] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_parameter<'a>() {} @@ -167,7 +167,7 @@ pub fn lifetime_parameter<'a>() {} pub fn trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} @@ -177,9 +177,9 @@ pub fn trait_bound() {} pub fn builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn builtin_bound() {} @@ -191,12 +191,12 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir" )] #[rustc_clean(cfg = "cfail6")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -207,7 +207,7 @@ pub fn lifetime_bound<'a, T: 'a>() {} pub fn second_trait_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} @@ -217,9 +217,9 @@ pub fn second_trait_bound() {} pub fn second_builtin_bound() {} #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn second_builtin_bound() {} @@ -231,12 +231,12 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a >() {} #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" + except = "opt_hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} @@ -302,9 +302,9 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, typeck, fn_sig")] #[rustc_clean(cfg = "cfail3")] -#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck, fn_sig, optimized_mir")] +#[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, typeck, fn_sig, optimized_mir")] #[rustc_clean(cfg = "cfail6")] pub fn return_impl_trait() -> impl Clone { 0 @@ -339,12 +339,12 @@ pub mod change_return_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_return_type() -> ReturnType { @@ -362,12 +362,12 @@ pub mod change_parameter_type_indirectly { #[rustc_clean( cfg = "cfail2", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail3")] #[rustc_clean( cfg = "cfail5", - except = "hir_owner_nodes, optimized_mir, typeck, fn_sig" + except = "opt_hir_owner_nodes, optimized_mir, typeck, fn_sig" )] #[rustc_clean(cfg = "cfail6")] pub fn indirect_parameter_type(p: ParameterType) {} @@ -384,9 +384,9 @@ pub mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound(p: T) {} } @@ -399,9 +399,9 @@ pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail3")] - #[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, predicates_of")] + #[rustc_clean(cfg = "cfail5", except = "opt_hir_owner_nodes, predicates_of")] #[rustc_clean(cfg = "cfail6")] pub fn indirect_trait_bound_where(p: T) where diff --git a/tests/incremental/hashes/if_expressions.rs b/tests/incremental/hashes/if_expressions.rs index cd80f8aa00a59..430a6015bd5a9 100644 --- a/tests/incremental/hashes/if_expressions.rs +++ b/tests/incremental/hashes/if_expressions.rs @@ -27,9 +27,9 @@ pub fn change_condition(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_condition(x: bool) -> u32 { if !x { @@ -50,9 +50,9 @@ pub fn change_then_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_then_branch(x: bool) -> u32 { if x { @@ -75,9 +75,9 @@ pub fn change_else_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_else_branch(x: bool) -> u32 { if x { @@ -103,9 +103,9 @@ pub fn add_else_branch(x: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -131,9 +131,9 @@ pub fn change_condition_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_condition_if_let(x: Option) -> u32 { if let Some(_ ) = x { @@ -156,9 +156,9 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -181,9 +181,9 @@ pub fn change_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_else_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -209,9 +209,9 @@ pub fn add_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/tests/incremental/hashes/indexing_expressions.rs b/tests/incremental/hashes/indexing_expressions.rs index 4bccec61a7ce3..f07550305f12c 100644 --- a/tests/incremental/hashes/indexing_expressions.rs +++ b/tests/incremental/hashes/indexing_expressions.rs @@ -23,9 +23,9 @@ fn change_simple_index(slice: &[u32]) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_simple_index(slice: &[u32]) -> u32 { slice[4] @@ -40,9 +40,9 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[2..5] @@ -57,9 +57,9 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] @@ -74,9 +74,9 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..4] @@ -91,9 +91,9 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] @@ -108,9 +108,9 @@ fn change_mutability(slice: &mut [u32]) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn change_mutability(slice: &mut [u32]) -> u32 { (& slice[3..5])[0] @@ -125,9 +125,9 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..=7] diff --git a/tests/incremental/hashes/inherent_impls.rs b/tests/incremental/hashes/inherent_impls.rs index 853fbc79fc878..a2b3dcdc1587a 100644 --- a/tests/incremental/hashes/inherent_impls.rs +++ b/tests/incremental/hashes/inherent_impls.rs @@ -26,9 +26,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail3")] @@ -41,9 +41,9 @@ impl Foo { // This should affect the method itself, but not the impl. #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------------ //-------------------------- pub fn method_body() { // ----------------------- @@ -56,9 +56,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn method_body() { println!("Hello, world!"); @@ -73,12 +73,12 @@ impl Foo { impl Foo { //------------ //--------------- - //------------------------------------------------------------ + //---------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //------------------------------------------------------------ + //---------------------------------------------------------------- // //-------------------------- #[inline] @@ -95,12 +95,12 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,optimized_mir,promoted_mir,typeck" + except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,optimized_mir,promoted_mir,typeck" + except="opt_hir_owner_nodes,optimized_mir,promoted_mir,typeck" )] #[rustc_clean(cfg="cfail6")] #[inline] @@ -115,7 +115,7 @@ impl Foo { impl Foo { //-------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- pub fn method_privacy() { } } @@ -128,7 +128,7 @@ impl Foo { impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] fn method_privacy() { } } @@ -138,31 +138,31 @@ impl Foo { impl Foo { //------------ //--------------- - //----------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //----------------------------------------------------------------------------------- + //--------------------------------------------------------------------------------------- // //-------------------------- pub fn method_selfness() { } } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="opt_hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", + except="opt_hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir", )] #[rustc_clean(cfg="cfail6")] pub fn method_selfness(&self) { } @@ -171,9 +171,9 @@ impl Foo { // Change Method Selfmutness --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn method_selfmutness(& self) { } } @@ -184,9 +184,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn method_selfmutness(&mut self) { } } @@ -200,9 +200,9 @@ impl Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,associated_item_def_ids")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,associated_item_def_ids")] #[rustc_clean(cfg="cfail6")] impl Foo { #[rustc_clean(cfg="cfail2")] @@ -221,9 +221,9 @@ impl Foo { // Add Method Parameter -------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn add_method_parameter(&self ) { } } @@ -234,9 +234,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_method_parameter(&self, _: i32) { } } @@ -246,9 +246,9 @@ impl Foo { // Change Method Parameter Name ------------------------------------------------ #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub fn change_method_parameter_name(&self, a: i64) { } } @@ -259,9 +259,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_method_parameter_name(&self, b: i64) { } } @@ -271,9 +271,9 @@ impl Foo { // Change Method Return Type --------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn change_method_return_type(&self) -> u16 { 0 } } @@ -284,9 +284,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_method_return_type(&self) -> u32 { 0 } } @@ -323,9 +323,9 @@ impl Foo { // Change order of parameters ------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub fn change_method_parameter_order(&self, a: i64, b: i64) { } } @@ -336,9 +336,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } } @@ -348,9 +348,9 @@ impl Foo { // Make method unsafe ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- - //-------------------------------------------------------------------------------- + //------------------------------------------------------------------------------------ //-------------------------- pub fn make_method_unsafe(&self) { } } @@ -361,9 +361,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck,optimized_mir")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub unsafe fn make_method_unsafe(&self) { } } @@ -373,9 +373,9 @@ impl Foo { // Make method extern ---------------------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub fn make_method_extern(&self) { } } @@ -386,9 +386,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "C" fn make_method_extern(&self) { } } @@ -398,9 +398,9 @@ impl Foo { // Change method calling convention -------------------------------------------- #[cfg(any(cfail1,cfail4))] impl Foo { - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- pub extern "C" fn change_method_calling_convention(&self) { } } @@ -411,9 +411,9 @@ impl Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl Foo { - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,typeck")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,typeck")] #[rustc_clean(cfg="cfail6")] pub extern "system" fn change_method_calling_convention(&self) { } } @@ -432,9 +432,9 @@ impl Foo { // ---------------------------------------------------------- // ----------------------------------------------------------- // ---------------------------------------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- pub fn add_lifetime_parameter_to_method (&self) { } } @@ -454,9 +454,9 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,fn_sig")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,fn_sig")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,fn_sig,generics_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,fn_sig,generics_of")] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -477,12 +477,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ------------------------------------------------------------ + // ---------------------------------------------------------------- // // ------------------------- // ----------- // -------------- - // ------------------------------------------------------------ + // ---------------------------------------------------------------- // // ------------------------- pub fn add_type_parameter_to_method (&self) { } @@ -505,12 +505,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,generics_of,predicates_of,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,generics_of,predicates_of,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail6")] pub fn add_type_parameter_to_method(&self) { } @@ -523,12 +523,12 @@ impl Foo { impl Foo { //------------ //--------------- - //------------------------------------------------------------------- + //----------------------------------------------------------------------- // //-------------------------- //------------ //--------------- - //------------------------------------------------------------------- + //----------------------------------------------------------------------- // //-------------------------- pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b >(&self) { } @@ -542,12 +542,12 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -569,12 +569,12 @@ impl Foo { // ------------------------------------------------- // ----------- // -------------- - // ------------------------------------------------------------------ + // ---------------------------------------------------------------------- // // ------------------------- // ----------- // -------------- - // ------------------------------------------------------------------ + // ---------------------------------------------------------------------- // // ------------------------- pub fn add_lifetime_bound_to_type_param_of_method<'a, T >(&self) { } @@ -597,12 +597,12 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( cfg="cfail5", - except="hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" + except="opt_hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig" )] #[rustc_clean(cfg="cfail6")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -622,9 +622,9 @@ impl Foo { // ------------------------------------------------------------ // ------------------------------------------------------ // ------------------------------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -644,9 +644,9 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,predicates_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,predicates_of")] #[rustc_clean(cfg="cfail6")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -689,9 +689,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,generics_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,generics_of")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean( @@ -716,9 +716,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")] @@ -737,9 +737,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] @@ -758,9 +758,9 @@ impl Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] impl Bar { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/inline_asm.rs b/tests/incremental/hashes/inline_asm.rs index 3118aa1356452..1570030dbeae3 100644 --- a/tests/incremental/hashes/inline_asm.rs +++ b/tests/incremental/hashes/inline_asm.rs @@ -33,9 +33,9 @@ pub fn change_template(_a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(_a: i32) -> i32 { @@ -66,9 +66,9 @@ pub fn change_output(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { @@ -100,9 +100,9 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { @@ -133,9 +133,9 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { @@ -166,9 +166,9 @@ pub fn change_clobber(_a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { @@ -201,9 +201,9 @@ pub fn change_options(_a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { diff --git a/tests/incremental/hashes/let_expressions.rs b/tests/incremental/hashes/let_expressions.rs index a835b8eef8ce7..62a91bf75f8a3 100644 --- a/tests/incremental/hashes/let_expressions.rs +++ b/tests/incremental/hashes/let_expressions.rs @@ -23,9 +23,9 @@ pub fn change_name() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name() { let _y = 2u64; @@ -40,9 +40,9 @@ pub fn add_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_type() { let _x: u32 = 2u32; @@ -57,9 +57,9 @@ pub fn change_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_type() { let _x: u8 = 2; @@ -74,9 +74,9 @@ pub fn change_mutability_of_reference_type() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; @@ -91,9 +91,9 @@ pub fn change_mutability_of_slot() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_slot() { let _x: u64 = 0; @@ -108,9 +108,9 @@ pub fn change_simple_binding_to_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_simple_binding_to_pattern() { let (_a, _b) = (0u8, 'x'); @@ -125,9 +125,9 @@ pub fn change_name_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name_in_pattern() { let (_a, _c) = (1u8, 'y'); @@ -142,9 +142,9 @@ pub fn add_ref_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_ref_in_pattern() { let (ref _a, _b) = (1u8, 'y'); @@ -159,9 +159,9 @@ pub fn add_amp_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_amp_in_pattern() { let (&_a, _b) = (&1u8, 'y'); @@ -176,9 +176,9 @@ pub fn change_mutability_of_binding_in_pattern() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_binding_in_pattern() { let (mut _a, _b) = (99u8, 'q'); @@ -193,9 +193,9 @@ pub fn add_initializer() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_initializer() { let _x: i16 = 3i16; @@ -210,9 +210,9 @@ pub fn change_initializer() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_initializer() { let _x = 5u16; diff --git a/tests/incremental/hashes/loop_expressions.rs b/tests/incremental/hashes/loop_expressions.rs index 13e37bd59f8e8..810ba877061c6 100644 --- a/tests/incremental/hashes/loop_expressions.rs +++ b/tests/incremental/hashes/loop_expressions.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -130,9 +130,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -157,9 +157,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -184,9 +184,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -211,9 +211,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hashes/match_expressions.rs b/tests/incremental/hashes/match_expressions.rs index ebcf1708a7aaa..c77ac27d49623 100644 --- a/tests/incremental/hashes/match_expressions.rs +++ b/tests/incremental/hashes/match_expressions.rs @@ -28,9 +28,9 @@ pub fn add_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_arm(x: u32) -> u32 { match x { @@ -54,9 +54,9 @@ pub fn change_order_of_arms(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_order_of_arms(x: u32) -> u32 { match x { @@ -79,9 +79,9 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -104,9 +104,9 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -129,9 +129,9 @@ pub fn add_at_binding(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_at_binding(x: u32) -> u32 { match x { @@ -154,9 +154,9 @@ pub fn change_name_of_at_binding(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name_of_at_binding(x: u32) -> u32 { match x { @@ -178,9 +178,9 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -202,9 +202,9 @@ pub fn change_name_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_name_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -227,9 +227,9 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { // Ignore optimized_mir in cfail2, the only change to optimized MIR is a span. #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -250,9 +250,9 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -273,9 +273,9 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { @@ -297,9 +297,9 @@ pub fn change_rhs_of_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_rhs_of_arm(x: u32) -> u32 { match x { @@ -322,9 +322,9 @@ pub fn add_alternative_to_arm(x: u32) -> u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { diff --git a/tests/incremental/hashes/panic_exprs.rs b/tests/incremental/hashes/panic_exprs.rs index 37d10d922c177..440a7b6fbf41f 100644 --- a/tests/incremental/hashes/panic_exprs.rs +++ b/tests/incremental/hashes/panic_exprs.rs @@ -18,7 +18,7 @@ // Indexing expression -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn indexing(slice: &[u8]) -> u8 { #[cfg(cfail1)] @@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 { // Arithmetic overflow plus -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_plus(val: i32) -> i32 { #[cfg(cfail1)] @@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 { // Arithmetic overflow minus -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_minus(val: i32) -> i32 { #[cfg(cfail1)] @@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 { // Arithmetic overflow mult -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_mult(val: i32) -> i32 { #[cfg(cfail1)] @@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 { // Arithmetic overflow negation -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_negation(val: i32) -> i32 { #[cfg(cfail1)] @@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 { // Division by zero -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn division_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 { } // Division by zero -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn mod_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 { // shift left -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_left(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] @@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 { // shift right -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_right(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] diff --git a/tests/incremental/hashes/statics.rs b/tests/incremental/hashes/statics.rs index 2adf05390bc4e..7e2ccc4ce6f20 100644 --- a/tests/incremental/hashes/statics.rs +++ b/tests/incremental/hashes/statics.rs @@ -26,7 +26,7 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub static STATIC_VISIBILITY: u8 = 0; @@ -36,9 +36,9 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static mut STATIC_MUTABILITY: u8 = 0; @@ -87,9 +87,9 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -99,17 +99,17 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_1: i16 = { #[cfg(any(cfail1,cfail4))] @@ -121,9 +121,9 @@ static STATIC_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_2: i16 = { #[cfg(any(cfail1,cfail4))] @@ -133,9 +133,9 @@ static STATIC_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_3: i16 = { #[cfg(any(cfail1,cfail4))] @@ -145,9 +145,9 @@ static STATIC_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_VALUE_4: i16 = { #[cfg(any(cfail1,cfail4))] @@ -169,15 +169,15 @@ mod static_change_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] + #[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/tests/incremental/hashes/struct_constructors.rs b/tests/incremental/hashes/struct_constructors.rs index eabb8683e0296..458f4d1a6d7de 100644 --- a/tests/incremental/hashes/struct_constructors.rs +++ b/tests/incremental/hashes/struct_constructors.rs @@ -34,9 +34,9 @@ pub fn change_field_value_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { @@ -59,9 +59,9 @@ pub fn change_field_order_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { @@ -90,9 +90,9 @@ pub fn add_field_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -127,9 +127,9 @@ pub fn change_field_label_regular_struct() -> RegularStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -164,9 +164,9 @@ pub fn change_constructor_path_regular_struct() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_regular_struct() { let _ = RegularStruct2 { @@ -185,9 +185,9 @@ pub mod change_constructor_path_indirectly_regular_struct { #[cfg(not(any(cfail1,cfail4)))] use super::RegularStruct2 as Struct; - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] pub fn function() -> Struct { Struct { @@ -209,9 +209,9 @@ pub fn change_field_value_tuple_struct() -> TupleStruct { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 3) @@ -228,9 +228,9 @@ pub fn change_constructor_path_tuple_struct() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,typeck")] #[rustc_clean(cfg="cfail6")] pub fn change_constructor_path_tuple_struct() { let _ = TupleStruct2(0, 1, 2); @@ -245,9 +245,9 @@ pub mod change_constructor_path_indirectly_tuple_struct { #[cfg(not(any(cfail1,cfail4)))] use super::TupleStruct2 as Struct; - #[rustc_clean(cfg="cfail5", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail5", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail6")] - #[rustc_clean(cfg="cfail2", except="fn_sig,hir_owner_nodes,optimized_mir,typeck")] + #[rustc_clean(cfg="cfail2", except="fn_sig,opt_hir_owner_nodes,optimized_mir,typeck")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { Struct(0, 1, 2) diff --git a/tests/incremental/hashes/struct_defs.rs b/tests/incremental/hashes/struct_defs.rs index 6ea4d890e4d54..113ada2855d1e 100644 --- a/tests/incremental/hashes/struct_defs.rs +++ b/tests/incremental/hashes/struct_defs.rs @@ -51,9 +51,9 @@ struct LayoutC; struct TupleStructFieldType(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -68,9 +68,9 @@ struct TupleStructFieldType( struct TupleStructAddField(i32); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStructAddField( i32, @@ -86,7 +86,7 @@ struct TupleStructFieldVisibility( char); #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct TupleStructFieldVisibility(pub char); @@ -97,9 +97,9 @@ struct TupleStructFieldVisibility(pub char); struct RecordStructFieldType { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] // Note that changing the type of a field does not change the type of the struct or enum, but // adding/removing fields or changing a fields name or visibility does. @@ -114,9 +114,9 @@ struct RecordStructFieldType { struct RecordStructFieldName { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldName { y: f32 } @@ -127,9 +127,9 @@ struct RecordStructFieldName { y: f32 } struct RecordStructAddField { x: f32 } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStructAddField { x: f32, @@ -144,7 +144,7 @@ struct RecordStructFieldVisibility { x: f32 } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2", except="type_of")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,type_of")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,type_of")] #[rustc_clean(cfg="cfail6")] struct RecordStructFieldVisibility { pub x: f32 } @@ -155,9 +155,9 @@ struct RecordStructFieldVisibility { pub x: f32 } struct AddLifetimeParameter<'a>(&'a f32, &'a f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); @@ -168,9 +168,9 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBound<'a, 'b: 'a>( &'a f32, @@ -181,9 +181,9 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>( struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddLifetimeParameterBoundWhereClause<'a, 'b>( &'a f32, @@ -197,9 +197,9 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>( struct AddTypeParameter(T1, T1); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameter( // The field contains the parent's Generics, so it's dirty even though its @@ -215,9 +215,9 @@ struct AddTypeParameter( struct AddTypeParameterBound(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBound( T @@ -228,9 +228,9 @@ struct AddTypeParameterBound( struct AddTypeParameterBoundWhereClause(T); #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct AddTypeParameterBoundWhereClause( T @@ -257,7 +257,7 @@ struct Visibility; #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub struct Visibility; @@ -271,9 +271,9 @@ mod tuple_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct TupleStruct( FieldType @@ -288,9 +288,9 @@ mod record_struct_change_field_type_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedType2 as FieldType; - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct RecordStruct { _x: FieldType @@ -310,9 +310,9 @@ mod change_trait_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T); } @@ -324,9 +324,9 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] struct Struct(T) where T : Trait; } diff --git a/tests/incremental/hashes/trait_defs.rs b/tests/incremental/hashes/trait_defs.rs index 0a5eba7397722..60faf3c47d69d 100644 --- a/tests/incremental/hashes/trait_defs.rs +++ b/tests/incremental/hashes/trait_defs.rs @@ -30,7 +30,7 @@ trait TraitVisibility { } #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub trait TraitVisibility { } @@ -41,9 +41,9 @@ pub trait TraitVisibility { } trait TraitUnsafety { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe trait TraitUnsafety { } @@ -55,9 +55,9 @@ trait TraitAddMethod { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait TraitAddMethod { fn method(); @@ -72,9 +72,9 @@ trait TraitChangeMethodName { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodName { fn methodChanged(); @@ -85,9 +85,9 @@ trait TraitChangeMethodName { // Add return type to method #[cfg(any(cfail1,cfail4))] trait TraitAddReturnType { - //----------------------------------------------------------- + //--------------------------------------------------------------- //-------------------------- - //----------------------------------------------------------- + //--------------------------------------------------------------- //-------------------------- fn method() ; } @@ -98,9 +98,9 @@ trait TraitAddReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddReturnType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u32; } @@ -110,9 +110,9 @@ trait TraitAddReturnType { // Change return type of method #[cfg(any(cfail1,cfail4))] trait TraitChangeReturnType { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method() -> u32; } @@ -123,9 +123,9 @@ trait TraitChangeReturnType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> u64; } @@ -135,9 +135,9 @@ trait TraitChangeReturnType { // Add parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddParameterToMethod { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method( ); } @@ -148,9 +148,9 @@ trait TraitAddParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddParameterToMethod { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: u32); } @@ -161,15 +161,15 @@ trait TraitAddParameterToMethod { #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterName { //------------------------------------------------------ - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- fn method(a: u32); - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- - //------------------------------------------------------------------ + //---------------------------------------------------------------------- //-------------------------- fn with_default(x: i32) {} } @@ -181,15 +181,15 @@ trait TraitChangeMethodParameterName { #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: u32); - #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn with_default(y: i32) {} } @@ -199,9 +199,9 @@ trait TraitChangeMethodParameterName { // Change type of method parameter (i32 => i64) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterType { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(a: i32); } @@ -212,9 +212,9 @@ trait TraitChangeMethodParameterType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: i64); } @@ -224,9 +224,9 @@ trait TraitChangeMethodParameterType { // Change type of method parameter (&i32 => &mut i32) #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParameterTypeRef { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(a: & i32); } @@ -237,9 +237,9 @@ trait TraitChangeMethodParameterTypeRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParameterTypeRef { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: &mut i32); } @@ -249,9 +249,9 @@ trait TraitChangeMethodParameterTypeRef { // Change order of method parameters #[cfg(any(cfail1,cfail4))] trait TraitChangeMethodParametersOrder { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(a: i32, b: i64); } @@ -262,9 +262,9 @@ trait TraitChangeMethodParametersOrder { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeMethodParametersOrder { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(b: i64, a: i32); } @@ -274,9 +274,9 @@ trait TraitChangeMethodParametersOrder { // Add default implementation to method #[cfg(any(cfail1,cfail4))] trait TraitAddMethodAutoImplementation { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- fn method() ; } @@ -287,9 +287,9 @@ trait TraitAddMethodAutoImplementation { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddMethodAutoImplementation { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() {} } @@ -304,9 +304,9 @@ trait TraitChangeOrderOfMethods { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeOrderOfMethods { fn method1(); @@ -318,9 +318,9 @@ trait TraitChangeOrderOfMethods { // Change mode of self parameter #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfRefToMut { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(& self); } @@ -331,9 +331,9 @@ trait TraitChangeModeSelfRefToMut { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfRefToMut { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&mut self); } @@ -342,9 +342,9 @@ trait TraitChangeModeSelfRefToMut { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToMut: Sized { - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- fn method( self) {} } @@ -355,9 +355,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToMut: Sized { - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(mut self) {} } @@ -366,9 +366,9 @@ trait TraitChangeModeSelfOwnToMut: Sized { #[cfg(any(cfail1,cfail4))] trait TraitChangeModeSelfOwnToRef { - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- fn method( self); } @@ -379,9 +379,9 @@ trait TraitChangeModeSelfOwnToRef { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeModeSelfOwnToRef { - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(&self); } @@ -391,9 +391,9 @@ trait TraitChangeModeSelfOwnToRef { // Add unsafe modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddUnsafeModifier { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(); } @@ -404,9 +404,9 @@ trait TraitAddUnsafeModifier { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddUnsafeModifier { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] unsafe fn method(); } @@ -416,9 +416,9 @@ trait TraitAddUnsafeModifier { // Add extern modifier to method #[cfg(any(cfail1,cfail4))] trait TraitAddExternModifier { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method(); } @@ -429,9 +429,9 @@ trait TraitAddExternModifier { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddExternModifier { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "C" fn method(); } @@ -441,9 +441,9 @@ trait TraitAddExternModifier { // Change extern "C" to extern "stdcall" #[cfg(any(cfail1,cfail4))] trait TraitChangeExternCToRustIntrinsic { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- extern "C" fn method(); } @@ -454,9 +454,9 @@ trait TraitChangeExternCToRustIntrinsic { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeExternCToRustIntrinsic { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] extern "stdcall" fn method(); } @@ -466,10 +466,10 @@ trait TraitChangeExternCToRustIntrinsic { // Add type parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddTypeParameterToMethod { - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // --------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // --------------- // ------------------------- fn method (); @@ -481,10 +481,10 @@ trait TraitAddTypeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToMethod { - #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of,type_of", + #[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); @@ -495,9 +495,9 @@ trait TraitAddTypeParameterToMethod { // Add lifetime parameter to method #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeParameterToMethod { - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------------------- + // -------------------------------------------------------------------------- // ------------------------- fn method (); } @@ -508,9 +508,9 @@ trait TraitAddLifetimeParameterToMethod { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToMethod { - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,generics_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method<'a>(); } @@ -524,9 +524,9 @@ trait ReferencedTrait1 { } // Add trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -537,9 +537,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -549,9 +549,9 @@ trait TraitAddTraitBoundToMethodTypeParameter { // Add builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddBuiltinBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -559,12 +559,12 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(not(any(cfail1,cfail4)))] #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -575,12 +575,12 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToMethodLifetimeParameter { // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- @@ -594,12 +594,12 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -611,9 +611,9 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { // Add second trait bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondTraitBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -624,9 +624,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -636,9 +636,9 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { // Add second builtin bound to method type parameter #[cfg(any(cfail1,cfail4))] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------------- + // --------------------------------------------------------------------- // ------------------------- fn method(); } @@ -649,9 +649,9 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(); } @@ -662,12 +662,12 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { #[cfg(any(cfail1,cfail4))] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- // ----------- - // ------------------------------------------------------------------- + // ----------------------------------------------------------------------- // -------------- // // ------------------------- @@ -681,12 +681,12 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", + except="opt_hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -710,9 +710,9 @@ trait TraitAddAssociatedType { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedType { #[rustc_clean(cfg="cfail3")] @@ -731,9 +731,9 @@ trait TraitAddAssociatedType { // Add trait bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddTraitBoundToAssociatedType { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- type Associated ; @@ -749,9 +749,9 @@ trait TraitAddTraitBoundToAssociatedType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToAssociatedType { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: ReferencedTrait0; @@ -763,9 +763,9 @@ trait TraitAddTraitBoundToAssociatedType { // Add lifetime bound to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddLifetimeBoundToAssociatedType<'a> { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- type Associated ; @@ -778,9 +778,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToAssociatedType<'a> { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated: 'a; @@ -792,9 +792,9 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { // Add default to associated type #[cfg(any(cfail1,cfail4))] trait TraitAddDefaultToAssociatedType { - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- type Associated ; @@ -807,9 +807,9 @@ trait TraitAddDefaultToAssociatedType { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddDefaultToAssociatedType { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] type Associated = ReferenceType0; @@ -825,9 +825,9 @@ trait TraitAddAssociatedConstant { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddAssociatedConstant { const Value: u32; @@ -840,9 +840,9 @@ trait TraitAddAssociatedConstant { // Add initializer to associated constant #[cfg(any(cfail1,cfail4))] trait TraitAddInitializerToAssociatedConstant { - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- const Value: u32 ; @@ -859,9 +859,9 @@ trait TraitAddInitializerToAssociatedConstant { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddInitializerToAssociatedConstant { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: u32 = 1; @@ -877,9 +877,9 @@ trait TraitAddInitializerToAssociatedConstant { // Change type of associated constant #[cfg(any(cfail1,cfail4))] trait TraitChangeTypeOfAssociatedConstant { - // ----------------------------------------------------------- + // --------------------------------------------------------------- // ------------------------- - // ----------------------------------------------------------- + // --------------------------------------------------------------- // ------------------------- const Value: u32; @@ -896,9 +896,9 @@ trait TraitChangeTypeOfAssociatedConstant { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTypeOfAssociatedConstant { - #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,type_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,type_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] const Value: f64; @@ -916,9 +916,9 @@ trait TraitChangeTypeOfAssociatedConstant { trait TraitAddSuperTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSuperTrait : ReferencedTrait0 { } @@ -929,9 +929,9 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } trait TraitAddBuiltiBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltiBound : Send { } @@ -942,9 +942,9 @@ trait TraitAddBuiltiBound : Send { } trait TraitAddStaticLifetimeBound { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticLifetimeBound : 'static { } @@ -955,9 +955,9 @@ trait TraitAddStaticLifetimeBound : 'static { } trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } @@ -965,9 +965,9 @@ trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } trait TraitAddTraitAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } @@ -978,9 +978,9 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } @@ -988,9 +988,9 @@ trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } @@ -1001,9 +1001,9 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } @@ -1011,9 +1011,9 @@ trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } @@ -1024,9 +1024,9 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } trait TraitAddTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTypeParameterToTrait { } @@ -1037,9 +1037,9 @@ trait TraitAddTypeParameterToTrait { } trait TraitAddLifetimeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeParameterToTrait<'a> { } @@ -1050,9 +1050,9 @@ trait TraitAddLifetimeParameterToTrait<'a> { } trait TraitAddTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTrait { } @@ -1063,9 +1063,9 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } @@ -1076,9 +1076,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } @@ -1089,9 +1089,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } trait TraitAddBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } @@ -1102,9 +1102,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait { } trait TraitAddSecondTypeParameterToTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTypeParameterToTrait { } @@ -1115,9 +1115,9 @@ trait TraitAddSecondTypeParameterToTrait { } trait TraitAddSecondLifetimeParameterToTrait<'a> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } @@ -1128,9 +1128,9 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -1141,9 +1141,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } @@ -1154,9 +1154,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { } @@ -1167,9 +1167,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -1185,9 +1185,9 @@ struct ReferenceType1 {} trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } @@ -1198,9 +1198,9 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } @@ -1211,9 +1211,9 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { } @@ -1224,9 +1224,9 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } @@ -1237,9 +1237,9 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 + ReferencedTrait1 { } @@ -1251,9 +1251,9 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } @@ -1264,9 +1264,9 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { } @@ -1277,9 +1277,9 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } @@ -1296,9 +1296,9 @@ mod change_return_type_of_method_indirectly_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeReturnType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method() -> ReturnType; } @@ -1318,9 +1318,9 @@ mod change_method_parameter_type_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeArgType { - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: ArgType); } @@ -1340,9 +1340,9 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameter { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T); } @@ -1363,9 +1363,9 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeBoundOfMethodTypeParameterWhere { - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method(a: T) where T: Bound; } @@ -1380,9 +1380,9 @@ mod change_method_type_parameter_bound_indirectly { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBound { fn method(a: T); @@ -1399,9 +1399,9 @@ mod change_method_type_parameter_bound_indirectly_where { #[cfg(not(any(cfail1,cfail4)))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,predicates_of", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,predicates_of", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] trait TraitChangeTraitBoundWhere where T: Bound { fn method(a: T); diff --git a/tests/incremental/hashes/trait_impls.rs b/tests/incremental/hashes/trait_impls.rs index 028598244de73..2e97a35d36bb7 100644 --- a/tests/incremental/hashes/trait_impls.rs +++ b/tests/incremental/hashes/trait_impls.rs @@ -32,9 +32,9 @@ impl ChangeMethodNameTrait for Foo { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeMethodNameTrait { #[rustc_clean(cfg="cfail3")] @@ -43,9 +43,9 @@ pub trait ChangeMethodNameTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodNameTrait for Foo { #[rustc_clean(cfg="cfail3")] @@ -63,9 +63,9 @@ pub trait ChangeMethodBodyTrait { #[cfg(any(cfail1,cfail4))] impl ChangeMethodBodyTrait for Foo { - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- - // ---------------------------------------------------------- + // -------------------------------------------------------------- // ------------------------- fn method_name() { // @@ -78,9 +78,9 @@ impl ChangeMethodBodyTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodBodyTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name() { () @@ -97,9 +97,9 @@ pub trait ChangeMethodBodyTraitInlined { #[cfg(any(cfail1,cfail4))] impl ChangeMethodBodyTraitInlined for Foo { - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------ + // ---------------------------------------------------------------------------- // ------------------------- #[inline] fn method_name() { @@ -113,9 +113,9 @@ impl ChangeMethodBodyTraitInlined for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodBodyTraitInlined for Foo { - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] #[inline] fn method_name() { @@ -141,18 +141,18 @@ pub trait ChangeMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -179,18 +179,18 @@ pub trait RemoveMethodSelfnessTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveMethodSelfnessTrait for Foo { #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", + except="opt_hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -206,9 +206,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[cfg(any(cfail1,cfail4))] impl ChangeMethodSelfmutnessTrait for Foo { - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- fn method_name(& self) {} } @@ -224,9 +224,9 @@ pub trait ChangeMethodSelfmutnessTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeMethodSelfmutnessTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&mut self) {} } @@ -249,9 +249,9 @@ pub trait ChangeItemKindTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeItemKindTrait for Foo { type name = (); @@ -277,9 +277,9 @@ pub trait RemoveItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl RemoveItemTrait for Foo { type TypeName = (); @@ -304,9 +304,9 @@ pub trait AddItemTrait { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,associated_item_def_ids", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddItemTrait for Foo { type TypeName = (); @@ -317,9 +317,9 @@ impl AddItemTrait for Foo { #[cfg(any(cfail1,cfail4))] pub trait ChangeHasValueTrait { - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- - //---------------------------------------------------- + //-------------------------------------------------------- //-------------------------- fn method_name() ; } @@ -335,9 +335,9 @@ impl ChangeHasValueTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub trait ChangeHasValueTrait { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name() { } } @@ -359,9 +359,9 @@ pub trait AddDefaultTrait { #[cfg(any(cfail1,cfail4))] impl AddDefaultTrait for Foo { - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- - // --------------------------------------------------- + // ------------------------------------------------------- // ------------------------- fn method_name() { } } @@ -372,9 +372,9 @@ impl AddDefaultTrait for Foo { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddDefaultTrait for Foo { - #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] default fn method_name() { } } @@ -388,9 +388,9 @@ pub trait AddArgumentTrait { #[cfg(any(cfail1,cfail4))] impl AddArgumentTrait for Foo { - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- fn method_name(&self ) { } } @@ -406,9 +406,9 @@ pub trait AddArgumentTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddArgumentTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: u32) { } } @@ -422,9 +422,9 @@ pub trait ChangeArgumentTypeTrait { #[cfg(any(cfail1,cfail4))] impl ChangeArgumentTypeTrait for Foo { - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- - // ------------------------------------------------------------------------------- + // ----------------------------------------------------------------------------------- // ------------------------- fn method_name(&self, _x: u32 ) { } } @@ -440,9 +440,9 @@ pub trait ChangeArgumentTypeTrait { #[rustc_clean(cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeArgumentTypeTrait for Foo { - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] - #[rustc_clean(except="hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] + #[rustc_clean(except="opt_hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] fn method_name(&self, _x: char) { } } @@ -462,18 +462,18 @@ impl AddTypeParameterToImpl for Bar { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,generics_of,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTypeParameterToImpl for Bar { #[rustc_clean( - except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="opt_hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail2", )] #[rustc_clean(cfg="cfail3")] #[rustc_clean( - except="hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", + except="opt_hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir", cfg="cfail5", )] #[rustc_clean(cfg="cfail6")] @@ -493,9 +493,9 @@ impl ChangeSelfTypeOfImpl for u32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,impl_trait_ref", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,impl_trait_ref", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl ChangeSelfTypeOfImpl for u64 { #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")] @@ -518,9 +518,9 @@ impl AddLifetimeBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddLifetimeBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] @@ -543,9 +543,9 @@ impl AddTraitBoundToImplParameter for T { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] impl AddTraitBoundToImplParameter for T { #[rustc_clean(cfg="cfail2")] diff --git a/tests/incremental/hashes/type_defs.rs b/tests/incremental/hashes/type_defs.rs index 206c0595d5464..6b0dac1fe69b5 100644 --- a/tests/incremental/hashes/type_defs.rs +++ b/tests/incremental/hashes/type_defs.rs @@ -24,7 +24,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -35,7 +35,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -60,7 +60,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -91,7 +91,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -135,7 +135,7 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -146,7 +146,7 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -181,7 +181,7 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -200,7 +200,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); } @@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] + #[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); } diff --git a/tests/incremental/hashes/unary_and_binary_exprs.rs b/tests/incremental/hashes/unary_and_binary_exprs.rs index 58af51eef077f..3d48f2d28a37b 100644 --- a/tests/incremental/hashes/unary_and_binary_exprs.rs +++ b/tests/incremental/hashes/unary_and_binary_exprs.rs @@ -24,9 +24,9 @@ pub fn const_negation() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn const_negation() -> i32 { -1 @@ -41,9 +41,9 @@ pub fn const_bitwise_not() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn const_bitwise_not() -> i32 { !99 @@ -58,9 +58,9 @@ pub fn var_negation(x: i32, y: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn var_negation(x: i32, y: i32) -> i32 { -y @@ -75,9 +75,9 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn var_bitwise_not(x: i32, y: i32) -> i32 { !y @@ -92,9 +92,9 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn var_deref(x: &i32, y: &i32) -> i32 { *y @@ -109,9 +109,9 @@ pub fn first_const_add() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn first_const_add() -> i32 { 2 + 3 @@ -126,9 +126,9 @@ pub fn second_const_add() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn second_const_add() -> i32 { 1 + 3 @@ -143,9 +143,9 @@ pub fn first_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn first_var_add(a: i32, b: i32) -> i32 { b + 2 @@ -160,9 +160,9 @@ pub fn second_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn second_var_add(a: i32, b: i32) -> i32 { 1 + b @@ -177,9 +177,9 @@ pub fn plus_to_minus(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_minus(a: i32) -> i32 { 1 - a @@ -194,9 +194,9 @@ pub fn plus_to_mult(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_mult(a: i32) -> i32 { 1 * a @@ -211,9 +211,9 @@ pub fn plus_to_div(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_div(a: i32) -> i32 { 1 / a @@ -228,9 +228,9 @@ pub fn plus_to_mod(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn plus_to_mod(a: i32) -> i32 { 1 % a @@ -245,9 +245,9 @@ pub fn and_to_or(a: bool, b: bool) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn and_to_or(a: bool, b: bool) -> bool { a || b @@ -262,9 +262,9 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { 1 | a @@ -279,9 +279,9 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { 1 ^ a @@ -296,9 +296,9 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_lshift(a: i32) -> i32 { a << 1 @@ -313,9 +313,9 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn bitwise_and_to_rshift(a: i32) -> i32 { a >> 1 @@ -330,9 +330,9 @@ pub fn eq_to_uneq(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_uneq(a: i32) -> bool { a != 1 @@ -347,9 +347,9 @@ pub fn eq_to_lt(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_lt(a: i32) -> bool { a < 1 @@ -364,9 +364,9 @@ pub fn eq_to_gt(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_gt(a: i32) -> bool { a > 1 @@ -381,9 +381,9 @@ pub fn eq_to_le(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_le(a: i32) -> bool { a <= 1 @@ -398,9 +398,9 @@ pub fn eq_to_ge(a: i32) -> bool { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn eq_to_ge(a: i32) -> bool { a >= 1 @@ -417,9 +417,9 @@ pub fn type_cast(a: u8) -> u64 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn type_cast(a: u8) -> u64 { let b = a as u32; @@ -436,9 +436,9 @@ pub fn value_cast(a: u32) -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn value_cast(a: u32) -> i32 { 2 as i32 @@ -456,9 +456,9 @@ pub fn place() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn place() -> i32 { let mut x = 10; @@ -478,9 +478,9 @@ pub fn rvalue() -> i32 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn rvalue() -> i32 { let mut x = 10; @@ -497,9 +497,9 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="cfail5")] #[rustc_clean(cfg="cfail6")] pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { s[j] diff --git a/tests/incremental/hashes/while_let_loops.rs b/tests/incremental/hashes/while_let_loops.rs index c81b0d0afb811..64ba3f6e7ef83 100644 --- a/tests/incremental/hashes/while_let_loops.rs +++ b/tests/incremental/hashes/while_let_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn change_loop_condition() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_condition() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -128,9 +128,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -155,9 +155,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -180,9 +180,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -207,9 +207,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -234,9 +234,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hashes/while_loops.rs b/tests/incremental/hashes/while_loops.rs index 077d76fdd43a1..534f61b84bdee 100644 --- a/tests/incremental/hashes/while_loops.rs +++ b/tests/incremental/hashes/while_loops.rs @@ -28,9 +28,9 @@ pub fn change_loop_body() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_body() { let mut _x = 0; @@ -53,9 +53,9 @@ pub fn change_loop_condition() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_loop_condition() { let mut _x = 0; @@ -78,9 +78,9 @@ pub fn add_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_break() { let mut _x = 0; @@ -103,9 +103,9 @@ pub fn add_loop_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label() { let mut _x = 0; @@ -128,9 +128,9 @@ pub fn add_loop_label_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -155,9 +155,9 @@ pub fn change_break_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes,optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_break_label() { let mut _x = 0; @@ -182,9 +182,9 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -209,9 +209,9 @@ pub fn change_continue_label() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_label() { let mut _x = 0; @@ -236,9 +236,9 @@ pub fn change_continue_to_break() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")] +#[rustc_clean(cfg="cfail5", except="opt_hir_owner_nodes, optimized_mir")] #[rustc_clean(cfg="cfail6")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/tests/incremental/hygiene/auxiliary/cached_hygiene.rs b/tests/incremental/hygiene/auxiliary/cached_hygiene.rs index b31f60e972bf0..c1fd47cb2bb46 100644 --- a/tests/incremental/hygiene/auxiliary/cached_hygiene.rs +++ b/tests/incremental/hygiene/auxiliary/cached_hygiene.rs @@ -13,7 +13,7 @@ macro_rules! first_macro { } } -#[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir,promoted_mir", cfg="rpass2")] +#[rustc_clean(except="opt_hir_owner_nodes,typeck,optimized_mir,promoted_mir", cfg="rpass2")] #[inline(always)] pub fn changed_fn() { // This will cause additional hygiene to be generate, diff --git a/tests/incremental/ich_nested_items.rs b/tests/incremental/ich_nested_items.rs index 379c09575edfb..f0310e94015c0 100644 --- a/tests/incremental/ich_nested_items.rs +++ b/tests/incremental/ich_nested_items.rs @@ -8,7 +8,7 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] -#[rustc_clean(except = "hir_owner_nodes", cfg = "cfail2")] +#[rustc_clean(except = "opt_hir_owner_nodes", cfg = "cfail2")] pub fn foo() { #[cfg(cfail1)] pub fn baz() {} // order is different... diff --git a/tests/incremental/ich_resolve_results.rs b/tests/incremental/ich_resolve_results.rs index e6ab6bcebae09..9b5afcd801216 100644 --- a/tests/incremental/ich_resolve_results.rs +++ b/tests/incremental/ich_resolve_results.rs @@ -30,13 +30,13 @@ mod mod3 { use mod2::Foo; #[rustc_clean(cfg="rpass2")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="rpass3")] fn in_expr() { Foo(0); } #[rustc_clean(cfg="rpass2")] - #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")] + #[rustc_clean(except="opt_hir_owner_nodes,typeck", cfg="rpass3")] fn in_type() { test::(); } diff --git a/tests/incremental/source_loc_macros.rs b/tests/incremental/source_loc_macros.rs index e5f04e5dc5818..16ad4d1899e94 100644 --- a/tests/incremental/source_loc_macros.rs +++ b/tests/incremental/source_loc_macros.rs @@ -22,7 +22,7 @@ fn file_same() { let _ = file!(); } -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="rpass2")] fn line_different() { #[cfg(rpass1)] { @@ -34,7 +34,7 @@ fn line_different() { } } -#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")] +#[rustc_clean(except="opt_hir_owner_nodes,optimized_mir", cfg="rpass2")] fn col_different() { #[cfg(rpass1)] { diff --git a/tests/incremental/string_constant.rs b/tests/incremental/string_constant.rs index 47cd100b13691..325b200e69b49 100644 --- a/tests/incremental/string_constant.rs +++ b/tests/incremental/string_constant.rs @@ -17,7 +17,7 @@ pub mod x { } #[cfg(cfail2)] - #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail2")] + #[rustc_clean(except = "opt_hir_owner_nodes,promoted_mir", cfg = "cfail2")] pub fn x() { println!("{}", "2"); } diff --git a/tests/incremental/struct_change_field_name.rs b/tests/incremental/struct_change_field_name.rs index a7c79e9d751e0..bd952bcc1c89a 100644 --- a/tests/incremental/struct_change_field_name.rs +++ b/tests/incremental/struct_change_field_name.rs @@ -6,6 +6,7 @@ // [cfail2] compile-flags: -Z query-dep-graph -Z assert-incr-state=loaded #![feature(rustc_attrs)] +#![allow(unused_variables)] #[cfg(rpass1)] pub struct X { diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir new file mode 100644 index 0000000000000..1fae40c5f4004 --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-abort.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (_1.1: i32); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(_1.1: i32); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir new file mode 100644 index 0000000000000..1fae40c5f4004 --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.panic-unwind.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_move + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (_1.1: i32); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(_1.1: i32); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-abort.mir new file mode 100644 index 0000000000000..9886d6f68a41c --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-abort.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_mut + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (*(_1.1: &i32)); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(*(_1.1: &i32)); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-unwind.mir new file mode 100644 index 0000000000000..9886d6f68a41c --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.panic-unwind.mir @@ -0,0 +1,47 @@ +// MIR for `main::{closure#0}::{closure#0}::{closure#0}` 0 coroutine_by_mut + +fn main::{closure#0}::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug a => (_1.0: i32); + debug b => (*(_1.1: &i32)); + let mut _0: (); + let _3: i32; + scope 1 { + debug a => _3; + let _4: &i32; + scope 2 { + debug a => _4; + let _5: &i32; + scope 3 { + debug b => _5; + } + } + } + + bb0: { + StorageLive(_3); + _3 = (_1.0: i32); + FakeRead(ForLet(None), _3); + StorageLive(_4); + _4 = &_3; + FakeRead(ForLet(None), _4); + StorageLive(_5); + _5 = &(*(_1.1: &i32)); + FakeRead(ForLet(None), _5); + _0 = const (); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + drop(_1) -> [return: bb1, unwind: bb2]; + } + + bb1: { + return; + } + + bb2 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir new file mode 100644 index 0000000000000..7df4eb492605b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-abort.mir @@ -0,0 +1,10 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move + +fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + + bb0: { + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: move _2, b: move (_1.0: i32) }; + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir new file mode 100644 index 0000000000000..7df4eb492605b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.panic-unwind.mir @@ -0,0 +1,10 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move + +fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + + bb0: { + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: move _2, b: move (_1.0: i32) }; + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir new file mode 100644 index 0000000000000..517b8d0dd883b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-abort.mir @@ -0,0 +1,16 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut + +fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + debug a => _2; + debug b => ((*_1).0: i32); + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + let mut _3: &i32; + + bb0: { + StorageLive(_3); + _3 = &((*_1).0: i32); + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: _2, b: move _3 }; + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir new file mode 100644 index 0000000000000..517b8d0dd883b --- /dev/null +++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.panic-unwind.mir @@ -0,0 +1,16 @@ +// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut + +fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} { + debug a => _2; + debug b => ((*_1).0: i32); + let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10}; + let mut _3: &i32; + + bb0: { + StorageLive(_3); + _3 = &((*_1).0: i32); + _0 = {coroutine@$DIR/async_closure_shims.rs:39:53: 42:10 (#0)} { a: _2, b: move _3 }; + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs new file mode 100644 index 0000000000000..2c99a2dad37a7 --- /dev/null +++ b/tests/mir-opt/async_closure_shims.rs @@ -0,0 +1,46 @@ +// edition:2021 +// skip-filecheck +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![feature(async_closure, noop_waker, async_fn_traits)] + +use std::future::Future; +use std::ops::{AsyncFnMut, AsyncFnOnce}; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match fut.as_mut().poll(ctx) { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} + +async fn call_mut(f: &mut impl AsyncFnMut(i32)) { + f(0).await; +} + +async fn call_once(f: impl AsyncFnOnce(i32)) { + f(1).await; +} + +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.mir +// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.mir +pub fn main() { + block_on(async { + let b = 2i32; + let mut async_closure = async move |a: i32| { + let a = &a; + let b = &b; + }; + call_mut(&mut async_closure).await; + call_once(async_closure).await; + }); +} diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir index 3c0d4008c9018..9c8cf8763fdf1 100644 --- a/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir +++ b/tests/mir-opt/building/async_await.b-{closure#0}.coroutine_resume.0.mir @@ -5,6 +5,7 @@ ty: Coroutine( DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), [ + (), std::future::ResumeTy, (), (), @@ -22,6 +23,7 @@ ty: Coroutine( DefId(0:4 ~ async_await[ccf8]::a::{closure#0}), [ + (), std::future::ResumeTy, (), (), diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index 3d420f930076d..8f0cc489a5bb7 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -1,9 +1,21 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR array_index.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main() -> () { fn main() { + // CHECK: let mut [[array_lit:_.*]]: [u32; 4]; + // CHECK: debug x => [[x:_.*]]; + + // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + // CHECK: {{_.*}} = const 4_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true + // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u32 = [0, 1, 2, 3][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs index 2605c7019e6f4..c9be1d65b0302 100644 --- a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs +++ b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs @@ -1,11 +1,18 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR boolean_identities.test.DataflowConstProp.diff + +// CHECK-LABEL: fn test( pub fn test(x: bool, y: bool) -> bool { + // CHECK-NOT: BitAnd( + // CHECK-NOT: BitOr( (y | true) & (x & false) + // CHECK: _0 = const false; + // CHECK-NOT: BitAnd( + // CHECK-NOT: BitOr( } +// CHECK-LABEL: fn main( fn main() { test(true, false); } diff --git a/tests/mir-opt/dataflow-const-prop/cast.rs b/tests/mir-opt/dataflow-const-prop/cast.rs index c87872609dcf7..298ff49803936 100644 --- a/tests/mir-opt/dataflow-const-prop/cast.rs +++ b/tests/mir-opt/dataflow-const-prop/cast.rs @@ -1,8 +1,14 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR cast.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + + // CHECK: [[a]] = const 257_i32; let a = 257; + // CHECK: [[b]] = const 2_u8; let b = a as u8 + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index f7fac8890a057..30b0afa8334dd 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -1,15 +1,32 @@ -// skip-filecheck // unit-test: DataflowConstProp // compile-flags: -Coverflow-checks=on // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR checked.main.DataflowConstProp.diff #[allow(arithmetic_overflow)] + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + // CHECK: debug e => [[e:_.*]]; + + // CHECK: [[a]] = const 1_i32; let a = 1; + + // CHECK: [[b]] = const 2_i32; let b = 2; + + // CHECK: assert(!const false, + // CHECK: [[c]] = const 3_i32; let c = a + b; + // CHECK: [[d]] = const _; let d = i32::MAX; + + // CHECK: assert(!const true, + // CHECK: [[e]] = const i32::MIN; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index ffbd97bb5452f..94cfb4e63fc22 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 7b6dcf1972b2e..ee85287882be9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index ffbd97bb5452f..94cfb4e63fc22 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 7b6dcf1972b2e..ee85287882be9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index df68ce496fd8c..4df38d6e61b7e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index e16ea22091ee2..6aac30bcd17fb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index df68ce496fd8c..4df38d6e61b7e 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index e16ea22091ee2..6aac30bcd17fb 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index 8006bd510e150..fb708e5084bb9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -1,18 +1,29 @@ -// skip-filecheck // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+GVN,+Inline // ignore-debug assertions change the output MIR // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// This test is to check ICE in issue [#115789](https://github.com/rust-lang/rust/issues/115789). + struct A { foo: Box<[bool]>, } // EMIT_MIR default_boxed_slice.main.GVN.diff // EMIT_MIR default_boxed_slice.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { // ConstProp will create a constant of type `Box<[bool]>`. + // FIXME: it is not yet a constant. + // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. + + // CHECK: debug a => [[a:_.*]]; + // We may check other inlined functions as well... + + // CHECK: {{_.*}} = Box::<[bool]>( + // FIXME: should be `{{_.*}} = const Box::<[bool]>` let a: A = A { foo: Box::default() }; } diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff index 07ac5b72e244c..f50a763ef9a05 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff index 07ac5b72e244c..f50a763ef9a05 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff index 775325c4d0626..6bf702b856815 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff @@ -14,7 +14,7 @@ let _6: u8; let _8: u8; scope 2 { - debug x => _6; + debug x2 => _6; let _9: u8; scope 4 { debug y => _9; diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff index 775325c4d0626..6bf702b856815 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff @@ -14,7 +14,7 @@ let _6: u8; let _8: u8; scope 2 { - debug x => _6; + debug x2 => _6; let _9: u8; scope 4 { debug y => _9; diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index e35c0e6e85bed..7ad64d05be434 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH @@ -13,27 +12,67 @@ enum E { } // EMIT_MIR enum.simple.DataflowConstProp.diff + +// CHECK-LABEL: fn simple( fn simple() { + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[e]] = const E::V1(0_i32); let e = E::V1(0); - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { + // CHECK: [[x]] = const 0_i32; + let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } // EMIT_MIR enum.constant.DataflowConstProp.diff + +// CHECK-LABEL: fn constant( fn constant() { + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x => [[x:_.*]]; const C: E = E::V1(0); + + // CHECK: [[e]] = const _; let e = C; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { + // CHECK: [[x]] = const 0_i32; + let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } // EMIT_MIR enum.statics.DataflowConstProp.diff + +// CHECK-LABEL: fn statics( fn statics() { + // CHECK: debug e1 => [[e1:_.*]]; + // CHECK: debug x1 => [[x1:_.*]]; + // CHECK: debug e2 => [[e2:_.*]]; + // CHECK: debug x2 => [[x2:_.*]]; + static C: E = E::V1(0); - let e = C; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: [[e1]] = const E::V1(0_i32); + let e1 = C; + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { + // CHECK: [[x1]] = const 0_i32; + let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 }; static RC: &E = &E::V2(4); - let e = RC; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: [[t:_.*]] = const {alloc2: &&E}; + // CHECK: [[e2]] = (*[[t]]); + let e2 = RC; + + // CHECK: switchInt({{move _.*}}) -> {{.*}} + // FIXME: add checks for x2. Currently, their MIRs are not symmetric in the two + // switch branches. + // One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can + // get by printing MIR directly. It is better to check if there are any bugs in the + // MIR passes around this stage. + let x2 = match e2 { E::V1(x21) => x21, E::V2(x22) => x22 }; } #[rustc_layout_scalar_valid_range_start(1)] @@ -41,6 +80,8 @@ fn statics() { struct NonZeroUsize(usize); // EMIT_MIR enum.mutate_discriminant.DataflowConstProp.diff + +// CHECK-LABEL: fn mutate_discriminant( #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn mutate_discriminant() -> u8 { mir!( @@ -50,7 +91,11 @@ fn mutate_discriminant() -> u8 { // This assignment overwrites the niche in which the discriminant is stored. place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize; // So we cannot know the value of this discriminant. + + // CHECK: [[a:_.*]] = discriminant({{_.*}}); let a = Discriminant(x); + + // CHECK: switchInt([[a]]) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; match a { 0 => bb1, _ => bad, @@ -68,18 +113,33 @@ fn mutate_discriminant() -> u8 { } // EMIT_MIR enum.multiple.DataflowConstProp.diff +// CHECK-LABEL: fn multiple( fn multiple(x: bool, i: u8) { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x2 => [[x2:_.*]]; + // CHECK: debug y => [[y:_.*]]; let e = if x { + // CHECK: [[e]] = Option::::Some(move {{_.*}}); Some(i) } else { + // CHECK: [[e]] = Option::::None; None }; // The dataflow state must have: // discriminant(e) => Top // (e as Some).0 => Top - let x = match e { Some(i) => i, None => 0 }; - // Therefore, `x` should be `Top` here, and no replacement shall happen. - let y = x; + // CHECK: [[x2]] = const 0_u8; + // CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8) + // CHECK: [[x2]] = [[some]]; + let x2 = match e { Some(i) => i, None => 0 }; + + // Therefore, `x2` should be `Top` here, and no replacement shall happen. + + // CHECK-NOT: [[y]] = const + // CHECK: [[y]] = [[x2]]; + // CHECK-NOT: [[y]] = const + let y = x2; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 798b0c041b4ec..b31f98460e45b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 798b0c041b4ec..b31f98460e45b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index 053981abea3ec..44e8d39cca333 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -9,34 +9,34 @@ let mut _8: &&E; let mut _10: isize; scope 1 { - debug e => _1; + debug e1 => _1; let _3: i32; let _5: i32; let _6: i32; scope 2 { - debug x => _3; + debug x1 => _3; let _7: &E; scope 5 { - debug e => _7; + debug e2 => _7; let _9: &i32; let _11: &i32; let _12: &i32; scope 6 { - debug x => _9; + debug x2 => _9; } scope 7 { - debug x => _11; + debug x21 => _11; } scope 8 { - debug x => _12; + debug x22 => _12; } } } scope 3 { - debug x => _5; + debug x11 => _5; } scope 4 { - debug x => _6; + debug x12 => _6; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index d862bd93ff577..ac4ca086d0fed 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -9,34 +9,34 @@ let mut _8: &&E; let mut _10: isize; scope 1 { - debug e => _1; + debug e1 => _1; let _3: i32; let _5: i32; let _6: i32; scope 2 { - debug x => _3; + debug x1 => _3; let _7: &E; scope 5 { - debug e => _7; + debug e2 => _7; let _9: &i32; let _11: &i32; let _12: &i32; scope 6 { - debug x => _9; + debug x2 => _9; } scope 7 { - debug x => _11; + debug x21 => _11; } scope 8 { - debug x => _12; + debug x22 => _12; } } } scope 3 { - debug x => _5; + debug x11 => _5; } scope 4 { - debug x => _6; + debug x12 => _6; } } diff --git a/tests/mir-opt/dataflow-const-prop/if.rs b/tests/mir-opt/dataflow-const-prop/if.rs index 72aabbccf56c8..3400068baba2a 100644 --- a/tests/mir-opt/dataflow-const-prop/if.rs +++ b/tests/mir-opt/dataflow-const-prop/if.rs @@ -1,12 +1,26 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR if.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + // CHECK: debug e => [[e:_.*]]; + let a = 1; + + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; + // CHECK: [[b]] = const 2_i32; let b = if a == 1 { 2 } else { 3 }; + + // CHECK: [[c]] = const 3_i32; let c = b + 1; + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; + // CHECK: [[d]] = const 1_i32; let d = if a == 1 { a } else { a + 1 }; + + // CHECK: [[e]] = const 2_i32; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs index 664cbcb2c259f..b0acc31e0dbcc 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -1,11 +1,14 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+Inline // EMIT_MIR inherit_overflow.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { // After inlining, this will contain a `CheckedBinaryOp`. // Propagating the overflow is ok as codegen will just skip emitting the panic. + + // CHECK: {{_.*}} = const (0_u8, true); + // CHECK: assert(!const true, let _ = ::add(255, 1); } diff --git a/tests/mir-opt/dataflow-const-prop/issue_81605.rs b/tests/mir-opt/dataflow-const-prop/issue_81605.rs index 7c5eceb8a2b68..f13c364279d41 100644 --- a/tests/mir-opt/dataflow-const-prop/issue_81605.rs +++ b/tests/mir-opt/dataflow-const-prop/issue_81605.rs @@ -1,9 +1,18 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR issue_81605.f.DataflowConstProp.diff + +// Plese find the original issue [here](https://github.com/rust-lang/rust/issues/81605). +// This test program comes directly from the issue. Prior to this issue, +// the compiler cannot simplify the return value of `f` into 2. This was +// solved by adding a new MIR constant propagation based on dataflow +// analysis in [#101168](https://github.com/rust-lang/rust/pull/101168). + +// CHECK-LABEL: fn f( fn f() -> usize { + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; 1 + if true { 1 } else { 2 } + // CHECK: _0 = const 2_usize; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index d611a54ba71a2..62be2c3824fa5 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -1,10 +1,18 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR large_array_index.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { // check that we don't propagate this, because it's too large + + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[array_lit:_.*]] = [const 0_u8; 5000]; + // CHECK: {{_.*}} = const 5000_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true + // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u8 = [0_u8; 5000][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs index 16a45c8e9fb59..be8ce7310564c 100644 --- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs +++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs @@ -1,9 +1,10 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff +// CHECK-LABEL: fn test( fn test(x : i32) -> i32 { x * 0 + // CHECK: _0 = const 0_i32; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index c1be691025805..ed8e8fcec16e6 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -29,18 +28,46 @@ struct Delta { } // EMIT_MIR offset_of.concrete.DataflowConstProp.diff + +// CHECK-LABEL: fn concrete( fn concrete() { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: debug z0 => [[z0:_.*]]; + // CHECK: debug z1 => [[z1:_.*]]; + + // CHECK: [[x]] = must_use::(const 4_usize) -> {{.*}} let x = offset_of!(Alpha, x); + + // CHECK: [[y]] = must_use::(const 0_usize) -> {{.*}} let y = offset_of!(Alpha, y); + + // CHECK: [[z0]] = must_use::(const 2_usize) -> {{.*}} let z0 = offset_of!(Alpha, z.0); + + // CHECK: [[z1]] = must_use::(const 3_usize) -> {{.*}} let z1 = offset_of!(Alpha, z.1); } // EMIT_MIR offset_of.generic.DataflowConstProp.diff + +// CHECK-LABEL: fn generic( fn generic() { + // CHECK: debug gx => [[gx:_.*]]; + // CHECK: debug gy => [[gy:_.*]]; + // CHECK: debug dx => [[dx:_.*]]; + // CHECK: debug dy => [[dy:_.*]]; + + // CHECK: [[gx]] = must_use::(move {{_.*}}) -> {{.*}} let gx = offset_of!(Gamma, x); + + // CHECK: [[gy]] = must_use::(move {{_.*}}) -> {{.*}} let gy = offset_of!(Gamma, y); + + // CHECK: [[dx]] = must_use::(const 0_usize) -> {{.*}} let dx = offset_of!(Delta, x); + + // CHECK: [[dy]] = must_use::(const 2_usize) -> {{.*}} let dy = offset_of!(Delta, y); } diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs index 2851c0590ad5f..7bf2b18407854 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp @@ -9,11 +8,23 @@ fn escape(x: &T) {} fn some_function() {} // EMIT_MIR ref_without_sb.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + let mut a = 0; + + // CHECK: {{_.*}} = escape::(move {{_.*}}) -> {{.*}} escape(&a); a = 1; + + // CHECK: {{_.*}} = some_function() -> {{.*}} some_function(); // This should currently not be propagated. + + // CHECK-NOT: [[b]] = const + // CHECK: [[b]] = [[a]]; + // CHECK-NOT: [[b]] = const let b = a; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index b824481948116..daa8dbaf07655 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -1,9 +1,21 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR repeat.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug x => [[x:_.*]]; + + // CHECK: [[array_lit:_.*]] = [const 42_u32; 8]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK: {{_.*}} = const 8_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true + + // CHECK-NOT: [[t:_.*]] = [[array_lit]][_ + // CHECK: [[t:_.*]] = [[array_lit]][2 of 3]; + // CHECK: [[x]] = Add(move [[t]], const 0_u32); let x: u32 = [42; 8][2] + 0; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs index 8cbed6fbb624d..39a2b357193ad 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // The struct has scalar ABI, but is not a scalar type. @@ -7,7 +6,15 @@ struct I32(i32); // EMIT_MIR repr_transparent.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + + // CHECK: [[x]] = const I32(0_i32); let x = I32(0); + + // CHECK: [[y]] = const I32(0_i32); let y = I32(x.0 + x.0); } diff --git a/tests/mir-opt/dataflow-const-prop/self_assign.rs b/tests/mir-opt/dataflow-const-prop/self_assign.rs index c5866c4a9fd98..a5b232131286f 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign.rs @@ -1,13 +1,26 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR self_assign.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + let mut a = 0; + + // CHECK: [[a]] = Add(move {{_.*}}, const 1_i32); a = a + 1; + + // CHECK: [[a]] = move {{_.*}}; a = a; + // CHECK: [[b]] = &[[a]]; let mut b = &a; + + // CHECK: [[b]] = move {{_.*}}; b = b; + + // CHECK: [[a]] = move {{_.*}}; a = *b; } diff --git a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs index cfe1458e44be7..7bfbda7a96c61 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs @@ -1,9 +1,15 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR self_assign_add.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; let mut a = 0; + + // CHECK: [[a]] = const 1_i32; a += 1; + + // CHECK: [[a]] = const 2_i32; a += 1; } diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs index 68aff528695d5..9c610aabe821a 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`. // According to Miri, that is UB. However, T-opsem has not finalized that @@ -10,11 +9,17 @@ // unit-test: DataflowConstProp // EMIT_MIR sibling_ptr.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug x1 => [[x1:_.*]]; + let mut x: (u8, u8) = (0, 0); unsafe { let p = std::ptr::addr_of_mut!(x.0); *p.add(1) = 1; } + + // CHECK: [[x1]] = ({{_.*}}.1: u8); let x1 = x.1; // should not be propagated } diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs index 86266ef5d4e60..65c87580330fc 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.rs +++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs @@ -1,13 +1,34 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+InstSimplify // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR slice_len.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug local => [[local:_.*]]; + // CHECK: debug constant => [[constant:_.*]]; + + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, + + // CHECK: [[local]] = (*{{_.*}})[1 of 2]; let local = (&[1u32, 2, 3] as &[u32])[1]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ const SLICE: &[u32] = &[1, 2, 3]; + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, + + // CHECK-NOT: [[constant]] = (*{{_.*}})[_ + // CHECK: [[constant]] = (*{{_.*}})[1 of 2]; let constant = SLICE[1]; } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 0f461f515fdd0..c486281d6f8d7 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -37,16 +37,16 @@ let _8: std::option::Option; let _9: &[f32]; scope 4 { - debug a => _7; - debug b => _8; - debug c => _9; + debug a1 => _7; + debug b1 => _8; + debug c1 => _9; let _11: f32; let _12: std::option::Option; let _13: &[f32]; scope 5 { - debug a => _11; - debug b => _12; - debug c => _13; + debug a2 => _11; + debug b2 => _12; + debug c2 => _13; let _15: SmallStruct; scope 6 { debug ss => _15; @@ -54,16 +54,16 @@ let _20: std::option::Option; let _21: &[f32]; scope 7 { - debug a => _19; - debug b => _20; - debug c => _21; + debug a3 => _19; + debug b3 => _20; + debug c3 => _21; let _23: f32; let _24: std::option::Option; let _25: &[f32]; scope 8 { - debug a => _23; - debug b => _24; - debug c => _25; + debug a4 => _23; + debug b4 => _24; + debug c4 => _25; let _27: BigStruct; scope 9 { debug bs => _27; diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index 3c40ec8bfb450..7ea53d157334d 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -37,16 +37,16 @@ let _8: std::option::Option; let _9: &[f32]; scope 4 { - debug a => _7; - debug b => _8; - debug c => _9; + debug a1 => _7; + debug b1 => _8; + debug c1 => _9; let _11: f32; let _12: std::option::Option; let _13: &[f32]; scope 5 { - debug a => _11; - debug b => _12; - debug c => _13; + debug a2 => _11; + debug b2 => _12; + debug c2 => _13; let _15: SmallStruct; scope 6 { debug ss => _15; @@ -54,16 +54,16 @@ let _20: std::option::Option; let _21: &[f32]; scope 7 { - debug a => _19; - debug b => _20; - debug c => _21; + debug a3 => _19; + debug b3 => _20; + debug c3 => _21; let _23: f32; let _24: std::option::Option; let _25: &[f32]; scope 8 { - debug a => _23; - debug b => _24; - debug c => _25; + debug a4 => _23; + debug b4 => _24; + debug c4 => _25; let _27: BigStruct; scope 9 { debug bs => _27; diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 043981a295484..a7e0f6a987d5a 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH @@ -12,27 +11,69 @@ struct SmallStruct(f32, Option, &'static [f32]); struct BigStruct(f32, Option, &'static [f32]); // EMIT_MIR struct.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug s => [[s:_.*]]; + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug a1 => [[a1:_.*]]; + // CHECK: debug b1 => [[b1:_.*]]; + // CHECK: debug c1 => [[c1:_.*]]; + // CHECK: debug a2 => [[a2:_.*]]; + // CHECK: debug b2 => [[b2:_.*]]; + // CHECK: debug c2 => [[c2:_.*]]; + // CHECK: debug ss => [[ss:_.*]]; + // CHECK: debug a3 => [[a3:_.*]]; + // CHECK: debug b3 => [[b3:_.*]]; + // CHECK: debug c3 => [[c3:_.*]]; + // CHECK: debug a4 => [[a4:_.*]]; + // CHECK: debug b4 => [[b4:_.*]]; + // CHECK: debug c4 => [[c4:_.*]]; + // CHECK: debug bs => [[bs:_.*]]; + + // CHECK: [[s]] = const S(1_i32); let mut s = S(1); + + // CHECK: [[a]] = const 3_i32; let a = s.0 + 2; s.0 = 3; + + // CHECK: [[b]] = const 6_i32; let b = a + s.0; const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]); - let SmallStruct(a, b, c) = SMALL_VAL; + + // CHECK: [[a1]] = const 4f32; + // CHECK: [[b1]] = const Option::::Some(S(1_i32)); + // CHECK: [[c1]] = ({{_.*}}.2: &[f32]); + let SmallStruct(a1, b1, c1) = SMALL_VAL; static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); - let SmallStruct(a, b, c) = *SMALL_STAT; - let ss = SmallStruct(a, b, c); + // CHECK: [[a2]] = const 9f32; + // CHECK: [[b2]] = ((*{{_.*}}).1: std::option::Option); + // CHECK: [[c2]] = ((*{{_.*}}).2: &[f32]); + let SmallStruct(a2, b2, c2) = *SMALL_STAT; + + // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_.*}}, move {{_.*}}); + let ss = SmallStruct(a2, b2, c2); const BIG_VAL: BigStruct = BigStruct(25., None, &[]); - let BigStruct(a, b, c) = BIG_VAL; + + // CHECK: [[a3]] = const 25f32; + // CHECK: [[b3]] = ({{_.*}}.1: std::option::Option); + // CHECK: [[c3]] = ({{_.*}}.2: &[f32]); + let BigStruct(a3, b3, c3) = BIG_VAL; static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); - let BigStruct(a, b, c) = *BIG_STAT; + // CHECK: [[a4]] = const 82f32; + // CHECK: [[b4]] = const Option::::Some(S(35_i32)); + // CHECK: [[c4]] = ((*{{_.*}}).2: &[f32]); + let BigStruct(a4, b4, c4) = *BIG_STAT; // We arbitrarily limit the size of synthetized values to 4 pointers. // `BigStruct` can be read, but we will keep a MIR aggregate for this. - let bs = BigStruct(a, b, c); + // CHECK: [[bs]] = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move {{_.*}}); + let bs = BigStruct(a4, b4, c4); } diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs index 92a42f22c218f..4472861f132db 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.rs +++ b/tests/mir-opt/dataflow-const-prop/terminator.rs @@ -1,12 +1,14 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp fn foo(n: i32) {} // EMIT_MIR terminator.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { let a = 1; // Checks that we propagate into terminators. + // CHECK: {{_.*}} = foo(const 2_i32) -> [return: {{bb.*}}, unwind foo(a + 1); } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index bb706eafe8885..563558da04a5d 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -1,13 +1,27 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR tuple.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + + // CHECK: [[a]] = const (1_i32, 2_i32); let mut a = (1, 2); + + // CHECK: [[b]] = const 6_i32; let b = a.0 + a.1 + 3; + + // CHECK: [[a]] = const (2_i32, 3_i32); a = (2, 3); + + // CHECK: [[c]] = const 11_i32; let c = a.0 + a.1 + b; + // CHECK: [[d]] = (const 6_i32, const (2_i32, 3_i32), const 11_i32); let d = (b, a, c); } diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff index 7a374c5675ab9..8b427cff67780 100644 --- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff @@ -51,13 +51,13 @@ - } - - bb3: { - StorageLive(_8); - _8 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_8); + _8 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_9); StorageDead(_8); + StorageDead(_9); - goto -> bb4; + goto -> bb3; } diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 21f58a14a2b3f..b91a469225cd2 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -58,13 +58,13 @@ - - bb4: { + bb2: { - StorageLive(_9); - _9 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_10); StorageDead(_9); + StorageDead(_10); - goto -> bb6; + goto -> bb4; } diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff index e058c409cb596..cc16af721ca69 100644 --- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff @@ -51,13 +51,13 @@ - } - - bb3: { - StorageLive(_8); - _8 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option) as Some).0: bool); + StorageLive(_8); + _8 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_9); StorageDead(_8); + StorageDead(_9); - goto -> bb4; + goto -> bb3; } diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff index f98d68e6ffce3..eb8926d27ee87 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff @@ -69,16 +69,16 @@ - bb4: { + bb3: { - StorageLive(_11); - _11 = (((_4.0: std::option::Option) as Some).0: u32); - StorageLive(_12); - _12 = (((_4.1: std::option::Option) as Some).0: u32); StorageLive(_13); _13 = (((_4.2: std::option::Option) as Some).0: u32); + StorageLive(_12); + _12 = (((_4.1: std::option::Option) as Some).0: u32); + StorageLive(_11); + _11 = (((_4.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_13); - StorageDead(_12); StorageDead(_11); + StorageDead(_12); + StorageDead(_13); - goto -> bb5; + goto -> bb4; } diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index 0c94794fa3ffe..79cf1c0e34ad5 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -116,12 +116,12 @@ } bb6: { - StorageLive(_12); - _39 = deref_copy (_4.0: &ViewportPercentageLength); - _12 = (((*_39) as Vw).0: f32); StorageLive(_13); - _40 = deref_copy (_4.1: &ViewportPercentageLength); - _13 = (((*_40) as Vw).0: f32); + _39 = deref_copy (_4.1: &ViewportPercentageLength); + _13 = (((*_39) as Vw).0: f32); + StorageLive(_12); + _40 = deref_copy (_4.0: &ViewportPercentageLength); + _12 = (((*_40) as Vw).0: f32); StorageLive(_14); StorageLive(_15); _15 = _12; @@ -132,18 +132,18 @@ StorageDead(_15); _3 = ViewportPercentageLength::Vw(move _14); StorageDead(_14); - StorageDead(_13); StorageDead(_12); + StorageDead(_13); goto -> bb10; } bb7: { - StorageLive(_17); - _41 = deref_copy (_4.0: &ViewportPercentageLength); - _17 = (((*_41) as Vh).0: f32); StorageLive(_18); - _42 = deref_copy (_4.1: &ViewportPercentageLength); - _18 = (((*_42) as Vh).0: f32); + _41 = deref_copy (_4.1: &ViewportPercentageLength); + _18 = (((*_41) as Vh).0: f32); + StorageLive(_17); + _42 = deref_copy (_4.0: &ViewportPercentageLength); + _17 = (((*_42) as Vh).0: f32); StorageLive(_19); StorageLive(_20); _20 = _17; @@ -154,18 +154,18 @@ StorageDead(_20); _3 = ViewportPercentageLength::Vh(move _19); StorageDead(_19); - StorageDead(_18); StorageDead(_17); + StorageDead(_18); goto -> bb10; } bb8: { - StorageLive(_22); - _43 = deref_copy (_4.0: &ViewportPercentageLength); - _22 = (((*_43) as Vmin).0: f32); StorageLive(_23); - _44 = deref_copy (_4.1: &ViewportPercentageLength); - _23 = (((*_44) as Vmin).0: f32); + _43 = deref_copy (_4.1: &ViewportPercentageLength); + _23 = (((*_43) as Vmin).0: f32); + StorageLive(_22); + _44 = deref_copy (_4.0: &ViewportPercentageLength); + _22 = (((*_44) as Vmin).0: f32); StorageLive(_24); StorageLive(_25); _25 = _22; @@ -176,18 +176,18 @@ StorageDead(_25); _3 = ViewportPercentageLength::Vmin(move _24); StorageDead(_24); - StorageDead(_23); StorageDead(_22); + StorageDead(_23); goto -> bb10; } bb9: { - StorageLive(_27); - _45 = deref_copy (_4.0: &ViewportPercentageLength); - _27 = (((*_45) as Vmax).0: f32); StorageLive(_28); - _46 = deref_copy (_4.1: &ViewportPercentageLength); - _28 = (((*_46) as Vmax).0: f32); + _45 = deref_copy (_4.1: &ViewportPercentageLength); + _28 = (((*_45) as Vmax).0: f32); + StorageLive(_27); + _46 = deref_copy (_4.0: &ViewportPercentageLength); + _27 = (((*_46) as Vmax).0: f32); StorageLive(_29); StorageLive(_30); _30 = _27; @@ -198,8 +198,8 @@ StorageDead(_30); _3 = ViewportPercentageLength::Vmax(move _29); StorageDead(_29); - StorageDead(_28); StorageDead(_27); + StorageDead(_28); goto -> bb10; } diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff index 09cdce718572e..af0337d0a7e71 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff @@ -59,13 +59,13 @@ } bb5: { - StorageLive(_9); - _9 = (((_3.0: std::option::Option) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_10); StorageDead(_9); + StorageDead(_10); goto -> bb8; } diff --git a/tests/mir-opt/fn_ptr_shim.rs b/tests/mir-opt/fn_ptr_shim.rs index c82260baefee3..2650cbf9704f3 100644 --- a/tests/mir-opt/fn_ptr_shim.rs +++ b/tests/mir-opt/fn_ptr_shim.rs @@ -5,7 +5,7 @@ // (as only `FnDef` and `FnPtr` callees are allowed in MIR). // EMIT_MIR core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir -fn main() { +pub fn main() { call(noop as fn()); } diff --git a/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff new file mode 100644 index 0000000000000..b12de636f58b1 --- /dev/null +++ b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff @@ -0,0 +1,27 @@ +- // MIR for `fn0` before GVN ++ // MIR for `fn0` after GVN + + fn fn0() -> () { + let mut _0: (); + let mut _1: usize; + let mut _2: [u128; 6]; + let mut _3: ([u128; 6],); + let mut _4: ([u128; 6],); + let mut _5: (); + + bb0: { + _1 = const 1_usize; + _2 = [const 42_u128; 6]; +- _2[_1] = const 1_u128; ++ _2[1 of 2] = const 1_u128; + _3 = (_2,); + _4 = _3; +- _5 = fn1(move (_3.0: [u128; 6]), _4) -> [return: bb1, unwind unreachable]; ++ _5 = fn1((_3.0: [u128; 6]), _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_moves.rs b/tests/mir-opt/gvn_copy_moves.rs new file mode 100644 index 0000000000000..d216825e5e689 --- /dev/null +++ b/tests/mir-opt/gvn_copy_moves.rs @@ -0,0 +1,46 @@ +// unit-test: GVN + +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "initial")] +fn fn0() { + // CHECK-LABEL: fn fn0( + mir! { + let a: usize; + let b: [u128; 6]; + let c: ([u128; 6],); + let d: ([u128; 6],); + let x: (); + { + // CHECK: bb0: { + // CHECK-NEXT: _1 = const 1_usize; + // CHECK-NEXT: _2 = [const 42_u128; 6]; + // CHECK-NEXT: _2[1 of 2] = const 1_u128; + // CHECK-NEXT: _3 = (_2,); + // CHECK-NEXT: _4 = _3; + // CHECK-NEXT: _5 = fn1((_3.0: [u128; 6]), _3) + a = 1_usize; + b = [42; 6]; + b[a] = 1; + c = (b,); + d = c; + Call(x = fn1(Move(c.0), d), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + Return() + } + } +} + +#[inline(never)] +fn fn1(a: [u128; 6], mut b: ([u128; 6],)) { + b.0 = [0; 6]; +} + +fn main() { + fn0(); +} + +// EMIT_MIR gvn_copy_moves.fn0.GVN.diff diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff index 8f2baf4a3b61c..1be0a4f2d2976 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff @@ -4,35 +4,16 @@ fn g() -> () { let mut _0: (); let _1: (); -+ let mut _2: fn() {main}; -+ scope 1 (inlined f::) { -+ debug g => _2; -+ let mut _3: &fn() {main}; -+ let _4: (); -+ } bb0: { StorageLive(_1); -- _1 = f::(main) -> [return: bb1, unwind unreachable]; -+ StorageLive(_2); -+ _2 = main; -+ StorageLive(_4); -+ StorageLive(_3); -+ _3 = &_2; -+ _4 = >::call(move _3, const ()) -> [return: bb2, unwind unreachable]; + _1 = f::(main) -> [return: bb1, unwind unreachable]; } bb1: { -+ StorageDead(_4); -+ StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb2: { -+ StorageDead(_3); -+ drop(_2) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff index 1fd1014ba1d53..da516220d5048 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff @@ -4,43 +4,16 @@ fn g() -> () { let mut _0: (); let _1: (); -+ let mut _2: fn() {main}; -+ scope 1 (inlined f::) { -+ debug g => _2; -+ let mut _3: &fn() {main}; -+ let _4: (); -+ } bb0: { StorageLive(_1); -- _1 = f::(main) -> [return: bb1, unwind continue]; -+ StorageLive(_2); -+ _2 = main; -+ StorageLive(_4); -+ StorageLive(_3); -+ _3 = &_2; -+ _4 = >::call(move _3, const ()) -> [return: bb2, unwind: bb3]; + _1 = f::(main) -> [return: bb1, unwind continue]; } bb1: { -+ StorageDead(_4); -+ StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb2: { -+ StorageDead(_3); -+ drop(_2) -> [return: bb1, unwind continue]; -+ } -+ -+ bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; -+ } -+ -+ bb4 (cleanup): { -+ resume; } } diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs index 350724235ba04..c251226673d5f 100644 --- a/tests/mir-opt/inline/cycle.rs +++ b/tests/mir-opt/inline/cycle.rs @@ -13,9 +13,7 @@ fn f(g: impl Fn()) { #[inline(always)] fn g() { // CHECK-LABEL: fn g( - // CHECK-NOT: inlined - // CHECK: (inlined f::) - // CHECK-NOT: inlined + // CHECK-NOT: (inlined f::) f(main); } diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff index d437dbf5763a2..142b9c5659889 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff @@ -7,6 +7,10 @@ + scope 1 (inlined ::call) { + scope 2 (inlined as Call>::call) { + scope 3 (inlined ::call) { ++ scope 4 (inlined as Call>::call) { ++ scope 5 (inlined ::call) { ++ } ++ } + } + } + } @@ -14,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = ::call() -> [return: bb1, unwind unreachable]; -+ _1 = as Call>::call() -> [return: bb1, unwind unreachable]; ++ _1 = as Call>::call() -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff index 8314526ee0431..193ada05f0234 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff @@ -7,6 +7,10 @@ + scope 1 (inlined ::call) { + scope 2 (inlined as Call>::call) { + scope 3 (inlined ::call) { ++ scope 4 (inlined as Call>::call) { ++ scope 5 (inlined ::call) { ++ } ++ } + } + } + } @@ -14,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = ::call() -> [return: bb1, unwind continue]; -+ _1 = as Call>::call() -> [return: bb1, unwind continue]; ++ _1 = as Call>::call() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/unwrap_unchecked.rs b/tests/mir-opt/inline/unwrap_unchecked.rs index be133706e5c22..1adf2224d976a 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.rs +++ b/tests/mir-opt/inline/unwrap_unchecked.rs @@ -2,7 +2,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // ignore-debug: the debug assertions prevent the inlining we are testing for -// compile-flags: -Zmir-opt-level=2 -Zinline-mir +// compile-flags: -Zmir-opt-level=2 -Zinline-mir -Cdebug-assertions=no // EMIT_MIR unwrap_unchecked.unwrap_unchecked.Inline.diff // EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index 2a36ad9230e4b..9358a64b4fabe 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -7,41 +7,44 @@ let mut _2: std::option::Option; + scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; ++ } ++ ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index 14c8c671d3fe2..ac33c126155ca 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -7,48 +7,51 @@ let mut _2: std::option::Option; + scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { +- StorageDead(_2); +- return; ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; + } + +- bb2 (cleanup): { +- resume; ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); - StorageDead(_2); - return; -- } -- -- bb2 (cleanup): { -- resume; ++ StorageDead(_2); ++ return; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index d6a608476df9c..8ec65935c6612 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option) -> T { scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index d6a608476df9c..8ec65935c6612 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option) -> T { scope 1 (inlined #[track_caller] Option::::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index ffb1aedd2ea90..a10061ed9412c 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index ffb1aedd2ea90..a10061ed9412c 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir index 0114309dbb58e..7c038b0ee88e7 100644 --- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir @@ -4,19 +4,31 @@ fn ub_if_b(_1: Thing) -> Thing { debug t => _1; let mut _0: Thing; let mut _2: isize; - let mut _3: bool; scope 1 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); scope 2 { - scope 3 (inlined unreachable_unchecked::runtime) { - } } } bb0: { _2 = discriminant(_1); - _3 = Eq(_2, const 0_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { _0 = move _1; return; } + + bb2: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir similarity index 100% rename from tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir rename to tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..3ca24e152a4e0 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,16 @@ +// MIR for `manual_replace` after PreCodegen + +fn manual_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 { + debug temp => _0; + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir deleted file mode 100644 index f0cb4ca31fecc..0000000000000 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ /dev/null @@ -1,66 +0,0 @@ -// MIR for `mem_replace` after PreCodegen - -fn mem_replace(_1: &mut u32, _2: u32) -> u32 { - debug r => _1; - debug v => _2; - let mut _0: u32; - scope 1 (inlined std::mem::replace::) { - debug dest => _1; - debug src => _2; - scope 2 { - scope 3 { - debug result => _0; - scope 16 (inlined std::ptr::write::) { - debug dst => _1; - debug src => _2; - scope 17 { - } - } - } - scope 4 (inlined std::ptr::read::) { - debug src => _1; - let mut _3: *const u32; - scope 5 { - scope 6 (inlined std::ptr::read::runtime::) { - debug src => _3; - scope 7 (inlined intrinsics::is_aligned_and_not_null::) { - debug ptr => _3; - scope 8 (inlined std::ptr::const_ptr::::is_null) { - debug self => _3; - let mut _4: *const u8; - scope 9 { - scope 10 (inlined std::ptr::const_ptr::::is_null::runtime_impl) { - debug ptr => _4; - scope 11 (inlined std::ptr::const_ptr::::addr) { - debug self => _4; - scope 12 { - scope 13 (inlined std::ptr::const_ptr::::cast::<()>) { - debug self => _4; - } - } - } - } - } - } - scope 14 (inlined std::ptr::const_ptr::::is_aligned) { - debug self => _3; - scope 15 (inlined align_of::) { - } - } - } - } - } - } - } - } - - bb0: { - StorageLive(_3); - StorageLive(_4); - _0 = (*_1); - StorageDead(_4); - StorageDead(_3); - (*_1) = _2; - return; - } -} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir new file mode 100644 index 0000000000000..26919dd98dd27 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..26919dd98dd27 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs index 18c4653d4c6ea..551afea3ba5a8 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.rs +++ b/tests/mir-opt/pre-codegen/mem_replace.rs @@ -1,7 +1,8 @@ // skip-filecheck -// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 +// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir // only-64bit // ignore-debug the standard library debug assertions leak into this test +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 26b2663fa3580..4906c86f8ed97 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate>; - let mut _15: std::iter::Enumerate>; - let mut _16: &mut std::iter::Enumerate>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate>; + let mut _17: std::iter::Enumerate>; + let mut _18: &mut std::iter::Enumerate>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind unreachable]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = > as Iterator>::next(move _18) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index a055612bd5feb..25a5ecdc6c360 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate>; - let mut _15: std::iter::Enumerate>; - let mut _16: &mut std::iter::Enumerate>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate>; + let mut _17: std::iter::Enumerate>; + let mut _18: &mut std::iter::Enumerate>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = > as Iterator>::next(move _18) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind continue]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 471491108e0b6..133d6f53fce11 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = as Iterator>::next(move _17) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind unreachable]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index bbf38aba91f08..4e74253e54172 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = as Iterator>::next(move _17) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index f9c8ab4db60b7..639e1a51430db 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev>; - let mut _15: std::iter::Rev>; - let mut _16: &mut std::iter::Rev>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev>; + let mut _17: std::iter::Rev>; + let mut _18: &mut std::iter::Rev>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined > as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 65f423ac326be..2237fd7dbd12c 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev>; - let mut _15: std::iter::Rev>; - let mut _16: &mut std::iter::Rev>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev>; + let mut _17: std::iter::Rev>; + let mut _18: &mut std::iter::Rev>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined > as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined > as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::::new_unchecked::runtime::) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::>::new) { - debug iter => _13; + scope 19 (inlined as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::>::new) { + debug iter => _15; } } - scope 24 (inlined > as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined > as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull:: { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull:: { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind continue]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = >::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = >::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/mir-opt/remove_storage_markers.rs b/tests/mir-opt/remove_storage_markers.rs index 6666ff3b7263b..27661ab325411 100644 --- a/tests/mir-opt/remove_storage_markers.rs +++ b/tests/mir-opt/remove_storage_markers.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: RemoveStorageMarkers @@ -8,6 +7,10 @@ // EMIT_MIR remove_storage_markers.main.RemoveStorageMarkers.diff fn main() { + // CHECK-LABEL: fn main( + + // CHECK-NOT: StorageDead + // CHECK-NOT: StorageLive let mut sum = 0; for i in 0..10 { sum += i; diff --git a/tests/mir-opt/retag.rs b/tests/mir-opt/retag.rs index 1e4b017dad5fa..554b8ece90f28 100644 --- a/tests/mir-opt/retag.rs +++ b/tests/mir-opt/retag.rs @@ -28,7 +28,7 @@ impl Drop for Test { // EMIT_MIR retag.main.SimplifyCfg-elaborate-drops.after.mir // EMIT_MIR retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir -fn main() { +pub fn main() { let mut x = 0; { let v = Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index e7280f148377c..d273161528464 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -66,7 +66,7 @@ _5 = ((_2 as Break).0: std::result::Result); StorageLive(_6); _6 = _5; - _12 = move ((_5 as Err).0: i32); + _12 = ((_5 as Err).0: i32); _0 = Result::::Err(_12); StorageDead(_6); StorageDead(_2); @@ -83,7 +83,7 @@ } bb4: { - _10 = move ((_1 as Err).0: i32); + _10 = ((_1 as Err).0: i32); StorageLive(_11); _11 = Result::::Err(_10); _2 = ControlFlow::, i32>::Break(move _11); @@ -92,7 +92,7 @@ } bb5: { - _9 = move ((_1 as Ok).0: i32); + _9 = ((_1 as Ok).0: i32); _2 = ControlFlow::, i32>::Continue(_9); goto -> bb3; } diff --git a/tests/mir-opt/simplify_if.rs b/tests/mir-opt/simplify_if.rs index 19b5806f72094..f600c05958198 100644 --- a/tests/mir-opt/simplify_if.rs +++ b/tests/mir-opt/simplify_if.rs @@ -1,10 +1,13 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #[inline(never)] fn noop() {} // EMIT_MIR simplify_if.main.SimplifyConstCondition-after-const-prop.diff fn main() { + // CHECK-LABEL: fn main( + + // CHECK: bb0: { + // CHECK-NEXT: return; if false { noop(); } diff --git a/tests/mir-opt/slice_drop_shim.rs b/tests/mir-opt/slice_drop_shim.rs index cac0a349128c3..037e048b3b797 100644 --- a/tests/mir-opt/slice_drop_shim.rs +++ b/tests/mir-opt/slice_drop_shim.rs @@ -1,6 +1,8 @@ // skip-filecheck -// compile-flags: -Zmir-opt-level=0 - +// compile-flags: -Zmir-opt-level=0 -Clink-dead-code +// mir-opt tests are always built as rlibs so that they seamlessly cross-compile, +// so this test only produces MIR for the drop_in_place we're looking for +// if we use -Clink-dead-code. // EMIT_MIR core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir fn main() { diff --git a/tests/mir-opt/sroa/lifetimes.rs b/tests/mir-opt/sroa/lifetimes.rs index cc5c0c9bbcdb5..ea04fac15710e 100644 --- a/tests/mir-opt/sroa/lifetimes.rs +++ b/tests/mir-opt/sroa/lifetimes.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ScalarReplacementOfAggregates // compile-flags: -Cpanic=abort // no-prefer-dynamic @@ -16,6 +15,10 @@ struct Foo { // EMIT_MIR lifetimes.foo.ScalarReplacementOfAggregates.diff fn foo() { + // CHECK-LABEL: fn foo( + + // CHECK-NOT: [foo:_.*]: Foo + // CHECK-NOT: Box let foo: Foo = Foo { x: Ok(Box::new(5_u32)), y: 7_u32, diff --git a/tests/mir-opt/sroa/structs.rs b/tests/mir-opt/sroa/structs.rs index 73563e12c94fc..5ea3795b86e2d 100644 --- a/tests/mir-opt/sroa/structs.rs +++ b/tests/mir-opt/sroa/structs.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ScalarReplacementOfAggregates // compile-flags: -Cpanic=abort // no-prefer-dynamic @@ -13,28 +12,68 @@ impl Drop for Tag { fn drop(&mut self) {} } +/// Check that SROA excludes structs with a `Drop` implementation. pub fn dropping() { + // CHECK-LABEL: fn dropping( + + // CHECK: [[aggregate:_[0-9]+]]: S; + + // CHECK: bb0: { + // CHECK: [[aggregate]] = S S(Tag(0), Tag(1), Tag(2)).1; } +/// Check that SROA excludes enums. pub fn enums(a: usize) -> usize { + // CHECK-LABEL: fn enums( + + // CHECK: [[enum:_[0-9]+]]: std::option::Option; + + // CHECK: bb0: { + // CHECK: [[enum]] = Option::::Some + // CHECK: _5 = (([[enum]] as Some).0: usize) + // CHECK: _0 = _5 if let Some(a) = Some(a) { a } else { 0 } } +/// Check that SROA destructures `U`. pub fn structs(a: f32) -> f32 { + // CHECK-LABEL: fn structs( struct U { _foo: usize, a: f32, } - + // CHECK: [[ret:_0]]: f32; + // CHECK: [[struct:_[0-9]+]]: structs::U; + // CHECK: [[a_tmp:_[0-9]+]]: f32; + // CHECK: [[foo:_[0-9]+]]: usize; + // CHECK: [[a_ret:_[0-9]+]]: f32; + + // CHECK: bb0: { + // CHECK-NOT: [[struct]] + // CHECK: [[a_tmp]] = _1; + // CHECK-NOT: [[struct]] + // CHECK: [[foo]] = const 0_usize; + // CHECK-NOT: [[struct]] + // CHECK: [[a_ret]] = move [[a_tmp]]; + // CHECK-NOT: [[struct]] + // CHECK: _0 = [[a_ret]]; + // CHECK-NOT: [[struct]] U { _foo: 0, a }.a } +/// Check that SROA excludes unions. pub fn unions(a: f32) -> u32 { + // CHECK-LABEL: fn unions( union Repr { f: f32, u: u32, } + // CHECK: [[union:_[0-9]+]]: unions::Repr; + + // CHECK: bb0: { + // CHECK: [[union]] = Repr { + // CHECK: _0 = ([[union]].1: u32) unsafe { Repr { f: a }.u } } @@ -46,11 +85,21 @@ struct Foo { d: Option, } -fn g() -> u32 { - 3 -} - +/// Check that non-escaping uses of a struct are destructured. pub fn flat() { + // CHECK-LABEL: fn flat( + + // CHECK: [[struct:_[0-9]+]]: Foo; + + // CHECK: bb0: { + // CHECK: [[init_unit:_[0-9]+]] = (); + // CHECK: [[init_opt_isize:_[0-9]+]] = Option::::Some + + // CHECK: [[destr_five:_[0-9]+]] = const 5_u8; + // CHECK: [[destr_unit:_[0-9]+]] = move [[init_unit]]; + // CHECK: [[destr_a:_[0-9]+]] = const "a"; + // CHECK: [[destr_opt_isize:_[0-9]+]] = move [[init_opt_isize]]; + let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) }; let _ = a; let _ = b; @@ -65,6 +114,10 @@ struct Escaping { c: u32, } +fn g() -> u32 { + 3 +} + fn f(a: *const u32) { println!("{}", unsafe { *a.add(2) }); } @@ -76,10 +129,38 @@ fn f(a: *const u32) { // of them to `f`. However, this would lead to a miscompilation because `b` and `c` // might no longer appear right after `a` in memory. pub fn escaping() { + // CHECK-LABEL: fn escaping( + + // CHECK: [[ptr:_[0-9]+]]: *const u32; + // CHECK: [[ref:_[0-9]+]]: &u32; + // CHECK: [[struct:_[0-9]+]]: Escaping; + // CHECK: [[a:_[0-9]+]]: u32; + + // CHECK: bb0: { + // CHECK: [[struct]] = Escaping { + // CHECK: [[ref]] = &([[struct]].0 + // CHECK: [[ptr]] = &raw const (*[[ref]]); f(&Escaping { a: 1, b: 2, c: g() }.a); } +/// Check that copies from an internal struct are destructured and reassigned to +/// the original struct. fn copies(x: Foo) { + // CHECK-LABEL: fn copies( + + // CHECK: [[external:_[0-9]+]]: Foo) -> + // CHECK: [[internal:_[0-9]+]]: Foo; + // CHECK: [[byte:_[0-9]+]]: u8; + // CHECK: [[unit:_[0-9]+]]: (); + // CHECK: [[str:_[0-9]+]]: &str; + // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option; + + // CHECK: bb0: { + // CHECK: [[byte]] = ([[external]].0 + // CHECK: [[unit]] = ([[external]].1 + // CHECK: [[str]] = ([[external]].2 + // CHECK: [[opt_isize]] = ([[external]].3 + let y = x; let t = y.a; let u = y.c; @@ -87,13 +168,44 @@ fn copies(x: Foo) { let a = z.b; } +/// Check that copies from an internal struct are destructured and reassigned to +/// the original struct. fn ref_copies(x: &Foo) { + // CHECK-LABEL: fn ref_copies( + + // CHECK: [[external:_[0-9]+]]: &Foo) -> + // CHECK: [[internal:_[0-9]+]]: Foo; + // CHECK: [[byte:_[0-9]+]]: u8; + // CHECK: [[unit:_[0-9]+]]: (); + // CHECK: [[str:_[0-9]+]]: &str; + // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option; + + // CHECK: bb0: { + // CHECK: [[byte]] = ((*[[external]]).0 + // CHECK: [[unit]] = ((*[[external]]).1 + // CHECK: [[str]] = ((*[[external]]).2 + // CHECK: [[opt_isize]] = ((*[[external]]).3 + let y = *x; let t = y.a; let u = y.c; } +/// Check that deaggregated assignments from constants are placed after the constant's +/// assignment. Also check that copying field accesses from the copy of the constant are +/// reassigned to copy from the constant. fn constant() { + // CHECK-LABEL: constant( + + // CHECK: [[constant:_[0-9]+]]: (usize, u8); + // CHECK: [[t:_[0-9]+]]: usize; + // CHECK: [[u:_[0-9]+]]: u8; + + // CHECK: bb0: { + // CHECK-NOT: [[constant]] + // CHECK: [[constant]] = const + // CHECK: [[t]] = move ([[constant]].0: usize) + // CHECK: [[u]] = move ([[constant]].1: u8) const U: (usize, u8) = (5, 9); let y = U; let t = y.0; @@ -101,6 +213,7 @@ fn constant() { } fn main() { + // CHECK-LABEL: fn main( dropping(); enums(5); structs(5.); diff --git a/tests/mir-opt/unusual_item_types.rs b/tests/mir-opt/unusual_item_types.rs index 49b663b4f8298..fa6ba515473ba 100644 --- a/tests/mir-opt/unusual_item_types.rs +++ b/tests/mir-opt/unusual_item_types.rs @@ -23,7 +23,7 @@ enum E { V = 5, } -fn main() { +pub fn main() { let f = Test::X as fn(usize) -> Test; // EMIT_MIR core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir let v = Vec::::new(); diff --git a/tests/pretty/delimited-token-groups.rs b/tests/pretty/delimited-token-groups.rs index c7c9277faf69e..b24c35bf0813f 100644 --- a/tests/pretty/delimited-token-groups.rs +++ b/tests/pretty/delimited-token-groups.rs @@ -9,7 +9,7 @@ mac! { { fn clone() -> S { - panic! () ; + panic! (); } } diff --git a/tests/pretty/macro_rules.rs b/tests/pretty/macro_rules.rs index 01adb14133b35..a5265446ee796 100644 --- a/tests/pretty/macro_rules.rs +++ b/tests/pretty/macro_rules.rs @@ -1,19 +1,19 @@ // pp-exact -macro_rules! brace { () => {} ; } +macro_rules! brace { () => {}; } -macro_rules! bracket[() => {} ;]; +macro_rules! bracket[() => {};]; -macro_rules! paren(() => {} ;); +macro_rules! paren(() => {};); macro_rules! matcher_brackets { - (paren) => {} ; (bracket) => {} ; (brace) => {} ; + (paren) => {}; (bracket) => {}; (brace) => {}; } macro_rules! all_fragments { ($b : block, $e : expr, $i : ident, $it : item, $l : lifetime, $lit : literal, $m : meta, $p : pat, $pth : path, $s : stmt, $tt : tt, $ty : ty, - $vis : vis) => {} ; + $vis : vis) => {}; } fn main() {} diff --git a/tests/pretty/stmt_expr_attributes.rs b/tests/pretty/stmt_expr_attributes.rs index 052c45f2cb8b6..69b153175615b 100644 --- a/tests/pretty/stmt_expr_attributes.rs +++ b/tests/pretty/stmt_expr_attributes.rs @@ -113,7 +113,7 @@ fn _8() { } fn _9() { - macro_rules! stmt_mac { () => { let _ = () ; } } + macro_rules! stmt_mac { () => { let _ = (); } } #[rustc_dummy] stmt_mac!(); diff --git a/tests/run-make/rust-lld-custom-target/custom-target.json b/tests/run-make/rust-lld-custom-target/custom-target.json index 7828a99f235c1..e2c64cbdb43c2 100644 --- a/tests/run-make/rust-lld-custom-target/custom-target.json +++ b/tests/run-make/rust-lld-custom-target/custom-target.json @@ -2,7 +2,7 @@ "arch": "x86_64", "cpu": "x86-64", "crt-static-respected": true, - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "gnu", "has-rpath": true, diff --git a/tests/run-make/rustdoc-target-spec-json-path/target.json b/tests/run-make/rustdoc-target-spec-json-path/target.json index 34357182c205e..c478f1196fae0 100644 --- a/tests/run-make/rustdoc-target-spec-json-path/target.json +++ b/tests/run-make/rustdoc-target-spec-json-path/target.json @@ -2,7 +2,7 @@ "arch": "x86_64", "cpu": "x86-64", "crt-static-respected": true, - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", "dynamic-linking": true, "env": "gnu", "executables": true, diff --git a/tests/run-make/target-specs/my-awesome-platform.json b/tests/run-make/target-specs/my-awesome-platform.json index 00de3de05f07a..1673ef7bd54d1 100644 --- a/tests/run-make/target-specs/my-awesome-platform.json +++ b/tests/run-make/target-specs/my-awesome-platform.json @@ -1,5 +1,5 @@ { - "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128", + "data-layout": "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i128:128-f64:32:64-f80:32-n8:16:32-S128", "linker-flavor": "gcc", "llvm-target": "i686-unknown-linux-gnu", "target-endian": "little", diff --git a/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json b/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json index 6d5e964ed4fee..0cafce15a9fef 100644 --- a/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json +++ b/tests/run-make/target-specs/my-x86_64-unknown-linux-gnu-platform.json @@ -1,6 +1,6 @@ { "pre-link-args": {"gcc": ["-m64"]}, - "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", + "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", "linker-flavor": "gcc", "llvm-target": "x86_64-unknown-linux-gnu", "target-endian": "little", diff --git a/tests/rustdoc-ui/issues/issue-102986.stderr b/tests/rustdoc-ui/issues/issue-102986.stderr index 996eb41c492b0..d91f93f394a5b 100644 --- a/tests/rustdoc-ui/issues/issue-102986.stderr +++ b/tests/rustdoc-ui/issues/issue-102986.stderr @@ -6,8 +6,8 @@ LL | y: (typeof("hey"),), | help: consider replacing `typeof(...)` with an actual type | -LL | y: (&'static str,), - | ~~~~~~~~~~~~ +LL | y: (&str,), + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/issues/issue-120444-1.rs b/tests/rustdoc-ui/issues/issue-120444-1.rs new file mode 100644 index 0000000000000..25d0111a7b763 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-1.stderr b/tests/rustdoc-ui/issues/issue-120444-1.stderr new file mode 100644 index 0000000000000..7bc56b4263f26 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-1.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-1.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/issues/issue-120444-2.rs b/tests/rustdoc-ui/issues/issue-120444-2.rs new file mode 100644 index 0000000000000..d13bf88462435 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +pub mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-2.stderr b/tests/rustdoc-ui/issues/issue-120444-2.stderr new file mode 100644 index 0000000000000..310bf08e2b525 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-2.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-2.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs index 0901ac3640fdd..ffd694e987908 100644 --- a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs +++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.rs @@ -24,10 +24,9 @@ mod rustc_ok { pub fn rustc_lints() { let x = 42.0; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] match x { - 5.0 => {} - 6.0 => {} + f32::NAN => {} _ => {} } } @@ -40,7 +39,7 @@ mod rustc_warn { pub fn rustc_lints() { let x = 42; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] match x { 5 => {} 6 => {} diff --git a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr index efc5f349f4f44..5ae3c039d275a 100644 --- a/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr +++ b/tests/rustdoc-ui/lints/expect-tool-lint-rfc-2383.stderr @@ -7,19 +7,19 @@ LL | #![expect(rustdoc::missing_crate_level_docs)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:71:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:70:14 | LL | #[expect(rustdoc::broken_intra_doc_links)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:76:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:75:14 | LL | #[expect(rustdoc::invalid_html_tags)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: this lint expectation is unfulfilled - --> $DIR/expect-tool-lint-rfc-2383.rs:81:14 + --> $DIR/expect-tool-lint-rfc-2383.rs:80:14 | LL | #[expect(rustdoc::bare_urls)] | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr index bd21dcb6e1af9..000a5b597d299 100644 --- a/tests/rustdoc-ui/unescaped_backticks.stderr +++ b/tests/rustdoc-ui/unescaped_backticks.stderr @@ -302,7 +302,6 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: or `None` if it isn't. to this: or `None\` if it isn't. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 @@ -322,7 +321,6 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: `on_event` should be called. to this: `on_event\` should be called. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:323:5 @@ -342,7 +340,6 @@ LL | | /// level changes. = help: if you meant to use a literal backtick, escape it change: [`rebuild_interest_cache`][rebuild] is called after the value of the max to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: unescaped backtick --> $DIR/unescaped_backticks.rs:349:56 diff --git a/tests/rustdoc/glob-reexport-attribute-merge-120487.rs b/tests/rustdoc/glob-reexport-attribute-merge-120487.rs new file mode 100644 index 0000000000000..98cdec107ae08 --- /dev/null +++ b/tests/rustdoc/glob-reexport-attribute-merge-120487.rs @@ -0,0 +1,32 @@ +// This test ensures that non-glob reexports don't get their attributes merge with +// the reexported item whereas glob reexports do. +// Regression test for . + +#![crate_name = "foo"] +#![feature(doc_cfg)] + +// @has 'foo/index.html' +// There are two items. +// @count - '//*[@class="item-table"]//div[@class="item-name"]' 2 +// Only one of them should have an attribute. +// @count - '//*[@class="item-table"]//div[@class="item-name"]/*[@class="stab portability"]' 1 + +mod a { + #[doc(cfg(not(feature = "a")))] + #[cfg(not(feature = "a"))] + pub struct Test1; +} + +mod b { + #[doc(cfg(not(feature = "a")))] + #[cfg(not(feature = "a"))] + pub struct Test2; +} + +// @has 'foo/struct.Test1.html' +// @count - '//*[@id="main-content"]/*[@class="item-info"]' 1 +// @has - '//*[@id="main-content"]/*[@class="item-info"]' 'Available on non-crate feature a only.' +pub use a::*; +// @has 'foo/struct.Test2.html' +// @count - '//*[@id="main-content"]/*[@class="item-info"]' 0 +pub use b::Test2; diff --git a/tests/rustdoc/jump-to-non-local-method.rs b/tests/rustdoc/jump-to-non-local-method.rs new file mode 100644 index 0000000000000..7767b92fbe557 --- /dev/null +++ b/tests/rustdoc/jump-to-non-local-method.rs @@ -0,0 +1,48 @@ +// compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +// @has 'src/foo/jump-to-non-local-method.rs.html' + +// @has - '//a[@href="{{channel}}/core/sync/atomic/struct.AtomicIsize.html"]' 'std::sync::atomic::AtomicIsize' +use std::sync::atomic::AtomicIsize; +// @has - '//a[@href="{{channel}}/std/io/trait.Read.html"]' 'std::io::Read' +use std::io::Read; +// @has - '//a[@href="{{channel}}/std/io/index.html"]' 'std::io' +use std::io; +// @has - '//a[@href="{{channel}}/std/process/fn.exit.html"]' 'std::process::exit' +use std::process::exit; +use std::cmp::Ordering; +use std::marker::PhantomData; + +pub fn bar2(readable: T) { + // @has - '//a[@href="{{channel}}/std/io/trait.Read.html#tymethod.read"]' 'read' + let _ = readable.read(&mut []); +} + +pub fn bar() { + // @has - '//a[@href="{{channel}}/core/sync/atomic/struct.AtomicIsize.html#method.new"]' 'AtomicIsize::new' + let _ = AtomicIsize::new(0); + // @has - '//a[@href="#48"]' 'local_private' + local_private(); +} + +pub fn extern_call() { + // @has - '//a[@href="{{channel}}/std/process/fn.exit.html"]' 'exit' + exit(0); +} + +pub fn macro_call() -> Result<(), ()> { + // @has - '//a[@href="{{channel}}/core/macro.try.html"]' 'try!' + try!(Err(())); + Ok(()) +} + +pub fn variant() { + // @has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html#variant.Less"]' 'Ordering::Less' + let _ = Ordering::Less; + // @has - '//a[@href="{{channel}}/core/marker/struct.PhantomData.html"]' 'PhantomData' + let _: PhantomData:: = PhantomData; +} + +fn local_private() {} diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index ab42d3b8c1e4e..5a2099865d6a7 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -14,7 +14,7 @@ extern crate rustc_span; use rustc_errors::{ AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, DiagCtxt, - IntoDiagnostic, Level, SubdiagnosticMessage, + IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -55,9 +55,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagn pub struct UntranslatableInAddToDiagnostic; impl AddToDiagnostic for UntranslatableInAddToDiagnostic { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.note("untranslatable diagnostic"); //~^ ERROR diagnostics should be created using translatable messages @@ -67,10 +65,7 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic { pub struct TranslatableInAddToDiagnostic; impl AddToDiagnostic for TranslatableInAddToDiagnostic { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.note(crate::fluent_generated::no_crate_note); } } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index f70240ecf172a..108b7c8ea9cbb 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -11,13 +11,13 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:62:14 + --> $DIR/diagnostics.rs:60:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:79:21 + --> $DIR/diagnostics.rs:74:21 | LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); | ^^^^^^^^^^ @@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:82:21 + --> $DIR/diagnostics.rs:77:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:82:21 + --> $DIR/diagnostics.rs:77:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ diff --git a/tests/ui-fulldeps/internal-lints/query_stability.rs b/tests/ui-fulldeps/internal-lints/query_stability.rs index 560675b448608..627ffa5cbd0f3 100644 --- a/tests/ui-fulldeps/internal-lints/query_stability.rs +++ b/tests/ui-fulldeps/internal-lints/query_stability.rs @@ -21,4 +21,17 @@ fn main() { for _ in x {} //~^ ERROR using `into_iter` + + let x = FxHashMap::::default(); + let _ = x.keys(); + //~^ ERROR using `keys` can result in unstable query results + + let _ = x.values(); + //~^ ERROR using `values` can result in unstable query results + + let mut x = FxHashMap::::default(); + for val in x.values_mut() { + //~^ ERROR using `values_mut` can result in unstable query results + *val = *val + 10; + } } diff --git a/tests/ui-fulldeps/internal-lints/query_stability.stderr b/tests/ui-fulldeps/internal-lints/query_stability.stderr index ee4ef9982371e..43b156dc20a3c 100644 --- a/tests/ui-fulldeps/internal-lints/query_stability.stderr +++ b/tests/ui-fulldeps/internal-lints/query_stability.stderr @@ -35,5 +35,29 @@ LL | for _ in x {} | = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale -error: aborting due to 4 previous errors +error: using `keys` can result in unstable query results + --> $DIR/query_stability.rs:26:15 + | +LL | let _ = x.keys(); + | ^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale + +error: using `values` can result in unstable query results + --> $DIR/query_stability.rs:29:15 + | +LL | let _ = x.values(); + | ^^^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale + +error: using `values_mut` can result in unstable query results + --> $DIR/query_stability.rs:33:18 + | +LL | for val in x.values_mut() { + | ^^^^^^^^^^ + | + = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale + +error: aborting due to 7 previous errors diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs index ae7f341fe4e33..cce223c77bbab 100644 --- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs +++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.rs @@ -29,6 +29,7 @@ fn main() { TyKind::FnPtr(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Dynamic(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::` + TyKind::CoroutineClosure(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Coroutine(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::CoroutineWitness(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Never => (), //~ ERROR usage of `ty::TyKind::` diff --git a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr index 45b7c26faad07..2ff5aad95dd87 100644 --- a/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr +++ b/tests/ui-fulldeps/internal-lints/ty_tykind_usage.stderr @@ -109,71 +109,77 @@ LL | TyKind::Closure(..) => (), error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:32:9 | -LL | TyKind::Coroutine(..) => (), +LL | TyKind::CoroutineClosure(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:33:9 | -LL | TyKind::CoroutineWitness(..) => (), +LL | TyKind::Coroutine(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:34:9 | -LL | TyKind::Never => (), +LL | TyKind::CoroutineWitness(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:35:9 | -LL | TyKind::Tuple(..) => (), +LL | TyKind::Never => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:36:9 | -LL | TyKind::Alias(..) => (), +LL | TyKind::Tuple(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:37:9 | -LL | TyKind::Param(..) => (), +LL | TyKind::Alias(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:38:9 | -LL | TyKind::Bound(..) => (), +LL | TyKind::Param(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:39:9 | -LL | TyKind::Placeholder(..) => (), +LL | TyKind::Bound(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:40:9 | -LL | TyKind::Infer(..) => (), +LL | TyKind::Placeholder(..) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:41:9 | +LL | TyKind::Infer(..) => (), + | ^^^^^^ help: try using `ty::` directly: `ty` + +error: usage of `ty::TyKind::` + --> $DIR/ty_tykind_usage.rs:42:9 + | LL | TyKind::Error(_) => (), | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:46:12 + --> $DIR/ty_tykind_usage.rs:47:12 | LL | if let TyKind::Int(int_ty) = kind {} | ^^^^^^ help: try using `ty::` directly: `ty` error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:48:24 + --> $DIR/ty_tykind_usage.rs:49:24 | LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} | ^^^^^^^^^^ @@ -181,7 +187,7 @@ LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:50:37 + --> $DIR/ty_tykind_usage.rs:51:37 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -189,7 +195,7 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:50:53 + --> $DIR/ty_tykind_usage.rs:51:53 | LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { | ^^^^^^^^^^^ @@ -197,12 +203,12 @@ LL | fn ir_ty_kind(bad: IrTyKind) -> IrTyKind { = help: try using `Ty` instead error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:53:9 + --> $DIR/ty_tykind_usage.rs:54:9 | LL | IrTyKind::Bool | --------^^^^^^ | | | help: try using `ty::` directly: `ty` -error: aborting due to 32 previous errors +error: aborting due to 33 previous errors diff --git a/tests/ui-fulldeps/rustc_encodable_hygiene.rs b/tests/ui-fulldeps/rustc_encodable_hygiene.rs index bec7930d4622f..36c684a131e65 100644 --- a/tests/ui-fulldeps/rustc_encodable_hygiene.rs +++ b/tests/ui-fulldeps/rustc_encodable_hygiene.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs index 785da11b9b2e3..3056ebb7575fd 100644 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs +++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs @@ -19,6 +19,6 @@ use rustc_errors::{Applicability, MultiSpan}; extern crate rustc_session; #[derive(Diagnostic)] -#[diag(compiletest_example, code = 0123)] +#[diag(compiletest_example, code = E0123)] //~^ ERROR diagnostic slug and crate name do not match struct Hello {} diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr index eda24a555f848..df1bad3cad0cf 100644 --- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr +++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr @@ -1,7 +1,7 @@ error: diagnostic slug and crate name do not match --> $DIR/enforce_slug_naming.rs:22:8 | -LL | #[diag(compiletest_example, code = 0123)] +LL | #[diag(compiletest_example, code = E0123)] | ^^^^^^^^^^^^^^^^^^^ | = note: slug is `compiletest_example` but the crate name is `rustc_dummy` diff --git a/tests/ui/abi/unsupported.aarch64.stderr b/tests/ui/abi/unsupported.aarch64.stderr index d7b4e6150ff31..72a9519e3e772 100644 --- a/tests/ui/abi/unsupported.aarch64.stderr +++ b/tests/ui/abi/unsupported.aarch64.stderr @@ -1,59 +1,53 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -62,6 +56,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 9 previous errors; 1 warning emitted +error: aborting due to 8 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.arm.stderr b/tests/ui/abi/unsupported.arm.stderr index 3a3ed2dd9c569..473b59a334df3 100644 --- a/tests/ui/abi/unsupported.arm.stderr +++ b/tests/ui/abi/unsupported.arm.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.i686.stderr b/tests/ui/abi/unsupported.i686.stderr index 31b7d030bd3b4..f0af3d251e245 100644 --- a/tests/ui/abi/unsupported.i686.stderr +++ b/tests/ui/abi/unsupported.i686.stderr @@ -1,45 +1,39 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv32.stderr b/tests/ui/abi/unsupported.riscv32.stderr index 1966e18f0a06e..b466a2a6ff86b 100644 --- a/tests/ui/abi/unsupported.riscv32.stderr +++ b/tests/ui/abi/unsupported.riscv32.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.riscv64.stderr b/tests/ui/abi/unsupported.riscv64.stderr index 1966e18f0a06e..b466a2a6ff86b 100644 --- a/tests/ui/abi/unsupported.riscv64.stderr +++ b/tests/ui/abi/unsupported.riscv64.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:51:1 + --> $DIR/unsupported.rs:48:1 | LL | extern "x86-interrupt" fn x86() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/abi/unsupported.rs b/tests/ui/abi/unsupported.rs index 57278e664b51e..9b99e51905da2 100644 --- a/tests/ui/abi/unsupported.rs +++ b/tests/ui/abi/unsupported.rs @@ -19,7 +19,6 @@ abi_ptx, abi_msp430_interrupt, abi_avr_interrupt, - abi_amdgpu_kernel, wasm_abi, abi_x86_interrupt, abi_riscv_interrupt @@ -29,8 +28,6 @@ trait Sized {} extern "ptx-kernel" fn ptx() {} //~^ ERROR is not a supported ABI -extern "amdgpu-kernel" fn amdgpu() {} -//~^ ERROR is not a supported ABI extern "wasm" fn wasm() {} //~^ ERROR is not a supported ABI extern "aapcs" fn aapcs() {} diff --git a/tests/ui/abi/unsupported.x64.stderr b/tests/ui/abi/unsupported.x64.stderr index ea62cb1514807..4a2b7e7496920 100644 --- a/tests/ui/abi/unsupported.x64.stderr +++ b/tests/ui/abi/unsupported.x64.stderr @@ -1,53 +1,47 @@ error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:30:1 + --> $DIR/unsupported.rs:29:1 | LL | extern "ptx-kernel" fn ptx() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:32:1 - | -LL | extern "amdgpu-kernel" fn amdgpu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0570]: `"wasm"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:34:1 + --> $DIR/unsupported.rs:31:1 | LL | extern "wasm" fn wasm() {} | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"aapcs"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:36:1 + --> $DIR/unsupported.rs:33:1 | LL | extern "aapcs" fn aapcs() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:42:1 + --> $DIR/unsupported.rs:39:1 | LL | extern "msp430-interrupt" fn msp430() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:44:1 + --> $DIR/unsupported.rs:41:1 | LL | extern "avr-interrupt" fn avr() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"riscv-interrupt-m"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:46:1 + --> $DIR/unsupported.rs:43:1 | LL | extern "riscv-interrupt-m" fn riscv() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0570]: `"thiscall"` is not a supported ABI for the current target - --> $DIR/unsupported.rs:56:1 + --> $DIR/unsupported.rs:53:1 | LL | extern "thiscall" fn thiscall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of calling convention not supported on this target - --> $DIR/unsupported.rs:62:1 + --> $DIR/unsupported.rs:59:1 | LL | extern "stdcall" fn stdcall() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -56,6 +50,6 @@ LL | extern "stdcall" fn stdcall() {} = note: for more information, see issue #87678 = note: `#[warn(unsupported_calling_conventions)]` on by default -error: aborting due to 8 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/anon-params/anon-params-deprecated.fixed b/tests/ui/anon-params/anon-params-deprecated.fixed index c09e20770846e..8ec1d41a70985 100644 --- a/tests/ui/anon-params/anon-params-deprecated.fixed +++ b/tests/ui/anon-params/anon-params-deprecated.fixed @@ -5,6 +5,7 @@ // edition:2015 // run-rustfix +#[allow(dead_code)] trait T { fn foo(_: i32); //~ WARNING anonymous parameters are deprecated //~| WARNING this is accepted in the current edition diff --git a/tests/ui/anon-params/anon-params-deprecated.rs b/tests/ui/anon-params/anon-params-deprecated.rs index 6f7385da040c5..108ba60a02f58 100644 --- a/tests/ui/anon-params/anon-params-deprecated.rs +++ b/tests/ui/anon-params/anon-params-deprecated.rs @@ -5,6 +5,7 @@ // edition:2015 // run-rustfix +#[allow(dead_code)] trait T { fn foo(i32); //~ WARNING anonymous parameters are deprecated //~| WARNING this is accepted in the current edition diff --git a/tests/ui/anon-params/anon-params-deprecated.stderr b/tests/ui/anon-params/anon-params-deprecated.stderr index 691e2c7951249..541cb004b5b2c 100644 --- a/tests/ui/anon-params/anon-params-deprecated.stderr +++ b/tests/ui/anon-params/anon-params-deprecated.stderr @@ -1,5 +1,5 @@ warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:9:12 + --> $DIR/anon-params-deprecated.rs:10:12 | LL | fn foo(i32); | ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32` @@ -13,7 +13,7 @@ LL | #![warn(anonymous_parameters)] | ^^^^^^^^^^^^^^^^^^^^ warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:12:30 + --> $DIR/anon-params-deprecated.rs:13:30 | LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` @@ -22,7 +22,7 @@ LL | fn bar_with_default_impl(String, String) {} = note: for more information, see issue #41686 warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:12:38 + --> $DIR/anon-params-deprecated.rs:13:38 | LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` diff --git a/tests/ui/anonymous-higher-ranked-lifetime.stderr b/tests/ui/anonymous-higher-ranked-lifetime.stderr index e441cbdc866a1..cc27a0fcf95f5 100644 --- a/tests/ui/anonymous-higher-ranked-lifetime.stderr +++ b/tests/ui/anonymous-higher-ranked-lifetime.stderr @@ -2,8 +2,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 | LL | f1(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` @@ -22,8 +23,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 | LL | f2(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _` @@ -42,8 +44,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 | LL | f3(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _` @@ -62,8 +65,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 | LL | f4(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'r, 'a> fn(&'a (), &'r ()) -> _` @@ -82,8 +86,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 | LL | f5(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'r> fn(&'r (), &'r ()) -> _` @@ -102,8 +107,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 | LL | g1(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` @@ -122,8 +128,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 | LL | g2(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _` @@ -142,8 +149,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 | LL | g3(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _` @@ -162,8 +170,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 | LL | g4(|_: (), _: ()| {}); - | ^^ -------------- found signature defined here - | | + | ^^^--------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _` @@ -182,8 +191,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 | LL | h1(|_: (), _: (), _: (), _: ()| {}); - | ^^ ---------------------------- found signature defined here - | | + | ^^^----------------------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _` @@ -202,8 +212,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 | LL | h2(|_: (), _: (), _: (), _: ()| {}); - | ^^ ---------------------------- found signature defined here - | | + | ^^^----------------------------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `for<'t0, 'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _` diff --git a/tests/ui/array-slice-vec/vec-matching-autoslice.rs b/tests/ui/array-slice-vec/vec-matching-autoslice.rs index 8179edf420cb0..f839cd62b1a5d 100644 --- a/tests/ui/array-slice-vec/vec-matching-autoslice.rs +++ b/tests/ui/array-slice-vec/vec-matching-autoslice.rs @@ -1,5 +1,4 @@ // run-pass -#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 pub fn main() { let x = [1, 2, 3]; diff --git a/tests/ui/asm/aarch64/type-check-3.rs b/tests/ui/asm/aarch64/type-check-3.rs index 623f6593d79ba..77524ba7aa5e4 100644 --- a/tests/ui/asm/aarch64/type-check-3.rs +++ b/tests/ui/asm/aarch64/type-check-3.rs @@ -1,7 +1,7 @@ // only-aarch64 // compile-flags: -C target-feature=+neon -#![feature(repr_simd, stdsimd, asm_const)] +#![feature(repr_simd, asm_const)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; diff --git a/tests/ui/asm/aarch64/type-check-4.rs b/tests/ui/asm/aarch64/type-check-4.rs index bd23755c02316..5dec60a2138d9 100644 --- a/tests/ui/asm/aarch64/type-check-4.rs +++ b/tests/ui/asm/aarch64/type-check-4.rs @@ -1,7 +1,7 @@ // only-aarch64 // compile-flags: -C target-feature=+neon -#![feature(repr_simd, stdsimd, asm_const)] +#![feature(repr_simd, asm_const)] use std::arch::aarch64::float64x2_t; use std::arch::{asm, global_asm}; diff --git a/tests/ui/asm/bad-template.aarch64.stderr b/tests/ui/asm/bad-template.aarch64.stderr index 4ffcd2303b74f..b18946d7c6d85 100644 --- a/tests/ui/asm/bad-template.aarch64.stderr +++ b/tests/ui/asm/bad-template.aarch64.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:27:15 + --> $DIR/bad-template.rs:30:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:29:15 + --> $DIR/bad-template.rs:32:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:29:21 + --> $DIR/bad-template.rs:32:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:32:16 + --> $DIR/bad-template.rs:35:16 | LL | asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:34:15 + --> $DIR/bad-template.rs:37:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:37:15 + --> $DIR/bad-template.rs:40:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:37:21 + --> $DIR/bad-template.rs:40:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:44:15 + --> $DIR/bad-template.rs:47:15 | LL | asm!("{}", in("x0") foo); | ^^ ------------ explicit register argument @@ -77,24 +77,24 @@ LL | asm!("{}", in("x0") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:44:20 + --> $DIR/bad-template.rs:47:20 | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ help: use the register name directly in the assembly code - --> $DIR/bad-template.rs:44:20 + --> $DIR/bad-template.rs:47:20 | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:17 + --> $DIR/bad-template.rs:49:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:49:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -104,7 +104,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:55:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -112,7 +112,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:57:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -120,7 +120,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:57:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -128,13 +128,13 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:60:15 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:62:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -143,13 +143,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -157,7 +157,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:65:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -165,7 +165,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:65:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -173,13 +173,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:68:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:70:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -189,7 +189,7 @@ LL | global_asm!("", const FOO, const FOO); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` warning: formatting may not be suitable for sub-register argument - --> $DIR/bad-template.rs:46:15 + --> $DIR/bad-template.rs:49:15 | LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument diff --git a/tests/ui/asm/bad-template.rs b/tests/ui/asm/bad-template.rs index a6a233a36ec38..b70da4921c20f 100644 --- a/tests/ui/asm/bad-template.rs +++ b/tests/ui/asm/bad-template.rs @@ -21,6 +21,9 @@ macro_rules! global_asm { #[lang = "sized"] trait Sized {} +#[lang = "copy"] +trait Copy {} + fn main() { let mut foo = 0; unsafe { diff --git a/tests/ui/asm/bad-template.x86_64.stderr b/tests/ui/asm/bad-template.x86_64.stderr index 52a7789b98cc1..2f584c30a3282 100644 --- a/tests/ui/asm/bad-template.x86_64.stderr +++ b/tests/ui/asm/bad-template.x86_64.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:27:15 + --> $DIR/bad-template.rs:30:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:29:15 + --> $DIR/bad-template.rs:32:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:29:21 + --> $DIR/bad-template.rs:32:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:32:16 + --> $DIR/bad-template.rs:35:16 | LL | asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:34:15 + --> $DIR/bad-template.rs:37:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:37:15 + --> $DIR/bad-template.rs:40:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:37:21 + --> $DIR/bad-template.rs:40:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:41:15 + --> $DIR/bad-template.rs:44:15 | LL | asm!("{}", in("eax") foo); | ^^ ------------- explicit register argument @@ -77,24 +77,24 @@ LL | asm!("{}", in("eax") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:41:20 + --> $DIR/bad-template.rs:44:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ help: use the register name directly in the assembly code - --> $DIR/bad-template.rs:41:20 + --> $DIR/bad-template.rs:44:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:17 + --> $DIR/bad-template.rs:49:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:49:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -104,7 +104,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:55:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -112,7 +112,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:57:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -120,7 +120,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:57:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -128,13 +128,13 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:60:15 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:62:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -143,13 +143,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -157,7 +157,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:65:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -165,7 +165,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:65:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -173,13 +173,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:68:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:70:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -189,7 +189,7 @@ LL | global_asm!("", const FOO, const FOO); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` warning: formatting may not be suitable for sub-register argument - --> $DIR/bad-template.rs:46:15 + --> $DIR/bad-template.rs:49:15 | LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 2f3716ca77f65..b18d01730f299 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -81,13 +81,15 @@ pub extern "C" fn missing_assembly() { #[naked] pub extern "C" fn too_many_asm_blocks() { //~^ ERROR naked functions must contain a single asm block - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!("", options(noreturn)); + unsafe { + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!("", options(noreturn)); + } } pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index f90967fbe6e43..6613c3dfdbafb 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -1,23 +1,23 @@ error: asm with the `pure` option must have at least one output - --> $DIR/naked-functions.rs:111:14 + --> $DIR/naked-functions.rs:113:14 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:203:5 + --> $DIR/naked-functions.rs:205:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:209:5 + --> $DIR/naked-functions.rs:211:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:216:10 + --> $DIR/naked-functions.rs:218:10 | LL | asm!(invalid_syntax) | ^^^^^^^^^^^^^^ @@ -142,37 +142,37 @@ LL | pub extern "C" fn missing_assembly() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:84:5 + --> $DIR/naked-functions.rs:85:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:86:5 + --> $DIR/naked-functions.rs:87:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:88:5 + --> $DIR/naked-functions.rs:89:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: naked functions must contain a single asm block --> $DIR/naked-functions.rs:82:1 @@ -180,17 +180,17 @@ error[E0787]: naked functions must contain a single asm block LL | pub extern "C" fn too_many_asm_blocks() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!("", options(noreturn)); - | --------------------------- multiple asm blocks are unsupported in naked functions +LL | asm!("", options(noreturn)); + | --------------------------- multiple asm blocks are unsupported in naked functions error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:97:11 + --> $DIR/naked-functions.rs:99:11 | LL | *&y | ^ @@ -198,7 +198,7 @@ LL | *&y = help: follow the calling convention in asm block to use parameters error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:95:5 + --> $DIR/naked-functions.rs:97:5 | LL | pub extern "C" fn inner(y: usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,19 +207,19 @@ LL | *&y | --- non-asm is unsupported in naked functions error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags` - --> $DIR/naked-functions.rs:105:5 + --> $DIR/naked-functions.rs:107:5 | LL | asm!("", options(nomem, preserves_flags, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` - --> $DIR/naked-functions.rs:111:5 + --> $DIR/naked-functions.rs:113:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:111:5 + --> $DIR/naked-functions.rs:113:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -230,13 +230,13 @@ LL | asm!("", options(noreturn), options(readonly, nostack), options(pure)); | +++++++++++++++++++ error[E0787]: asm options unsupported in naked functions: `may_unwind` - --> $DIR/naked-functions.rs:119:5 + --> $DIR/naked-functions.rs:121:5 | LL | asm!("", options(noreturn, may_unwind)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:124:1 + --> $DIR/naked-functions.rs:126:1 | LL | pub unsafe fn default_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -244,43 +244,43 @@ LL | pub unsafe fn default_abi() { = note: `#[warn(undefined_naked_function_abi)]` on by default warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:130:1 + --> $DIR/naked-functions.rs:132:1 | LL | pub unsafe fn rust_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:170:1 + --> $DIR/naked-functions.rs:172:1 | LL | #[inline] | ^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:177:1 + --> $DIR/naked-functions.rs:179:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:184:1 + --> $DIR/naked-functions.rs:186:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:191:1 + --> $DIR/naked-functions.rs:193:1 | LL | #[inline] | ^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:193:1 + --> $DIR/naked-functions.rs:195:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:195:1 + --> $DIR/naked-functions.rs:197:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs index f32ca0cccfc91..d5e9a2bde0060 100644 --- a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs +++ b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs @@ -1,4 +1,5 @@ -// run-pass +// check-pass + trait Lattice { const BOTTOM: Self; } diff --git a/tests/ui/associated-consts/associated-const-type-parameters.rs b/tests/ui/associated-consts/associated-const-type-parameters.rs index b62d47458be5e..a233b09ff89c6 100644 --- a/tests/ui/associated-consts/associated-const-type-parameters.rs +++ b/tests/ui/associated-consts/associated-const-type-parameters.rs @@ -27,7 +27,7 @@ fn sub() -> i32 { A::X - B::X } -trait Bar: Foo { +trait Bar: Foo { //~ WARN trait `Bar` is never used const Y: i32 = Self::X; } diff --git a/tests/ui/associated-consts/associated-const-type-parameters.stderr b/tests/ui/associated-consts/associated-const-type-parameters.stderr new file mode 100644 index 0000000000000..6ee2a5de1b6ad --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameters.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/associated-const-type-parameters.rs:30:7 + | +LL | trait Bar: Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs index 285e89cce4985..6c6dae864f340 100644 --- a/tests/ui/associated-consts/issue-105330.rs +++ b/tests/ui/associated-consts/issue-105330.rs @@ -14,5 +14,6 @@ fn foo>() { //~ ERROR E0658 fn main>() { //~^ ERROR E0658 + //~| ERROR E0131 foo::(); } diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr index 452367bed1201..b4c021d0f4fdc 100644 --- a/tests/ui/associated-consts/issue-105330.stderr +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -43,7 +43,13 @@ LL | impl TraitWAssocConst for impl Demo { | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error: aborting due to 5 previous errors +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-105330.rs:15:8 + | +LL | fn main>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters + +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0404, E0562, E0658. -For more information about an error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0131, E0404, E0562, E0658. +For more information about an error, try `rustc --explain E0131`. diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr index 82cbc9ed3b094..6ce995eaab716 100644 --- a/tests/ui/associated-consts/issue-58022.stderr +++ b/tests/ui/associated-consts/issue-58022.stderr @@ -13,7 +13,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | fn new(slice: &[u8; Self::SIZE]) -> Self { | ^^^^ doesn't have a size known at compile-time | - = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]` + = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `Bar<[u8]>: Sized` note: required because it appears within the type `Bar<[u8]>` --> $DIR/issue-58022.rs:8:12 | diff --git a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs index d180de9be3bf3..1c48aadecceb9 100644 --- a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs +++ b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -1,5 +1,4 @@ -// NOTE: rustc cannot currently handle bounds of the form `for<'a> >::Assoc: Baz`. -// This should hopefully be fixed with Chalk. +// check-pass #![feature(associated_type_bounds)] @@ -24,9 +23,6 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { trait Case1 { type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; - //~^ ERROR `<::C as Iterator>::Item` is not an iterator - //~| ERROR `<::C as Iterator>::Item` cannot be sent between threads safely - //~| ERROR `<::C as Iterator>::Item` cannot be shared between threads safely } pub struct S1; @@ -35,33 +31,17 @@ impl Case1 for S1 { } fn assume_case1() { - fn assert_a<_0, A>() - where - A: Iterator, - _0: Debug, - { - } - assert_a::<_, T::A>(); - - fn assert_b<_0, B>() - where - B: Iterator, - _0: 'static, - { - } - assert_b::<_, T::B>(); - - fn assert_c<_0, _1, _2, C>() + fn assert_c<_1, _2, C>() where C: Clone + Iterator, _2: Send + Iterator, - _1: for<'a> Lam<&'a u8, App = _0>, - _0: Debug, + _1: for<'a> Lam<&'a u8>, + for<'a> <_1 as Lam<&'a u8>>::App: Debug, { } - assert_c::<_, _, _, T::C>(); + assert_c::<_, _, T::C>(); } fn main() { - assume_case1(S1); + assume_case1::(); } diff --git a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr deleted file mode 100644 index c23e54594ee30..0000000000000 --- a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0277]: `<::C as Iterator>::Item` cannot be sent between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36 - | -LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; - | ^^^^ `<::C as Iterator>::Item` cannot be sent between threads safely - | - = help: the trait `Send` is not implemented for `<::C as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <::C as Iterator>::Item: Send { - | ++++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: `<::C as Iterator>::Item` is not an iterator - --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:43 - | -LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<::C as Iterator>::Item` is not an iterator - | - = help: the trait `Iterator` is not implemented for `<::C as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <::C as Iterator>::Item: Iterator { - | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: `<::C as Iterator>::Item` cannot be shared between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93 - | -LL | type C: Clone + Iterator Lam<&'a u8, App: Debug>> + Sync>; - | ^^^^ `<::C as Iterator>::Item` cannot be shared between threads safely - | - = help: the trait `Sync` is not implemented for `<::C as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <::C as Iterator>::Item: Sync { - | ++++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs index 23be735010bf3..7bc2970ade9a2 100644 --- a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs +++ b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -1,3 +1,5 @@ +// check-pass + #![feature(associated_type_bounds)] use std::fmt::Debug; @@ -16,8 +18,6 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } trait Case1 { type A: Iterator; - //~^ ERROR `<::A as Iterator>::Item` doesn't implement `Debug` - type B: Iterator; } @@ -33,7 +33,6 @@ impl Case1 for S1 { // bounds of `Out`, but trait selection can't find the bound since it applies // to a type other than `Self::Out`. pub trait Foo { type Out: Baz; } -//~^ ERROR trait bound `<::Out as Baz>::Assoc: Default` is not satisfied pub trait Baz { type Assoc; } #[derive(Default)] diff --git a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr deleted file mode 100644 index 4e2313bd4e4a9..0000000000000 --- a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0277]: `<::A as Iterator>::Item` doesn't implement `Debug` - --> $DIR/bounds-on-assoc-in-trait.rs:18:28 - | -LL | type A: Iterator; - | ^^^^^ `<::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = help: the trait `Debug` is not implemented for `<::A as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <::A as Iterator>::Item: Debug { - | +++++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: the trait bound `<::Out as Baz>::Assoc: Default` is not satisfied - --> $DIR/bounds-on-assoc-in-trait.rs:35:38 - | -LL | pub trait Foo { type Out: Baz; } - | ^^^^^^^ the trait `Default` is not implemented for `<::Out as Baz>::Assoc` - | -help: consider further restricting the associated type - | -LL | pub trait Foo where <::Out as Baz>::Assoc: Default { type Out: Baz; } - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/duplicate.rs b/tests/ui/associated-type-bounds/duplicate.rs index 160b524c881c9..036f8ede1b3b7 100644 --- a/tests/ui/associated-type-bounds/duplicate.rs +++ b/tests/ui/associated-type-bounds/duplicate.rs @@ -251,13 +251,10 @@ where trait TRA1 { type A: Iterator; //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] - //~| ERROR `<::A as Iterator>::Item` cannot be sent between threads safely - //~| ERROR the trait bound `<::A as Iterator>::Item: Copy` is not satisfied } trait TRA2 { type A: Iterator; //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] - //~| ERROR the trait bound `<::A as Iterator>::Item: Copy` is not satisfied } trait TRA3 { type A: Iterator; diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr index accb366dd1552..bf6aab96dc726 100644 --- a/tests/ui/associated-type-bounds/duplicate.stderr +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -7,7 +7,7 @@ LL | struct SI1> { | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:267:40 + --> $DIR/duplicate.rs:264:40 | LL | type TADyn1 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -15,7 +15,7 @@ LL | type TADyn1 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:269:44 + --> $DIR/duplicate.rs:266:44 | LL | type TADyn2 = Box>; | ---------- ^^^^^^^^^^ re-bound here @@ -23,7 +23,7 @@ LL | type TADyn2 = Box>; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:271:43 + --> $DIR/duplicate.rs:268:43 | LL | type TADyn3 = dyn Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -523,7 +523,7 @@ LL | type A: Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:258:34 + --> $DIR/duplicate.rs:256:34 | LL | type A: Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -531,7 +531,7 @@ LL | type A: Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:263:37 + --> $DIR/duplicate.rs:260:37 | LL | type A: Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -631,41 +631,7 @@ LL | Self: Iterator, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied - --> $DIR/duplicate.rs:252:28 - | -LL | type A: Iterator; - | ^^^^ the trait `Copy` is not implemented for `<::A as Iterator>::Item` - | -help: consider further restricting the associated type - | -LL | trait TRA1 where <::A as Iterator>::Item: Copy { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: `<::A as Iterator>::Item` cannot be sent between threads safely - --> $DIR/duplicate.rs:252:40 - | -LL | type A: Iterator; - | ^^^^ `<::A as Iterator>::Item` cannot be sent between threads safely - | - = help: the trait `Send` is not implemented for `<::A as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait TRA1 where <::A as Iterator>::Item: Send { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied - --> $DIR/duplicate.rs:258:28 - | -LL | type A: Iterator; - | ^^^^ the trait `Copy` is not implemented for `<::A as Iterator>::Item` - | -help: consider further restricting the associated type - | -LL | trait TRA2 where <::A as Iterator>::Item: Copy { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 78 previous errors +error: aborting due to 75 previous errors -Some errors have detailed explanations: E0277, E0282, E0719. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0282, E0719. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs index a3f4717791abd..079c44b3a598d 100644 --- a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs @@ -5,7 +5,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy(x: T) { let _x = x; let _x = x; } fn assert_static(_: T) {} diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr new file mode 100644 index 0000000000000..2e26a434f5d34 --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/dyn-impl-trait-type.rs:8:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs index 52199124ea3b5..49e5e72f225e2 100644 --- a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs @@ -7,7 +7,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy(x: T) { let _x = x; let _x = x; } fn assert_static(_: T) {} diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr new file mode 100644 index 0000000000000..9eddbe462847d --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/dyn-rpit-and-let.rs:10:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/higher-ranked.rs b/tests/ui/associated-type-bounds/higher-ranked.rs new file mode 100644 index 0000000000000..2bd5f316811d9 --- /dev/null +++ b/tests/ui/associated-type-bounds/higher-ranked.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait A<'a> { + type Assoc: ?Sized; +} + +impl<'a> A<'a> for () { + type Assoc = &'a (); +} + +fn hello() -> impl for<'a> A<'a, Assoc: Sized> { + () +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/nested-bounds-dont-eliminate-alias-bounds.rs b/tests/ui/associated-type-bounds/nested-bounds-dont-eliminate-alias-bounds.rs new file mode 100644 index 0000000000000..05e4e323d879d --- /dev/null +++ b/tests/ui/associated-type-bounds/nested-bounds-dont-eliminate-alias-bounds.rs @@ -0,0 +1,37 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait Trait1 { + type Assoc1: Bar; + + fn assoc(self) -> Self::Assoc1; +} + +impl Trait1 for () { + type Assoc1 = (); + fn assoc(self) {} +} + +trait Foo {} +impl Foo for () {} +trait Bar {} +impl Bar for () {} + +fn hello() -> impl Trait1 { + () +} + +fn world() { + // Tests that `Assoc1: Foo` bound in the RPIT doesn't disqualify + // the `Assoc1: Bar` bound in the item, as a nested RPIT desugaring + // would do. + + fn is_foo(_: impl Foo) {} + is_foo(hello().assoc()); + + fn is_bar(_: impl Bar) {} + is_bar(hello().assoc()); +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr index f576cc9c95f09..dde7036231e21 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr @@ -13,7 +13,7 @@ error: future cannot be sent between threads safely LL | is_send(foo::()); | ^^^^^^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future>`, the trait `Send` is not implemented for `impl Future> { ::method() }` + = help: within `impl Future>`, the trait `Send` is not implemented for `impl Future> { ::method() }`, which is required by `impl Future>: Send` note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/basic.rs:13:5 | diff --git a/tests/ui/associated-type-bounds/rpit.rs b/tests/ui/associated-type-bounds/rpit.rs index 59c7733fbe4ba..557e63b5f71fa 100644 --- a/tests/ui/associated-type-bounds/rpit.rs +++ b/tests/ui/associated-type-bounds/rpit.rs @@ -5,7 +5,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy(x: T) { let _x = x; let _x = x; } fn assert_static(_: T) {} diff --git a/tests/ui/associated-type-bounds/rpit.stderr b/tests/ui/associated-type-bounds/rpit.stderr new file mode 100644 index 0000000000000..76bd75bd2cab3 --- /dev/null +++ b/tests/ui/associated-type-bounds/rpit.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/rpit.rs:8:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed index b9f26a40219b5..128c7dfdda2ed 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait O { type M; } diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs index abff6af73e24b..6b6478419b4c0 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait O { type M; } diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr index 7ca9aff432279..21bc37bb3ea2d 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 + --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:13:21 | LL | const N: C::M = 4u8; | ^^^ expected associated type, found `u8` diff --git a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs index 93a44c01ce053..60088e443f300 100644 --- a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs +++ b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs @@ -1,5 +1,6 @@ // run-pass +#![allow(dead_code)] #![feature(associated_type_bounds)] #![feature(type_alias_impl_trait)] diff --git a/tests/ui/associated-types/associated-types-eq-hr.rs b/tests/ui/associated-types/associated-types-eq-hr.rs index dc653f7f2e9dc..b8a97b5c7dd2c 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.rs +++ b/tests/ui/associated-types/associated-types-eq-hr.rs @@ -94,10 +94,18 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::(); + //~^ ERROR not general enough + //~| ERROR not general enough + //~| ERROR not general enough + //~| ERROR not general enough } pub fn call_tuple_two() { tuple_two::(); + //~^ ERROR not general enough + //~| ERROR not general enough + //~| ERROR mismatched types + //~| ERROR mismatched types } pub fn call_tuple_three() { @@ -106,6 +114,8 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::(); + //~^ ERROR not general enough + //~| ERROR not general enough } fn main() {} diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 3e1142d5d9560..3a70189dd9f94 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -42,6 +42,113 @@ LL | where LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, | ^^^^^^^^^^^^^ required by this bound in `bar` -error: aborting due to 2 previous errors +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&'x _` + found reference `&'y _` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::(); + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&'x _` + found reference `&'y _` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:116:5 + | +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:116:5 + | +LL | tuple_four::(); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed index 80bbef17469db..adfba994f32dc 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #![allow(unused_variables)] trait Get { diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.rs b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs index 0f6cea8e69fcf..50478171d869a 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.rs +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #![allow(unused_variables)] trait Get { diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr index 17941b6bf1eef..27014fa53d8a2 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:40 + --> $DIR/associated-types-for-unimpl-trait.rs:11:40 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` diff --git a/tests/ui/associated-types/associated-types-in-bound-type-arg.rs b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs index 88bb5fe0afeab..05e66a168d9cf 100644 --- a/tests/ui/associated-types/associated-types-in-bound-type-arg.rs +++ b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test the case where we resolve `C::Result` and the trait bound // itself includes a `Self::Item` shorthand. // diff --git a/tests/ui/associated-types/associated-types-issue-20220.rs b/tests/ui/associated-types/associated-types-issue-20220.rs index 19fa7a6085a56..89efce198340f 100644 --- a/tests/ui/associated-types/associated-types-issue-20220.rs +++ b/tests/ui/associated-types/associated-types-issue-20220.rs @@ -4,7 +4,7 @@ use std::vec; -trait IntoIteratorX { +trait IntoIteratorX { //~ WARN trait `IntoIteratorX` is never used type Item; type IntoIter: Iterator; diff --git a/tests/ui/associated-types/associated-types-issue-20220.stderr b/tests/ui/associated-types/associated-types-issue-20220.stderr new file mode 100644 index 0000000000000..c682f46e1409b --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-20220.stderr @@ -0,0 +1,10 @@ +warning: trait `IntoIteratorX` is never used + --> $DIR/associated-types-issue-20220.rs:7:7 + | +LL | trait IntoIteratorX { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-issue-20371.rs b/tests/ui/associated-types/associated-types-issue-20371.rs index ae8a8767d2746..cbec83d45b29d 100644 --- a/tests/ui/associated-types/associated-types-issue-20371.rs +++ b/tests/ui/associated-types/associated-types-issue-20371.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that we are able to have an impl that defines an associated type // before the actual trait. diff --git a/tests/ui/associated-types/associated-types-nested-projections.rs b/tests/ui/associated-types/associated-types-nested-projections.rs index 76ba7496250cc..440f35c8bdef4 100644 --- a/tests/ui/associated-types/associated-types-nested-projections.rs +++ b/tests/ui/associated-types/associated-types-nested-projections.rs @@ -13,7 +13,7 @@ impl<'a> Bound for &'a i32 {} trait IntoIterator { type Iter: Iterator; - fn into_iter(self) -> Self::Iter; + fn into_iter(self) -> Self::Iter; //~ WARN method `into_iter` is never used } impl<'a, T> IntoIterator for &'a [T; 3] { diff --git a/tests/ui/associated-types/associated-types-nested-projections.stderr b/tests/ui/associated-types/associated-types-nested-projections.stderr new file mode 100644 index 0000000000000..97d5a7585736c --- /dev/null +++ b/tests/ui/associated-types/associated-types-nested-projections.stderr @@ -0,0 +1,13 @@ +warning: method `into_iter` is never used + --> $DIR/associated-types-nested-projections.rs:16:8 + | +LL | trait IntoIterator { + | ------------ method in this trait +... +LL | fn into_iter(self) -> Self::Iter; + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs index e09aa3663c6e5..6612598b1b8b4 100644 --- a/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs index dcfae0f37e1da..df0a82ee7ceb0 100644 --- a/tests/ui/associated-types/associated-types-normalize-in-bounds.rs +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. diff --git a/tests/ui/associated-types/associated-types-path-2.rs b/tests/ui/associated-types/associated-types-path-2.rs index 00066efccb8dd..c993e1d27202d 100644 --- a/tests/ui/associated-types/associated-types-path-2.rs +++ b/tests/ui/associated-types/associated-types-path-2.rs @@ -29,14 +29,12 @@ pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR `u32: Foo` is not satisfied //~| ERROR `u32: Foo` is not satisfied - //~| ERROR `u32: Foo` is not satisfied } pub fn f1_uint_int() { f1(2u32, 4i32); //~^ ERROR `u32: Foo` is not satisfied //~| ERROR `u32: Foo` is not satisfied - //~| ERROR `u32: Foo` is not satisfied } pub fn f2_int() { diff --git a/tests/ui/associated-types/associated-types-path-2.stderr b/tests/ui/associated-types/associated-types-path-2.stderr index 206f490241026..5edd5c864e135 100644 --- a/tests/ui/associated-types/associated-types-path-2.stderr +++ b/tests/ui/associated-types/associated-types-path-2.stderr @@ -31,14 +31,6 @@ note: required by a bound in `f1` LL | pub fn f1(a: T, x: T::A) {} | ^^^ required by this bound in `f1` -error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:29:5 - | -LL | f1(2u32, 4u32); - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32` - | - = help: the trait `Foo` is implemented for `i32` - error[E0277]: the trait bound `u32: Foo` is not satisfied --> $DIR/associated-types-path-2.rs:29:14 | @@ -48,7 +40,7 @@ LL | f1(2u32, 4u32); = help: the trait `Foo` is implemented for `i32` error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:36:8 + --> $DIR/associated-types-path-2.rs:35:8 | LL | f1(2u32, 4i32); | -- ^^^^ the trait `Foo` is not implemented for `u32` @@ -63,15 +55,7 @@ LL | pub fn f1(a: T, x: T::A) {} | ^^^ required by this bound in `f1` error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:36:5 - | -LL | f1(2u32, 4i32); - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32` - | - = help: the trait `Foo` is implemented for `i32` - -error[E0277]: the trait bound `u32: Foo` is not satisfied - --> $DIR/associated-types-path-2.rs:36:14 + --> $DIR/associated-types-path-2.rs:35:14 | LL | f1(2u32, 4i32); | ^^^^ the trait `Foo` is not implemented for `u32` @@ -79,7 +63,7 @@ LL | f1(2u32, 4i32); = help: the trait `Foo` is implemented for `i32` error[E0308]: mismatched types - --> $DIR/associated-types-path-2.rs:43:18 + --> $DIR/associated-types-path-2.rs:41:18 | LL | let _: i32 = f2(2i32); | --- ^^^^^^^^ expected `i32`, found `u32` @@ -91,7 +75,7 @@ help: you can convert a `u32` to an `i32` and panic if the converted value doesn LL | let _: i32 = f2(2i32).try_into().unwrap(); | ++++++++++++++++++++ -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs index 107e6b4ce0ca0..e99d0112ec4fd 100644 --- a/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs +++ b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we correctly handle projection bounds appearing in the // supertrait list (and in conjunction with overloaded operators). In diff --git a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs index a59c327be2101..e172c6e5611d3 100644 --- a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs +++ b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs @@ -6,7 +6,7 @@ trait Int { type T; - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } trait NonZero diff --git a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr new file mode 100644 index 0000000000000..c26ed79a026e4 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr @@ -0,0 +1,13 @@ +warning: method `dummy` is never used + --> $DIR/associated-types-projection-from-known-type-in-impl.rs:9:8 + | +LL | trait Int + | --- method in this trait +... +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed index 9bc308465ebdd..01f49d52ee212 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed @@ -2,6 +2,7 @@ // Check that we get an error when you use `::Value` in // the trait definition even if there is no default method. +#![allow(dead_code)] trait Get { type Value; } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs index 549fc8fc618e0..7068a754a12c1 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs @@ -2,6 +2,7 @@ // Check that we get an error when you use `::Value` in // the trait definition even if there is no default method. +#![allow(dead_code)] trait Get { type Value; } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 64a88525af8d4..79200dc3acc24 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:11:40 | LL | fn okay(&self, foo: U, bar: ::Value); | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs index 3b8c8c019e50b..a2d6c9ff5a45b 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Check that we do not get an error when you use `::Value` in // the trait definition if there is no default method and for every impl, // `Self` does implement `Get`. diff --git a/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs index 3c830d37060ab..1768fd1687b4e 100644 --- a/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs +++ b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/associated-types/associated-types-resolve-lifetime.rs b/tests/ui/associated-types/associated-types-resolve-lifetime.rs index 52f2324d72ab7..563d0c1182211 100644 --- a/tests/ui/associated-types/associated-types-resolve-lifetime.rs +++ b/tests/ui/associated-types/associated-types-resolve-lifetime.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Get { diff --git a/tests/ui/associated-types/associated-types-unconstrained.stderr b/tests/ui/associated-types/associated-types-unconstrained.stderr index 4221a064ff9ce..83b7f61fd6964 100644 --- a/tests/ui/associated-types/associated-types-unconstrained.stderr +++ b/tests/ui/associated-types/associated-types-unconstrained.stderr @@ -5,7 +5,7 @@ LL | fn bar() -> isize; | ------------------ `Foo::bar` defined here ... LL | let x: isize = Foo::bar(); - | ^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/associated-types/defaults-suitability.stderr b/tests/ui/associated-types/defaults-suitability.stderr index 0a8ad0f89e212..82b35a4863788 100644 --- a/tests/ui/associated-types/defaults-suitability.stderr +++ b/tests/ui/associated-types/defaults-suitability.stderr @@ -39,7 +39,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/defaults-suitability.rs:28:23 | LL | type Bar: Clone = Vec; - | ^^^^^^ the trait `Clone` is not implemented for `T` + | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `Vec: Clone` | = note: required for `Vec` to implement `Clone` note: required by a bound in `Foo::Bar` @@ -88,7 +88,7 @@ error[E0277]: the trait bound `>::Baz: Clone` is not satisfied --> $DIR/defaults-suitability.rs:65:23 | LL | type Bar: Clone = Vec; - | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` | = note: required for `Vec<>::Baz>` to implement `Clone` note: required by a bound in `Foo2::Bar` @@ -105,7 +105,7 @@ error[E0277]: the trait bound `>::Baz: Clone` is not satisfied --> $DIR/defaults-suitability.rs:74:23 | LL | type Bar: Clone = Vec; - | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz` + | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `>::Baz`, which is required by `Vec<>::Baz>: Clone` | = note: required for `Vec<>::Baz>` to implement `Clone` note: required by a bound in `Foo25::Bar` diff --git a/tests/ui/associated-types/defaults-wf.stderr b/tests/ui/associated-types/defaults-wf.stderr index aeb4e47abcbf7..f0b10189bd8d9 100644 --- a/tests/ui/associated-types/defaults-wf.stderr +++ b/tests/ui/associated-types/defaults-wf.stderr @@ -5,7 +5,7 @@ LL | type Ty = Vec<[u8]>; | ^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/hr-associated-type-bound-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-1.stderr index ab5dc803cdf47..01005b6b22d1f 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-1.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-1.rs:12:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> >::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/hr-associated-type-bound-object.stderr b/tests/ui/associated-types/hr-associated-type-bound-object.stderr index 8c91211b964b4..87a048d0a134c 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-object.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-object.stderr @@ -12,6 +12,10 @@ LL | trait X<'a> LL | where LL | for<'b> >::U: Clone, | ^^^^^ required by this bound in `X` +help: consider further restricting the associated type + | +LL | fn f<'a, T: X<'a> + ?Sized>(x: &>::U) where for<'b> >::U: Clone { + | ++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr index 9e03936422491..0031d205b8426 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-1.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-1.rs:14:14 | LL | type V = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> >::V: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `Y` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr index 1a749007ab674..bb484da6a77b1 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-2.stderr @@ -18,7 +18,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-2.rs:15:14 | LL | type W = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> >::W: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `Z` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr index f8be4ec241052..f4d2f43a9b4d9 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-3.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-3.rs:13:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <(T,) as X<'b, (T,)>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr index 22c4bd68690e3..7f03d1553912d 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-4.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-4.rs:13:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> <(T,) as X<'b, T>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr index aae80a9b2e196..fbbc2f4577243 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-param-5.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-5.rs:26:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> < as Cycle>::Next as X<'b, as Cycle>::Next>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` @@ -18,7 +18,7 @@ error[E0277]: the trait bound `str: Clone` is not satisfied --> $DIR/hr-associated-type-bound-param-5.rs:31:14 | LL | type U = str; - | ^^^ the trait `Clone` is not implemented for `str` + | ^^^ the trait `Clone` is not implemented for `str`, which is required by `for<'b> < as Cycle>::Next as X<'b, as Cycle>::Next>>::U: Clone` | = help: the trait `Clone` is implemented for `String` note: required by a bound in `X` diff --git a/tests/ui/associated-types/impl-wf-cycle-5.fixed b/tests/ui/associated-types/impl-wf-cycle-5.fixed index bff6ca90975d2..2b8f1e0d865ee 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.fixed +++ b/tests/ui/associated-types/impl-wf-cycle-5.fixed @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-5.rs b/tests/ui/associated-types/impl-wf-cycle-5.rs index a822e1fb0081b..e6de292ca5c91 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.rs +++ b/tests/ui/associated-types/impl-wf-cycle-5.rs @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-5.stderr b/tests/ui/associated-types/impl-wf-cycle-5.stderr index 284a50bb9a3be..61edf18b43d97 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-5.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-5.rs:20:1 + --> $DIR/impl-wf-cycle-5.rs:22:1 | LL | / impl Grault for (T,) LL | | @@ -12,7 +12,7 @@ LL | type A = (); | ------ associated type `<(T,) as Grault>::A` is specified here | note: required for `(T,)` to implement `Grault` - --> $DIR/impl-wf-cycle-5.rs:20:9 + --> $DIR/impl-wf-cycle-5.rs:22:9 | LL | impl Grault for (T,) | ^^^^^^ ^^^^ diff --git a/tests/ui/associated-types/impl-wf-cycle-6.fixed b/tests/ui/associated-types/impl-wf-cycle-6.fixed index 73ed64f7ce381..5ddf1faefe088 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.fixed +++ b/tests/ui/associated-types/impl-wf-cycle-6.fixed @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-6.rs b/tests/ui/associated-types/impl-wf-cycle-6.rs index 20d635cac5d6f..28f6deb77ce1f 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.rs +++ b/tests/ui/associated-types/impl-wf-cycle-6.rs @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-6.stderr b/tests/ui/associated-types/impl-wf-cycle-6.stderr index c9b5d8060be68..1c7495033183f 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-6.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-6.rs:20:1 + --> $DIR/impl-wf-cycle-6.rs:22:1 | LL | / impl Grault for (T,) LL | | @@ -11,7 +11,7 @@ LL | type A = (); | ------ associated type `<(T,) as Grault>::A` is specified here | note: required for `(T,)` to implement `Grault` - --> $DIR/impl-wf-cycle-6.rs:20:17 + --> $DIR/impl-wf-cycle-6.rs:22:17 | LL | impl Grault for (T,) | ^^^^^^ ^^^^ diff --git a/tests/ui/associated-types/issue-20005.stderr b/tests/ui/associated-types/issue-20005.stderr index 02470a4424919..f2983383fa623 100644 --- a/tests/ui/associated-types/issue-20005.stderr +++ b/tests/ui/associated-types/issue-20005.stderr @@ -4,11 +4,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | ) -> >::Result where Dst: From { | ^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `From` +note: required by an implicit `Sized` bound in `From` --> $DIR/issue-20005.rs:1:12 | LL | trait From { - | ^^^ required by this bound in `From` + | ^^^ required by the implicit `Sized` requirement on this type parameter in `From` help: consider further restricting `Self` | LL | ) -> >::Result where Dst: From, Self: Sized { diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 0e34f541ea303..50d622c89bb57 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -21,7 +21,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:38:1 | LL | pub enum ColumnInsertValue where - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -45,7 +45,7 @@ LL | | Col: Column, ... | LL | | Default(Col), LL | | } - | |_^ the trait `NotNull` is not implemented for `::SqlType` + | |_^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -63,7 +63,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -82,7 +82,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -102,7 +102,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -117,7 +117,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -133,7 +133,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -153,7 +153,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -172,7 +172,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -192,7 +192,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -207,7 +207,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -223,7 +223,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -239,7 +239,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -255,7 +255,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -271,7 +271,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:23 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^^ the trait `NotNull` is not implemented for `::SqlType`, which is required by `::SqlType: IntoNullable` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 diff --git a/tests/ui/associated-types/issue-43784-associated-type.stderr b/tests/ui/associated-types/issue-43784-associated-type.stderr index 529fc1f119a9c..b2cbe8ee86e56 100644 --- a/tests/ui/associated-types/issue-43784-associated-type.stderr +++ b/tests/ui/associated-types/issue-43784-associated-type.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-43784-associated-type.rs:14:18 | LL | type Assoc = T; - | ^ the trait `Copy` is not implemented for `T` + | ^ the trait `Copy` is not implemented for `T`, which is required by `::Assoc: Partial` | note: required for `::Assoc` to implement `Partial` --> $DIR/issue-43784-associated-type.rs:1:11 diff --git a/tests/ui/associated-types/issue-65774-1.stderr b/tests/ui/associated-types/issue-65774-1.stderr index 9c77a25c4320d..9748a8fbbf491 100644 --- a/tests/ui/associated-types/issue-65774-1.stderr +++ b/tests/ui/associated-types/issue-65774-1.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `T: MyDisplay` is not satisfied --> $DIR/issue-65774-1.rs:44:76 | LL | let closure = |config: &mut ::MpuConfig| writer.my_write(&config); - | ^^^^^^^ the trait `MyDisplay` is not implemented for `T` + | ^^^^^^^ the trait `MyDisplay` is not implemented for `T`, which is required by `&mut T: MyDisplay` | = help: the trait `MyDisplay` is implemented for `&'a mut T` note: required for `&mut T` to implement `MyDisplay` diff --git a/tests/ui/associated-types/substs-ppaux.normal.stderr b/tests/ui/associated-types/substs-ppaux.normal.stderr index 015b22f790f8a..93118616f02c7 100644 --- a/tests/ui/associated-types/substs-ppaux.normal.stderr +++ b/tests/ui/associated-types/substs-ppaux.normal.stderr @@ -76,7 +76,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | >::bar; | ^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `str` + = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>` note: required for `str` to implement `Foo<'_, '_, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/associated-types/substs-ppaux.verbose.stderr b/tests/ui/associated-types/substs-ppaux.verbose.stderr index 484581b10288b..13d3156fb8018 100644 --- a/tests/ui/associated-types/substs-ppaux.verbose.stderr +++ b/tests/ui/associated-types/substs-ppaux.verbose.stderr @@ -76,7 +76,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | >::bar; | ^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `str` + = help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>` note: required for `str` to implement `Foo<'?0, '?1, u8>` --> $DIR/substs-ppaux.rs:11:17 | diff --git a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr index 99a46dedcdce6..8154441411323 100644 --- a/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr +++ b/tests/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | trait ArithmeticOps: Add + Sub + Mul + Div {} | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Add` +note: required by an implicit `Sized` bound in `Add` --> $SRC_DIR/core/src/ops/arith.rs:LL:COL help: consider further restricting `Self` | diff --git a/tests/ui/async-await/async-await-let-else.stderr b/tests/ui/async-await/async-await-let-else.stderr index b360aab6b595f..057906b49a37b 100644 --- a/tests/ui/async-await/async-await-let-else.stderr +++ b/tests/ui/async-await/async-await-let-else.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(foo(Some(true))); | ^^^^^^^^^^^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-await-let-else.rs:8:15 | @@ -29,7 +29,7 @@ LL | is_send(foo2(Some(true))); | | | required by a bound introduced by this call | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: required because it's used within this `async` fn body --> $DIR/async-await-let-else.rs:24:29 | @@ -61,7 +61,7 @@ error: future cannot be sent between threads safely LL | is_send(foo3(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo3` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-await-let-else.rs:30:29 | @@ -81,7 +81,7 @@ error: future cannot be sent between threads safely LL | is_send(foo4(Some(true))); | ^^^^^^^^^^^^^^^^ future returned by `foo4` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-await-let-else.rs:38:15 | diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs index f8ff9186842b8..2a3e382e11868 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -1,10 +1,11 @@ // edition:2018 -// check-pass #![feature(async_closure)] fn foo() -> Box> { let x = 0u32; Box::new((async || x)()) + //~^ ERROR cannot return value referencing local variable `x` + //~| ERROR cannot return value referencing temporary value } fn main() { diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr new file mode 100644 index 0000000000000..be67c78221a7c --- /dev/null +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -0,0 +1,21 @@ +error[E0515]: cannot return value referencing local variable `x` + --> $DIR/async-borrowck-escaping-closure-error.rs:6:5 + | +LL | Box::new((async || x)()) + | ^^^^^^^^^------------^^^ + | | | + | | `x` is borrowed here + | returns a value referencing data owned by the current function + +error[E0515]: cannot return value referencing temporary value + --> $DIR/async-borrowck-escaping-closure-error.rs:6:5 + | +LL | Box::new((async || x)()) + | ^^^^^^^^^------------^^^ + | | | + | | temporary value created here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/async-await/async-closures/arg-mismatch.rs b/tests/ui/async-await/async-closures/arg-mismatch.rs new file mode 100644 index 0000000000000..650e13677bc95 --- /dev/null +++ b/tests/ui/async-await/async-closures/arg-mismatch.rs @@ -0,0 +1,15 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let c = async |x| {}; + c(1i32).await; + c(2usize).await; + //~^ ERROR mismatched types + }); +} diff --git a/tests/ui/async-await/async-closures/arg-mismatch.stderr b/tests/ui/async-await/async-closures/arg-mismatch.stderr new file mode 100644 index 0000000000000..70853ae28156f --- /dev/null +++ b/tests/ui/async-await/async-closures/arg-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/arg-mismatch.rs:12:11 + | +LL | c(2usize).await; + | - ^^^^^^ expected `i32`, found `usize` + | | + | arguments to this function are incorrect + | +note: closure parameter defined here + --> $DIR/arg-mismatch.rs:10:24 + | +LL | let c = async |x| {}; + | ^ +help: change the type of the numeric literal from `usize` to `i32` + | +LL | c(2i32).await; + | ~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs new file mode 100644 index 0000000000000..897def791feac --- /dev/null +++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs @@ -0,0 +1,18 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async || {}; + + async fn needs_async_fn_mut(mut x: impl async FnMut()) { + x().await; + } + needs_async_fn_mut(x).await; + }); +} diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs new file mode 100644 index 0000000000000..0e9b25e6d3043 --- /dev/null +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs @@ -0,0 +1,18 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async || {}; + + async fn needs_async_fn_once(x: impl async FnOnce()) { + x().await; + } + needs_async_fn_once(x).await; + }); +} diff --git a/tests/ui/async-await/async-closures/auxiliary/block-on.rs b/tests/ui/async-await/async-closures/auxiliary/block-on.rs new file mode 100644 index 0000000000000..902e033cfe711 --- /dev/null +++ b/tests/ui/async-await/async-closures/auxiliary/block-on.rs @@ -0,0 +1,20 @@ +// edition: 2021 + +#![feature(async_closure, noop_waker)] + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +pub fn block_on(fut: impl Future) -> T { + let mut fut = pin!(fut); + // Poll loop, just to test the future... + let ctx = &mut Context::from_waker(Waker::noop()); + + loop { + match unsafe { fut.as_mut().poll(ctx) } { + Poll::Pending => {} + Poll::Ready(t) => break t, + } + } +} diff --git a/tests/ui/async-await/async-closures/await-inference-guidance.rs b/tests/ui/async-await/async-closures/await-inference-guidance.rs new file mode 100644 index 0000000000000..3702915cbadd1 --- /dev/null +++ b/tests/ui/async-await/async-closures/await-inference-guidance.rs @@ -0,0 +1,16 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async |x: &str| -> String { x.to_owned() }; + let mut s = x("hello, world").await; + s.truncate(4); + println!("{s}"); + }); +} diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs new file mode 100644 index 0000000000000..26d2ed5a6ef65 --- /dev/null +++ b/tests/ui/async-await/async-closures/brand.rs @@ -0,0 +1,25 @@ +// aux-build:block-on.rs +// edition:2021 +// build-pass + +#![feature(async_closure)] + +extern crate block_on; + +use std::future::Future; +use std::marker::PhantomData; + +struct S; +struct B<'b>(PhantomData<&'b mut &'b mut ()>); + +impl S { + async fn q)>(self, f: F) { + f(B(PhantomData)).await; + } +} + +fn main() { + block_on::block_on(async { + S.q(async |b: B<'_>| { println!("...") }).await; + }); +} diff --git a/tests/ui/async-await/async-closures/def-path.rs b/tests/ui/async-await/async-closures/def-path.rs index 2883a1715b0ac..87e99ddda64b3 100644 --- a/tests/ui/async-await/async-closures/def-path.rs +++ b/tests/ui/async-await/async-closures/def-path.rs @@ -8,7 +8,7 @@ fn main() { //~^ NOTE the expected `async` closure body let () = x(); //~^ ERROR mismatched types - //~| NOTE this expression has type `{static main::{closure#0}::{closure#0} upvar_tys= + //~| NOTE this expression has type `{static main::{closure#0}::{closure#0}< //~| NOTE expected `async` closure body, found `()` - //~| NOTE expected `async` closure body `{static main::{closure#0}::{closure#0} + //~| NOTE expected `async` closure body `{static main::{closure#0}::{closure#0}< } diff --git a/tests/ui/async-await/async-closures/def-path.stderr b/tests/ui/async-await/async-closures/def-path.stderr index 4b37e50aac459..dae45825f370d 100644 --- a/tests/ui/async-await/async-closures/def-path.stderr +++ b/tests/ui/async-await/async-closures/def-path.stderr @@ -5,11 +5,11 @@ LL | let x = async || {}; | -- the expected `async` closure body LL | LL | let () = x(); - | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?7t witness=?8t}` + | ^^ --- this expression has type `{static main::{closure#0}::{closure#0} upvar_tys=?15t witness=?6t}` | | | expected `async` closure body, found `()` | - = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?7t witness=?8t}` + = note: expected `async` closure body `{static main::{closure#0}::{closure#0} upvar_tys=?15t witness=?6t}` found unit type `()` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs new file mode 100644 index 0000000000000..a243d20774d27 --- /dev/null +++ b/tests/ui/async-await/async-closures/drop.rs @@ -0,0 +1,38 @@ +// aux-build:block-on.rs +// edition:2018 +// run-pass +// check-run-results + +#![feature(async_closure)] +#![allow(unused)] + +extern crate block_on; + +struct DropMe(i32); + +impl Drop for DropMe { + fn drop(&mut self) { + println!("{} was dropped", self.0); + } +} + +async fn call_once(f: impl async FnOnce()) { + println!("before call"); + let fut = Box::pin(f()); + println!("after call"); + drop(fut); + println!("future dropped"); +} + +fn main() { + block_on::block_on(async { + let d = DropMe(42); + let async_closure = async move || { + let d = &d; + println!("called"); + }; + + call_once(async_closure).await; + println!("after"); + }); +} diff --git a/tests/ui/async-await/async-closures/drop.run.stdout b/tests/ui/async-await/async-closures/drop.run.stdout new file mode 100644 index 0000000000000..ab233f491ba65 --- /dev/null +++ b/tests/ui/async-await/async-closures/drop.run.stdout @@ -0,0 +1,5 @@ +before call +after call +42 was dropped +future dropped +after diff --git a/tests/ui/async-await/async-closures/higher-ranked-return.rs b/tests/ui/async-await/async-closures/higher-ranked-return.rs new file mode 100644 index 0000000000000..d98779c6ea320 --- /dev/null +++ b/tests/ui/async-await/async-closures/higher-ranked-return.rs @@ -0,0 +1,18 @@ +// aux-build:block-on.rs +// edition:2021 + +// known-bug: unknown +// Borrow checking doesn't like that higher-ranked output... + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async move |x: &str| -> &str { + x + }; + let s = x("hello!").await; + }); +} diff --git a/tests/ui/async-await/async-closures/higher-ranked-return.stderr b/tests/ui/async-await/async-closures/higher-ranked-return.stderr new file mode 100644 index 0000000000000..268631f67cddf --- /dev/null +++ b/tests/ui/async-await/async-closures/higher-ranked-return.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/higher-ranked-return.rs:13:46 + | +LL | let x = async move |x: &str| -> &str { + | ________________________________-________----_^ + | | | | + | | | return type of async closure `{async closure body@$DIR/higher-ranked-return.rs:13:46: 15:10}` contains a lifetime `'2` + | | let's call the lifetime of this reference `'1` +LL | | x +LL | | }; + | |_________^ returning this value requires that `'1` must outlive `'2` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-closures/higher-ranked.rs b/tests/ui/async-await/async-closures/higher-ranked.rs index f0bdcf691ae2f..17b5116cceb02 100644 --- a/tests/ui/async-await/async-closures/higher-ranked.rs +++ b/tests/ui/async-await/async-closures/higher-ranked.rs @@ -1,12 +1,16 @@ +// aux-build:block-on.rs // edition:2021 +// build-pass #![feature(async_closure)] +extern crate block_on; + fn main() { - let x = async move |x: &str| { - //~^ ERROR lifetime may not live long enough - // This error is proof that the `&str` type is higher-ranked. - // This won't work until async closures are fully impl'd. - println!("{x}"); - }; + block_on::block_on(async { + let x = async move |x: &str| { + println!("{x}"); + }; + x("hello!").await; + }); } diff --git a/tests/ui/async-await/async-closures/higher-ranked.stderr b/tests/ui/async-await/async-closures/higher-ranked.stderr deleted file mode 100644 index fb02a15b079d7..0000000000000 --- a/tests/ui/async-await/async-closures/higher-ranked.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/higher-ranked.rs:6:34 - | -LL | let x = async move |x: &str| { - | ____________________________-___-_^ - | | | | - | | | return type of closure `{async closure body@$DIR/higher-ranked.rs:6:34: 11:6}` contains a lifetime `'2` - | | let's call the lifetime of this reference `'1` -LL | | -LL | | // This error is proof that the `&str` type is higher-ranked. -LL | | // This won't work until async closures are fully impl'd. -LL | | println!("{x}"); -LL | | }; - | |_____^ returning this value requires that `'1` must outlive `'2` - -error: aborting due to 1 previous error - diff --git a/tests/ui/async-await/async-closures/is-not-fn.rs b/tests/ui/async-await/async-closures/is-not-fn.rs new file mode 100644 index 0000000000000..94c8e8563bd9e --- /dev/null +++ b/tests/ui/async-await/async-closures/is-not-fn.rs @@ -0,0 +1,12 @@ +// edition:2021 + +#![feature(async_closure)] + +fn main() { + fn needs_fn(x: impl FnOnce()) {} + needs_fn(async || {}); + //~^ ERROR expected a `FnOnce()` closure, found `{coroutine-closure@ + // FIXME(async_closures): This should explain in more detail how async fns don't + // implement the regular `Fn` traits. Or maybe we should just fix it and make them + // when there are no upvars or whatever. +} diff --git a/tests/ui/async-await/async-closures/is-not-fn.stderr b/tests/ui/async-await/async-closures/is-not-fn.stderr new file mode 100644 index 0000000000000..12da4b1fc6fb7 --- /dev/null +++ b/tests/ui/async-await/async-closures/is-not-fn.stderr @@ -0,0 +1,19 @@ +error[E0277]: expected a `FnOnce()` closure, found `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` + --> $DIR/is-not-fn.rs:7:14 + | +LL | needs_fn(async || {}); + | -------- ^^^^^^^^^^^ expected an `FnOnce()` closure, found `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce<()>` is not implemented for `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` + = note: wrap the `{coroutine-closure@$DIR/is-not-fn.rs:7:14: 7:22}` in a closure with no arguments: `|| { /* code */ }` +note: required by a bound in `needs_fn` + --> $DIR/is-not-fn.rs:6:25 + | +LL | fn needs_fn(x: impl FnOnce()) {} + | ^^^^^^^^ required by this bound in `needs_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs new file mode 100644 index 0000000000000..9d231d551765e --- /dev/null +++ b/tests/ui/async-await/async-closures/mangle.rs @@ -0,0 +1,35 @@ +// aux-build:block-on.rs +// edition:2021 +// build-pass +// revisions: v0 legacy +//[v0] compile-flags: -Csymbol-mangling-version=v0 +//[legacy] compile-flags: -Csymbol-mangling-version=legacy -Zunstable-options + +// FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. +// ignore-pass (test emits codegen-time warnings) + +#![feature(async_closure, noop_waker)] + +extern crate block_on; + +use std::future::Future; +use std::pin::pin; +use std::task::*; + +async fn call_mut(f: &mut impl async FnMut()) { + f().await; +} + +async fn call_once(f: impl async FnOnce()) { + f().await; +} + +fn main() { + block_on::block_on(async { + let mut async_closure = async move || { + println!("called"); + }; + call_mut(&mut async_closure).await; + call_once(async_closure).await; + }); +} diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.rs b/tests/ui/async-await/async-closures/move-consuming-capture.rs new file mode 100644 index 0000000000000..b8964c571f92e --- /dev/null +++ b/tests/ui/async-await/async-closures/move-consuming-capture.rs @@ -0,0 +1,20 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +struct NoCopy; + +fn main() { + block_on::block_on(async { + let s = NoCopy; + let x = async move || { + drop(s); + }; + x().await; + x().await; + //~^ ERROR use of moved value: `x` + }); +} diff --git a/tests/ui/async-await/async-closures/move-consuming-capture.stderr b/tests/ui/async-await/async-closures/move-consuming-capture.stderr new file mode 100644 index 0000000000000..2c2a0d1162d17 --- /dev/null +++ b/tests/ui/async-await/async-closures/move-consuming-capture.stderr @@ -0,0 +1,17 @@ +error[E0382]: use of moved value: `x` + --> $DIR/move-consuming-capture.rs:17:9 + | +LL | let x = async move || { + | - move occurs because `x` has type `{coroutine-closure@$DIR/move-consuming-capture.rs:13:17: 13:30}`, which does not implement the `Copy` trait +... +LL | x().await; + | --- `x` moved due to this method call +LL | x().await; + | ^ value used here after move + | +note: `async_call_once` takes ownership of the receiver `self`, which moves `x` + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/async-await/async-closures/move-is-async-fn.rs b/tests/ui/async-await/async-closures/move-is-async-fn.rs new file mode 100644 index 0000000000000..943c062954185 --- /dev/null +++ b/tests/ui/async-await/async-closures/move-is-async-fn.rs @@ -0,0 +1,21 @@ +// aux-build:block-on.rs +// edition:2021 +// build-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let s = String::from("hello, world"); + let c = async move || { + println!("{s}"); + }; + c().await; + c().await; + + fn is_static(_: T) {} + is_static(c); + }); +} diff --git a/tests/ui/async-await/async-closures/mutate.rs b/tests/ui/async-await/async-closures/mutate.rs new file mode 100644 index 0000000000000..cc1df5f034ff0 --- /dev/null +++ b/tests/ui/async-await/async-closures/mutate.rs @@ -0,0 +1,19 @@ +// aux-build:block-on.rs +// edition:2021 +// run-pass + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let mut prefix = String::from("Hello"); + let mut c = async move |x: &str| { + prefix.push(','); + println!("{prefix} {x}!") + }; + c("world").await; + c("rust").await; + }); +} diff --git a/tests/ui/async-await/async-closures/not-lending.rs b/tests/ui/async-await/async-closures/not-lending.rs new file mode 100644 index 0000000000000..90832e1a0745d --- /dev/null +++ b/tests/ui/async-await/async-closures/not-lending.rs @@ -0,0 +1,21 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +// Make sure that we can't make an async closure that evaluates to a self-borrow. +// i.e. that the generator may reference captures, but the future's return type can't. + +fn main() { + block_on::block_on(async { + let s = String::new(); + let x = async move || -> &String { &s }; + //~^ ERROR lifetime may not live long enough + + let s = String::new(); + let x = async move || { &s }; + //~^ ERROR lifetime may not live long enough + }); +} diff --git a/tests/ui/async-await/async-closures/not-lending.stderr b/tests/ui/async-await/async-closures/not-lending.stderr new file mode 100644 index 0000000000000..1713e49b551e6 --- /dev/null +++ b/tests/ui/async-await/async-closures/not-lending.stderr @@ -0,0 +1,24 @@ +error: lifetime may not live long enough + --> $DIR/not-lending.rs:14:42 + | +LL | let x = async move || -> &String { &s }; + | ------------------------ ^^^^^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of async closure `{async closure body@$DIR/not-lending.rs:14:42: 14:48}` contains a lifetime `'2` + | lifetime `'1` represents this closure's body + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure + +error: lifetime may not live long enough + --> $DIR/not-lending.rs:18:31 + | +LL | let x = async move || { &s }; + | ------------- ^^^^^^ returning this value requires that `'1` must outlive `'2` + | | | + | | return type of async closure `{async closure body@$DIR/not-lending.rs:18:31: 18:37}` contains a lifetime `'2` + | lifetime `'1` represents this closure's body + | + = note: closure implements `Fn`, so references to captured variables can't escape the closure + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/async-closures/return-type-mismatch.rs b/tests/ui/async-await/async-closures/return-type-mismatch.rs new file mode 100644 index 0000000000000..9ad6be0b6e61e --- /dev/null +++ b/tests/ui/async-await/async-closures/return-type-mismatch.rs @@ -0,0 +1,14 @@ +// aux-build:block-on.rs +// edition:2021 + +#![feature(async_closure)] + +extern crate block_on; + +fn main() { + block_on::block_on(async { + let x = async || -> i32 { 0 }; + let y: usize = x().await; + //~^ ERROR mismatched types + }); +} diff --git a/tests/ui/async-await/async-closures/return-type-mismatch.stderr b/tests/ui/async-await/async-closures/return-type-mismatch.stderr new file mode 100644 index 0000000000000..53841f62777e6 --- /dev/null +++ b/tests/ui/async-await/async-closures/return-type-mismatch.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/return-type-mismatch.rs:11:24 + | +LL | let y: usize = x().await; + | ^^^^^^^^^ expected `usize`, found `i32` + | +help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit + | +LL | let y: usize = x().await.try_into().unwrap(); + | ++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/async-closures/tainted-body.rs b/tests/ui/async-await/async-closures/tainted-body.rs new file mode 100644 index 0000000000000..62c28e7e58576 --- /dev/null +++ b/tests/ui/async-await/async-closures/tainted-body.rs @@ -0,0 +1,13 @@ +// edition:2021 + +#![feature(async_closure)] + +// Don't ICE in ByMove shim builder when MIR body is tainted by writeback errors + +fn main() { + let _ = async || { + used_fn(); + //~^ ERROR cannot find function `used_fn` in this scope + 0 + }; +} diff --git a/tests/ui/async-await/async-closures/tainted-body.stderr b/tests/ui/async-await/async-closures/tainted-body.stderr new file mode 100644 index 0000000000000..b06a896b81f52 --- /dev/null +++ b/tests/ui/async-await/async-closures/tainted-body.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `used_fn` in this scope + --> $DIR/tainted-body.rs:9:9 + | +LL | used_fn(); + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs new file mode 100644 index 0000000000000..f86cee3e0709e --- /dev/null +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -0,0 +1,16 @@ +// edition:2021 + +// FIXME(async_closures): This needs a better error message! + +#![feature(async_closure)] + +fn main() { + fn needs_async_fn(_: impl async Fn()) {} + + let mut x = 1; + needs_async_fn(async || { + //~^ ERROR i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper + // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. + x += 1; + }); +} diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr new file mode 100644 index 0000000000000..4ef8484cc34cd --- /dev/null +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not satisfied + --> $DIR/wrong-fn-kind.rs:11:20 + | +LL | needs_async_fn(async || { + | _____--------------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. +LL | | x += 1; +LL | | }); + | |_____^ the trait `ops::async_function::internal_implementation_detail::AsyncFnKindHelper` is not implemented for `i16` + | +note: required by a bound in `needs_async_fn` + --> $DIR/wrong-fn-kind.rs:8:31 + | +LL | fn needs_async_fn(_: impl async Fn()) {} + | ^^^^^^^^^^ required by this bound in `needs_async_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/async-fn-nonsend.stderr b/tests/ui/async-await/async-fn-nonsend.stderr index 0ced6c36f4715..8b245281da991 100644 --- a/tests/ui/async-await/async-fn-nonsend.stderr +++ b/tests/ui/async-await/async-fn-nonsend.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(non_send_temporary_in_match()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_send_temporary_in_match` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc<()>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:33:26 | @@ -24,7 +24,7 @@ error: future cannot be sent between threads safely LL | assert_send(non_sync_with_method_call()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write` + = help: within `impl Future`, the trait `Send` is not implemented for `dyn std::fmt::Write`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/async-fn-nonsend.rs:46:15 | diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs new file mode 100644 index 0000000000000..3201fb8dbf309 --- /dev/null +++ b/tests/ui/async-await/async-fn/dyn-pos.rs @@ -0,0 +1,14 @@ +// edition:2018 + +#![feature(async_closure)] + +fn foo(x: &dyn async Fn()) {} +//~^ ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFn` cannot be made into an object +//~| ERROR the trait `AsyncFnMut` cannot be made into an object +//~| ERROR the trait `AsyncFnMut` cannot be made into an object +//~| ERROR the trait `AsyncFnMut` cannot be made into an object + +fn main() {} diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr new file mode 100644 index 0000000000000..c93235265160b --- /dev/null +++ b/tests/ui/async-await/async-fn/dyn-pos.stderr @@ -0,0 +1,87 @@ +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFn` 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 + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + +error[E0038]: the trait `AsyncFnMut` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFnMut` 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 + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFn` 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 + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFnMut` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFnMut` 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 + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFn` 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 + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFnMut` cannot be made into an object + --> $DIR/dyn-pos.rs:5:16 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^ `AsyncFnMut` 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 + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0038]: the trait `AsyncFn` cannot be made into an object + --> $DIR/dyn-pos.rs:5:12 + | +LL | fn foo(x: &dyn async Fn()) {} + | ^^^^^^^^^^^^^^ `AsyncFn` 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 + --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallFuture` + ::: $SRC_DIR/core/src/ops/async_function.rs:LL:COL + | + = note: the trait cannot be made into an object because it contains the generic associated type `CallMutFuture` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs new file mode 100644 index 0000000000000..6436787b665d7 --- /dev/null +++ b/tests/ui/async-await/async-fn/edition-2015-not-async-bound.rs @@ -0,0 +1,10 @@ +// check-pass +// Make sure that we don't eagerly recover `async ::Bound` in edition 2015. + +mod async { + pub trait Foo {} +} + +fn test(x: impl async ::Foo) {} + +fn main() {} diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs new file mode 100644 index 0000000000000..83b9d415ddab4 --- /dev/null +++ b/tests/ui/async-await/async-fn/edition-2015.rs @@ -0,0 +1,7 @@ +fn foo(x: impl async Fn()) -> impl async Fn() { x } +//~^ ERROR `async` trait bounds are only allowed in Rust 2018 or later +//~| ERROR `async` trait bounds are only allowed in Rust 2018 or later +//~| ERROR async closures are unstable +//~| ERROR async closures are unstable + +fn main() {} diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr new file mode 100644 index 0000000000000..0029d53868d4f --- /dev/null +++ b/tests/ui/async-await/async-fn/edition-2015.stderr @@ -0,0 +1,43 @@ +error: `async` trait bounds are only allowed in Rust 2018 or later + --> $DIR/edition-2015.rs:1:16 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: `async` trait bounds are only allowed in Rust 2018 or later + --> $DIR/edition-2015.rs:1:36 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0658]: async closures are unstable + --> $DIR/edition-2015.rs:1:16 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: to use an async block, remove the `||`: `async {` + +error[E0658]: async closures are unstable + --> $DIR/edition-2015.rs:1:36 + | +LL | fn foo(x: impl async Fn()) -> impl async Fn() { x } + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: to use an async block, remove the `||`: `async {` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/async-await/async-fn/impl-header.rs b/tests/ui/async-await/async-fn/impl-header.rs new file mode 100644 index 0000000000000..fb1844384ae08 --- /dev/null +++ b/tests/ui/async-await/async-fn/impl-header.rs @@ -0,0 +1,8 @@ +// edition:2018 + +struct F; + +impl async Fn<()> for F {} +//~^ ERROR expected type, found keyword `async` + +fn main() {} diff --git a/tests/ui/async-await/async-fn/impl-header.stderr b/tests/ui/async-await/async-fn/impl-header.stderr new file mode 100644 index 0000000000000..02cb432624274 --- /dev/null +++ b/tests/ui/async-await/async-fn/impl-header.stderr @@ -0,0 +1,8 @@ +error: expected type, found keyword `async` + --> $DIR/impl-header.rs:5:6 + | +LL | impl async Fn<()> for F {} + | ^^^^^ expected type + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs new file mode 100644 index 0000000000000..97f6696fe1434 --- /dev/null +++ b/tests/ui/async-await/async-fn/impl-trait.rs @@ -0,0 +1,15 @@ +// edition:2018 +// check-pass + +#![feature(async_closure, type_alias_impl_trait)] + +type Tait = impl async Fn(); +fn tait() -> Tait { + || async {} +} + +fn foo(x: impl async Fn()) -> impl async Fn() { x } + +fn param() {} + +fn main() {} diff --git a/tests/ui/async-await/async-fn/method-call-pos.rs b/tests/ui/async-await/async-fn/method-call-pos.rs new file mode 100644 index 0000000000000..aaa0245b9868f --- /dev/null +++ b/tests/ui/async-await/async-fn/method-call-pos.rs @@ -0,0 +1,7 @@ +// edition:2018 + +fn main() { + <_ as async Fn()>(|| async {}); + //~^ ERROR expected identifier, found keyword `async` + //~| ERROR expected one of +} diff --git a/tests/ui/async-await/async-fn/method-call-pos.stderr b/tests/ui/async-await/async-fn/method-call-pos.stderr new file mode 100644 index 0000000000000..527515a1b44cc --- /dev/null +++ b/tests/ui/async-await/async-fn/method-call-pos.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found keyword `async` + --> $DIR/method-call-pos.rs:4:11 + | +LL | <_ as async Fn()>(|| async {}); + | ^^^^^ expected identifier, found keyword + +error: expected one of `(`, `::`, `<`, or `>`, found `Fn` + --> $DIR/method-call-pos.rs:4:17 + | +LL | <_ as async Fn()>(|| async {}); + | ^^ expected one of `(`, `::`, `<`, or `>` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/async-fn/not-a-trait.rs b/tests/ui/async-await/async-fn/not-a-trait.rs new file mode 100644 index 0000000000000..a8fa21e556888 --- /dev/null +++ b/tests/ui/async-await/async-fn/not-a-trait.rs @@ -0,0 +1,13 @@ +// edition:2018 + +#![feature(async_closure)] + +struct S; + +fn test(x: impl async S) {} +//~^ ERROR expected trait, found struct `S` + +fn missing(x: impl async Missing) {} +//~^ ERROR cannot find trait `Missing` in this scope + +fn main() {} diff --git a/tests/ui/async-await/async-fn/not-a-trait.stderr b/tests/ui/async-await/async-fn/not-a-trait.stderr new file mode 100644 index 0000000000000..d49f7d7d2fc16 --- /dev/null +++ b/tests/ui/async-await/async-fn/not-a-trait.stderr @@ -0,0 +1,16 @@ +error[E0404]: expected trait, found struct `S` + --> $DIR/not-a-trait.rs:7:23 + | +LL | fn test(x: impl async S) {} + | ^ not a trait + +error[E0405]: cannot find trait `Missing` in this scope + --> $DIR/not-a-trait.rs:10:26 + | +LL | fn missing(x: impl async Missing) {} + | ^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0404, E0405. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/async-await/async-fn/sugar.rs b/tests/ui/async-await/async-fn/sugar.rs new file mode 100644 index 0000000000000..868fb799ae4f9 --- /dev/null +++ b/tests/ui/async-await/async-fn/sugar.rs @@ -0,0 +1,14 @@ +// edition: 2021 +// check-pass + +#![feature(async_closure)] + +async fn foo() {} + +async fn call_asyncly(f: impl async Fn(i32) -> i32) -> i32 { + f(1).await +} + +fn main() { + let fut = call_asyncly(|x| async move { x + 1 }); +} diff --git a/tests/ui/async-await/async-fn/wrong-trait.rs b/tests/ui/async-await/async-fn/wrong-trait.rs new file mode 100644 index 0000000000000..c431a362b1ea9 --- /dev/null +++ b/tests/ui/async-await/async-fn/wrong-trait.rs @@ -0,0 +1,10 @@ +// edition:2018 + +#![feature(async_closure)] + +trait Foo {} + +fn test(x: impl async Foo) {} +//~^ ERROR `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits + +fn main() {} diff --git a/tests/ui/async-await/async-fn/wrong-trait.stderr b/tests/ui/async-await/async-fn/wrong-trait.stderr new file mode 100644 index 0000000000000..b39f5aa623c10 --- /dev/null +++ b/tests/ui/async-await/async-fn/wrong-trait.stderr @@ -0,0 +1,8 @@ +error: `async` bound modifier only allowed on `Fn`/`FnMut`/`FnOnce` traits + --> $DIR/wrong-trait.rs:7:23 + | +LL | fn test(x: impl async Foo) {} + | ^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-is-unwindsafe.stderr b/tests/ui/async-await/async-is-unwindsafe.stderr index 99bce89e8d3bf..5d87fc747682a 100644 --- a/tests/ui/async-await/async-is-unwindsafe.stderr +++ b/tests/ui/async-await/async-is-unwindsafe.stderr @@ -1,19 +1,21 @@ error[E0277]: the type `&mut Context<'_>` may not be safely transferred across an unwind boundary --> $DIR/async-is-unwindsafe.rs:12:5 | -LL | is_unwindsafe(async { - | _____^^^^^^^^^^^^^_- - | | | - | | `&mut Context<'_>` may not be safely transferred across an unwind boundary -LL | | -LL | | use std::ptr::null; -LL | | use std::task::{Context, RawWaker, RawWakerVTable, Waker}; -... | -LL | | drop(cx_ref); -LL | | }); - | |_____- within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}` +LL | is_unwindsafe(async { + | _____^_____________- + | |_____| + | || +LL | || +LL | || use std::ptr::null; +LL | || use std::task::{Context, RawWaker, RawWakerVTable, Waker}; +... || +LL | || drop(cx_ref); +LL | || }); + | ||_____-^ `&mut Context<'_>` may not be safely transferred across an unwind boundary + | |_____| + | within this `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}` | - = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>` + = help: within `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}`, the trait `UnwindSafe` is not implemented for `&mut Context<'_>`, which is required by `{async block@$DIR/async-is-unwindsafe.rs:12:19: 29:6}: UnwindSafe` = note: `UnwindSafe` is implemented for `&Context<'_>`, but not for `&mut Context<'_>` note: future does not implement `UnwindSafe` as this value is used across an await --> $DIR/async-is-unwindsafe.rs:25:18 diff --git a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr index 8c9d06c79ca42..eab5bea681cb1 100644 --- a/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr +++ b/tests/ui/async-await/debug-ice-attempted-to-add-with-overflow.stderr @@ -7,7 +7,7 @@ LL | [0usize; 0xffff_ffff_ffff_ffff].await; | |`[usize; usize::MAX]` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `[usize; usize::MAX]` + = help: the trait `Future` is not implemented for `[usize; usize::MAX]`, which is required by `[usize; usize::MAX]: IntoFuture` = note: [usize; usize::MAX] must be a future or must implement `IntoFuture` to be awaited = note: required for `[usize; usize::MAX]` to implement `IntoFuture` diff --git a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr index 721e01062937e..53cdc9b61d32b 100644 --- a/tests/ui/async-await/drop-track-bad-field-in-fru.stderr +++ b/tests/ui/async-await/drop-track-bad-field-in-fru.stderr @@ -15,7 +15,7 @@ LL | None { value: (), ..Default::default() }.await; | |`Option<_>` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `Option<_>` + = help: the trait `Future` is not implemented for `Option<_>`, which is required by `Option<_>: IntoFuture` = note: Option<_> must be a future or must implement `IntoFuture` to be awaited = note: required for `Option<_>` to implement `IntoFuture` diff --git a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr index 9fce4d61b3b6f..ce2cee6ed4735 100644 --- a/tests/ui/async-await/drop-track-field-assign-nonsend.stderr +++ b/tests/ui/async-await/drop-track-field-assign-nonsend.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(agent.handle()); | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/drop-track-field-assign-nonsend.rs:20:39 | diff --git a/tests/ui/async-await/field-assign-nonsend.stderr b/tests/ui/async-await/field-assign-nonsend.stderr index 418a0829c657e..525a2cc78b493 100644 --- a/tests/ui/async-await/field-assign-nonsend.stderr +++ b/tests/ui/async-await/field-assign-nonsend.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_send(agent.handle()); | ^^^^^^^^^^^^^^ future returned by `handle` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Rc` + = help: within `impl Future`, the trait `Send` is not implemented for `Rc`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/field-assign-nonsend.rs:20:39 | diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs index c5a9841029e38..69871d0dca01d 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -1,15 +1,18 @@ // edition: 2021 +// check-pass use std::future::Future; use std::pin::Pin; -trait MyTrait { +#[allow(async_fn_in_trait)] +pub trait MyTrait { async fn foo(&self) -> i32; } impl MyTrait for i32 { + #[warn(refining_impl_trait)] fn foo(&self) -> Pin + '_>> { - //~^ ERROR method `foo` should be async + //~^ WARN impl trait in impl method signature does not match trait method signature Box::pin(async { *self }) } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index 1462c694e161e..54aba77cc05d0 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -1,11 +1,22 @@ -error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-boxed.rs:11:5 +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/async-example-desugared-boxed.rs:14:22 | LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async + | --------------------------- return type from trait method defined here ... LL | fn foo(&self) -> Pin + '_>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate +note: the lint level is defined here + --> $DIR/async-example-desugared-boxed.rs:13:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ +help: replace the return type so that it matches the trait + | +LL | fn foo(&self) -> impl Future { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 1 previous error +warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs index c287b9a5b847f..c6e8f1ae90607 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -1,13 +1,15 @@ // edition: 2021 +// check-pass use std::future::Future; use std::task::Poll; -trait MyTrait { +#[allow(async_fn_in_trait)] +pub trait MyTrait { async fn foo(&self) -> i32; } -struct MyFuture; +pub struct MyFuture; impl Future for MyFuture { type Output = i32; fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll { @@ -16,8 +18,9 @@ impl Future for MyFuture { } impl MyTrait for u32 { + #[warn(refining_impl_trait)] fn foo(&self) -> MyFuture { - //~^ ERROR method `foo` should be async + //~^ WARN impl trait in impl method signature does not match trait method signature MyFuture } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index a2f1060e36fc4..d94afd92c5691 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -1,11 +1,22 @@ -error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-manual.rs:19:5 +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/async-example-desugared-manual.rs:22:22 | LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async + | --------------------------- return type from trait method defined here ... LL | fn foo(&self) -> MyFuture { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate +note: the lint level is defined here + --> $DIR/async-example-desugared-manual.rs:21:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ +help: replace the return type so that it matches the trait + | +LL | fn foo(&self) -> impl Future { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 1 previous error +warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/auxiliary/bad-region.rs b/tests/ui/async-await/in-trait/auxiliary/bad-region.rs new file mode 100644 index 0000000000000..02dc25aaa16bb --- /dev/null +++ b/tests/ui/async-await/in-trait/auxiliary/bad-region.rs @@ -0,0 +1,7 @@ +// edition:2021 + +#[allow(async_fn_in_trait)] + +pub trait BleRadio<'a> { + async fn transmit(&mut self); +} diff --git a/tests/ui/async-await/in-trait/bad-region.rs b/tests/ui/async-await/in-trait/bad-region.rs new file mode 100644 index 0000000000000..444368e21a497 --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-region.rs @@ -0,0 +1,17 @@ +// aux-build:bad-region.rs +// edition:2021 + +#![allow(async_fn_in_trait)] + +extern crate bad_region as jewel; + +use jewel::BleRadio; + +pub struct Radio {} + +impl BleRadio for Radio { +//~^ ERROR implicit elided lifetime not allowed here + async fn transmit(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/bad-region.stderr b/tests/ui/async-await/in-trait/bad-region.stderr new file mode 100644 index 0000000000000..9203fd790af78 --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-region.stderr @@ -0,0 +1,14 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/bad-region.rs:12:6 + | +LL | impl BleRadio for Radio { + | ^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | impl BleRadio<'_> for Radio { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/async-await/in-trait/coherence-constrained.rs b/tests/ui/async-await/in-trait/coherence-constrained.rs index 8e62b3e0e90bf..82c8724ca3e61 100644 --- a/tests/ui/async-await/in-trait/coherence-constrained.rs +++ b/tests/ui/async-await/in-trait/coherence-constrained.rs @@ -12,7 +12,6 @@ impl Foo for Bar { type T = (); async fn foo(&self) {} - //~^ ERROR type annotations needed: cannot satisfy `::T == ()` } impl Foo for Bar { @@ -20,7 +19,6 @@ impl Foo for Bar { type T = (); async fn foo(&self) {} - //~^ ERROR type annotations needed: cannot satisfy `::T == ()` } fn main() {} diff --git a/tests/ui/async-await/in-trait/coherence-constrained.stderr b/tests/ui/async-await/in-trait/coherence-constrained.stderr index 570a357ca8fb7..5c48a1fe98fc5 100644 --- a/tests/ui/async-await/in-trait/coherence-constrained.stderr +++ b/tests/ui/async-await/in-trait/coherence-constrained.stderr @@ -1,17 +1,5 @@ -error[E0284]: type annotations needed: cannot satisfy `::T == ()` - --> $DIR/coherence-constrained.rs:14:5 - | -LL | async fn foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^ cannot satisfy `::T == ()` - -error[E0284]: type annotations needed: cannot satisfy `::T == ()` - --> $DIR/coherence-constrained.rs:22:5 - | -LL | async fn foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^ cannot satisfy `::T == ()` - error[E0119]: conflicting implementations of trait `Foo` for type `Bar` - --> $DIR/coherence-constrained.rs:18:1 + --> $DIR/coherence-constrained.rs:17:1 | LL | impl Foo for Bar { | ---------------- first implementation here @@ -19,7 +7,6 @@ LL | impl Foo for Bar { LL | impl Foo for Bar { | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar` -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0284. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs index 60077a7e00cc8..ecd5737cf3c23 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs @@ -8,7 +8,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> i32 { - //~^ ERROR: method `foo` should be async + //~^ ERROR: method should be `async` or return a future, but it is synchronous *self } } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr index f75ccb65d1509..8260cd5271ee9 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -1,11 +1,14 @@ -error: method `foo` should be async because the method from the trait is async +error: method should be `async` or return a future, but it is synchronous --> $DIR/fn-not-async-err.rs:10:5 | -LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async -... LL | fn foo(&self) -> i32 { | ^^^^^^^^^^^^^^^^^^^^ + | +note: this method is `async` so it expects a future to be returned + --> $DIR/fn-not-async-err.rs:6:5 + | +LL | async fn foo(&self) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr index aeabb5931dfc7..93f37a9a8e904 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.stderr +++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | assert_is_send(test::()); | ^^^^^^^^^^^ future returned by `test` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `impl Future` + = help: within `impl Future`, the trait `Send` is not implemented for `impl Future`, which is required by `impl Future: Send` note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/missing-send-bound.rs:9:5 | diff --git a/tests/ui/async-await/issue-101715.stderr b/tests/ui/async-await/issue-101715.stderr index f6af15c00d621..3b429793b786f 100644 --- a/tests/ui/async-await/issue-101715.stderr +++ b/tests/ui/async-await/issue-101715.stderr @@ -7,7 +7,7 @@ LL | .await | |`()` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` diff --git a/tests/ui/async-await/issue-64130-1-sync.stderr b/tests/ui/async-await/issue-64130-1-sync.stderr index 5428d7ef71b30..15f49124f6fa0 100644 --- a/tests/ui/async-await/issue-64130-1-sync.stderr +++ b/tests/ui/async-await/issue-64130-1-sync.stderr @@ -4,7 +4,7 @@ error: future cannot be shared between threads safely LL | is_sync(bar()); | ^^^^^ future returned by `bar` is not `Sync` | - = help: within `impl Future`, the trait `Sync` is not implemented for `Foo` + = help: within `impl Future`, the trait `Sync` is not implemented for `Foo`, which is required by `impl Future: Sync` note: future is not `Sync` as this value is used across an await --> $DIR/issue-64130-1-sync.rs:15:11 | diff --git a/tests/ui/async-await/issue-64130-2-send.stderr b/tests/ui/async-await/issue-64130-2-send.stderr index f05e954d2d714..67368314b1b77 100644 --- a/tests/ui/async-await/issue-64130-2-send.stderr +++ b/tests/ui/async-await/issue-64130-2-send.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(bar()); | ^^^^^ future returned by `bar` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `Foo` + = help: within `impl Future`, the trait `Send` is not implemented for `Foo`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-2-send.rs:15:11 | diff --git a/tests/ui/async-await/issue-64130-3-other.stderr b/tests/ui/async-await/issue-64130-3-other.stderr index 3ac30bdc23e63..e3a73920c921a 100644 --- a/tests/ui/async-await/issue-64130-3-other.stderr +++ b/tests/ui/async-await/issue-64130-3-other.stderr @@ -5,7 +5,7 @@ LL | async fn bar() { | -------------- within this `impl Future` ... LL | is_qux(bar()); - | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo` + | ^^^^^ within `impl Future`, the trait `Qux` is not implemented for `Foo`, which is required by `impl Future: Qux` | note: future does not implement `Qux` as this value is used across an await --> $DIR/issue-64130-3-other.rs:18:11 diff --git a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr index d28807e223bef..bd890c838179e 100644 --- a/tests/ui/async-await/issue-64130-non-send-future-diags.stderr +++ b/tests/ui/async-await/issue-64130-non-send-future-diags.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | is_send(foo()); | ^^^^^ future returned by `foo` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-64130-non-send-future-diags.rs:17:11 | diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr similarity index 100% rename from tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr rename to tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr similarity index 100% rename from tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr rename to tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.rs b/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs similarity index 100% rename from tests/ui/issues/issue-65634-raw-ident-suggestion.rs rename to tests/ui/async-await/issue-65634-raw-ident-suggestion.rs diff --git a/tests/ui/async-await/issue-67252-unnamed-future.stderr b/tests/ui/async-await/issue-67252-unnamed-future.stderr index e1c5a22967e08..51c06b9c8afef 100644 --- a/tests/ui/async-await/issue-67252-unnamed-future.stderr +++ b/tests/ui/async-await/issue-67252-unnamed-future.stderr @@ -1,10 +1,14 @@ error: future cannot be sent between threads safely --> $DIR/issue-67252-unnamed-future.rs:18:5 | -LL | spawn(async { - | ^^^^^ future created by async block is not `Send` +LL | / spawn(async { +LL | | let a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send` +LL | | AFuture.await; +LL | | let _a = a; +LL | | }); + | |______^ future created by async block is not `Send` | - = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}`, the trait `Send` is not implemented for `*mut ()` + = help: within `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-67252-unnamed-future.rs:18:11: 22:6}: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-67252-unnamed-future.rs:20:17 | diff --git a/tests/ui/async-await/issue-68112.stderr b/tests/ui/async-await/issue-68112.stderr index 1cd8beac26035..f92ac5dd0bc56 100644 --- a/tests/ui/async-await/issue-68112.stderr +++ b/tests/ui/async-await/issue-68112.stderr @@ -2,9 +2,9 @@ error: future cannot be sent between threads safely --> $DIR/issue-68112.rs:34:5 | LL | require_send(send_fut); - | ^^^^^^^^^^^^ future created by async block is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{async block@$DIR/issue-68112.rs:29:20: 33:6}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:31:17 @@ -21,9 +21,9 @@ error: future cannot be sent between threads safely --> $DIR/issue-68112.rs:43:5 | LL | require_send(send_fut); - | ^^^^^^^^^^^^ future created by async block is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{async block@$DIR/issue-68112.rs:39:20: 42:6}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: future is not `Send` as it awaits another future which is not `Send` --> $DIR/issue-68112.rs:40:17 @@ -40,9 +40,9 @@ error[E0277]: `RefCell` cannot be shared between threads safely --> $DIR/issue-68112.rs:62:5 | LL | require_send(send_fut); - | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{async block@$DIR/issue-68112.rs:57:20: 61:6}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this `async` fn body diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index 4af73739584cb..81f6961840c14 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -14,6 +14,7 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { fn foo(x: NotSync) -> impl Future + Send { //~^ ERROR `*mut ()` cannot be shared between threads safely + //~| ERROR `*mut ()` cannot be shared between threads safely async move { baz(|| async { foo(x.clone()); diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 14ef1cbb67c50..8dc3f476ec8dd 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -4,7 +4,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely LL | fn foo(x: NotSync) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely | - = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send` note: required because it appears within the type `PhantomData<*mut ()>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `NotSync` @@ -14,7 +14,7 @@ LL | struct NotSync(PhantomData<*mut ()>); | ^^^^^^^ = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:18:13 + --> $DIR/issue-70935-complex-spans.rs:19:13 | LL | baz(|| async { | ^^ @@ -27,7 +27,7 @@ LL | | } | |_^ = note: required because it captures the following types: `impl Future` note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:17:5 + --> $DIR/issue-70935-complex-spans.rs:18:5 | LL | / async move { LL | | baz(|| async { @@ -36,6 +36,45 @@ LL | | }).await; LL | | } | |_____^ -error: aborting due to 1 previous error +error[E0277]: `*mut ()` cannot be shared between threads safely + --> $DIR/issue-70935-complex-spans.rs:15:23 + | +LL | fn foo(x: NotSync) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely + | + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send` +note: required because it appears within the type `PhantomData<*mut ()>` + --> $SRC_DIR/core/src/marker.rs:LL:COL +note: required because it appears within the type `NotSync` + --> $DIR/issue-70935-complex-spans.rs:9:8 + | +LL | struct NotSync(PhantomData<*mut ()>); + | ^^^^^^^ + = note: required for `&NotSync` to implement `Send` +note: required because it's used within this closure + --> $DIR/issue-70935-complex-spans.rs:19:13 + | +LL | baz(|| async { + | ^^ +note: required because it's used within this `async` fn body + --> $DIR/issue-70935-complex-spans.rs:12:67 + | +LL | async fn baz(_c: impl FnMut() -> T) where T: Future { + | ___________________________________________________________________^ +LL | | } + | |_^ + = note: required because it captures the following types: `impl Future` +note: required because it's used within this `async` block + --> $DIR/issue-70935-complex-spans.rs:18:5 + | +LL | / async move { +LL | | baz(|| async { +LL | | foo(x.clone()); +LL | | }).await; +LL | | } + | |_____^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/issue-71137.stderr b/tests/ui/async-await/issue-71137.stderr index 8739c22a31048..75d72e425f57b 100644 --- a/tests/ui/async-await/issue-71137.stderr +++ b/tests/ui/async-await/issue-71137.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | fake_spawn(wrong_mutex()); | ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`, which is required by `impl Future: Send` note: future is not `Send` as this value is used across an await --> $DIR/issue-71137.rs:14:26 | diff --git a/tests/ui/async-await/issue-72590-type-error-sized.stderr b/tests/ui/async-await/issue-72590-type-error-sized.stderr index 778423578e169..1b822234d80cc 100644 --- a/tests/ui/async-await/issue-72590-type-error-sized.stderr +++ b/tests/ui/async-await/issue-72590-type-error-sized.stderr @@ -16,7 +16,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | async fn frob(self) {} | ^^^^ doesn't have a size known at compile-time | - = help: within `Foo`, the trait `Sized` is not implemented for `str` + = help: within `Foo`, the trait `Sized` is not implemented for `str`, which is required by `Foo: Sized` note: required because it appears within the type `Foo` --> $DIR/issue-72590-type-error-sized.rs:5:8 | diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs index 95683241aba26..904d28fb0a78d 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.rs @@ -12,6 +12,8 @@ pub async fn async_fn(x: &mut i32) -> &i32 { pub fn async_closure(x: &mut i32) -> impl Future { (async move || { + //~^ ERROR lifetime may not live long enough + //~| ERROR temporary value dropped while borrowed let y = &*x; *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed y @@ -20,6 +22,8 @@ pub fn async_closure(x: &mut i32) -> impl Future { pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { (async move || -> &i32 { + //~^ ERROR lifetime may not live long enough + //~| ERROR temporary value dropped while borrowed let y = &*x; *x += 1; //~ ERROR cannot assign to `*x` because it is borrowed y diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr index 628ba1a481893..bdf2820887c8b 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr @@ -11,7 +11,7 @@ LL | y | - returning this value requires that `*x` is borrowed for `'1` error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:16:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:18:9 | LL | let y = &*x; | --- `*x` is borrowed here @@ -22,20 +22,92 @@ LL | y LL | })() | - return type of async closure is &'1 i32 +error: lifetime may not live long enough + --> $DIR/issue-74072-lifetime-name-annotations.rs:14:20 + | +LL | (async move || { + | ______-------------_^ + | | | | + | | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:14:20: 20:6}` contains a lifetime `'2` + | | lifetime `'1` represents this closure's body +LL | | +LL | | +LL | | let y = &*x; +LL | | *x += 1; +LL | | y +LL | | })() + | |_____^ returning this value requires that `'1` must outlive `'2` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure + +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:14:5 + | +LL | pub fn async_closure(x: &mut i32) -> impl Future { + | - let's call the lifetime of this reference `'1` +LL | // (async move || { +LL | || +LL | || +LL | || let y = &*x; +LL | || *x += 1; +LL | || y +LL | || })() + | ||______^_- argument requires that borrow lasts for `'1` + | |_______| + | creates a temporary value which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement + error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:24:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:28:9 | -LL | (async move || -> &i32 { - | - let's call the lifetime of this reference `'1` LL | let y = &*x; | --- `*x` is borrowed here LL | *x += 1; | ^^^^^^^ `*x` is assigned to here but it was already borrowed LL | y | - returning this value requires that `*x` is borrowed for `'1` +LL | })() + | - return type of async closure is &'1 i32 + +error: lifetime may not live long enough + --> $DIR/issue-74072-lifetime-name-annotations.rs:24:28 + | +LL | (async move || -> &i32 { + | ______---------------------_^ + | | | | + | | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:24:28: 30:6}` contains a lifetime `'2` + | | lifetime `'1` represents this closure's body +LL | | +LL | | +LL | | let y = &*x; +LL | | *x += 1; +LL | | y +LL | | })() + | |_____^ returning this value requires that `'1` must outlive `'2` + | + = note: closure implements `FnMut`, so references to captured variables can't escape the closure + +error[E0716]: temporary value dropped while borrowed + --> $DIR/issue-74072-lifetime-name-annotations.rs:24:5 + | +LL | pub fn async_closure_explicit_return_type(x: &mut i32) -> impl Future { + | - let's call the lifetime of this reference `'1` +LL | // (async move || -> &i32 { +LL | || +LL | || +LL | || let y = &*x; +LL | || *x += 1; +LL | || y +LL | || })() + | ||______^_- argument requires that borrow lasts for `'1` + | |_______| + | creates a temporary value which is freed while still in use +LL | } + | - temporary value is freed at the end of this statement error[E0506]: cannot assign to `*x` because it is borrowed - --> $DIR/issue-74072-lifetime-name-annotations.rs:32:9 + --> $DIR/issue-74072-lifetime-name-annotations.rs:36:9 | LL | let y = &*x; | --- `*x` is borrowed here @@ -46,6 +118,7 @@ LL | y LL | } | - return type of async block is &'1 i32 -error: aborting due to 4 previous errors +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0506`. +Some errors have detailed explanations: E0506, E0716. +For more information about an error, try `rustc --explain E0506`. diff --git a/tests/ui/async-await/issues/issue-67893.stderr b/tests/ui/async-await/issues/issue-67893.stderr index 90c1e976dcee6..12bbfc125521d 100644 --- a/tests/ui/async-await/issues/issue-67893.stderr +++ b/tests/ui/async-await/issues/issue-67893.stderr @@ -11,7 +11,7 @@ LL | g(issue_67893::run()) LL | pub async fn run() { | ------------------ within this `impl Future` | - = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` + = help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`, which is required by `impl Future: Send` = note: required because it captures the following types: `Arc>`, `MutexGuard<'_, ()>`, `impl Future` note: required because it's used within this `async` fn body --> $DIR/auxiliary/issue_67893.rs:9:20 diff --git a/tests/ui/async-await/partial-drop-partial-reinit.stderr b/tests/ui/async-await/partial-drop-partial-reinit.stderr index f088b118730aa..a6140c6db8286 100644 --- a/tests/ui/async-await/partial-drop-partial-reinit.stderr +++ b/tests/ui/async-await/partial-drop-partial-reinit.stderr @@ -9,7 +9,7 @@ LL | gimme_send(foo()); LL | async fn foo() { | -------------- within this `impl Future` | - = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` + = help: within `impl Future`, the trait `Send` is not implemented for `NotSend`, which is required by `impl Future: Send` = note: required because it appears within the type `(NotSend,)` = note: required because it captures the following types: `(NotSend,)`, `impl Future` note: required because it's used within this `async` fn body diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr index 8eb671531e792..e22baabc25b53 100644 --- a/tests/ui/async-await/pin-needed-to-poll-2.stderr +++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr @@ -2,7 +2,7 @@ error[E0277]: `PhantomPinned` cannot be unpinned --> $DIR/pin-needed-to-poll-2.rs:43:18 | LL | Pin::new(&mut self.sleep).poll(cx) - | -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned` + | -------- ^^^^^^^^^^^^^^^ within `Sleep`, the trait `Unpin` is not implemented for `PhantomPinned`, which is required by `Sleep: Unpin` | | | required by a bound introduced by this call | diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr index d2db6abe3132c..2e82a3fcdb4c3 100644 --- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12 + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12 | LL | #![feature(return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ @@ -7,29 +7,5 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: `impl Future { <_ as Foo>::bar() }` cannot be sent between threads safely - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:22:11 - | -LL | build(Bar); - | ----- ^^^ `impl Future { <_ as Foo>::bar() }` cannot be sent between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `for<'a> Send` is not implemented for `impl Future { <_ as Foo>::bar() }` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:22:11 - | -LL | build(Bar); - | ------^^^- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant -note: required by a bound in `build` - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:19:39 - | -LL | fn build(_: T) where T: Foo {} - | ^^^^ required by this bound in `build` - -error: aborting due to 1 previous error; 1 warning emitted +warning: 1 warning emitted -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr index 4837815fad4ad..2e82a3fcdb4c3 100644 --- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12 + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12 | LL | #![feature(return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs index 6097c7f1073ed..5341c39a975aa 100644 --- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs @@ -1,11 +1,10 @@ +// check-pass // revisions: current next -//[current] known-bug: #109924 -//[next] check-pass //[next] compile-flags: -Znext-solver // edition:2021 #![feature(return_type_notation)] -//[next]~^ WARN the feature `return_type_notation` is incomplete +//~^ WARN the feature `return_type_notation` is incomplete trait Foo { async fn bar(&self); diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr index 620370a6113a3..8d81957653240 100644 --- a/tests/ui/async-await/unnecessary-await.stderr +++ b/tests/ui/async-await/unnecessary-await.stderr @@ -6,7 +6,7 @@ LL | boo().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` @@ -28,7 +28,7 @@ LL | e!().await; | |`()` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` @@ -44,7 +44,7 @@ LL | $expr.await LL | f!(()); | ------ in this macro invocation | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -58,7 +58,7 @@ LL | for x in [] {}.await | |`()` is not a future | help: remove the `.await` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` diff --git a/tests/ui/auto-traits/auto-trait-validation.fixed b/tests/ui/auto-traits/auto-trait-validation.fixed index da878ac6222bb..e37fed9faabae 100644 --- a/tests/ui/auto-traits/auto-trait-validation.fixed +++ b/tests/ui/auto-traits/auto-trait-validation.fixed @@ -1,4 +1,5 @@ #![feature(auto_traits)] +#![allow(dead_code)] // run-rustfix diff --git a/tests/ui/auto-traits/auto-trait-validation.rs b/tests/ui/auto-traits/auto-trait-validation.rs index d43055e270bd5..e209aa1322081 100644 --- a/tests/ui/auto-traits/auto-trait-validation.rs +++ b/tests/ui/auto-traits/auto-trait-validation.rs @@ -1,4 +1,5 @@ #![feature(auto_traits)] +#![allow(dead_code)] // run-rustfix diff --git a/tests/ui/auto-traits/auto-trait-validation.stderr b/tests/ui/auto-traits/auto-trait-validation.stderr index 89b63d23d4c8e..a6e5ac54869d2 100644 --- a/tests/ui/auto-traits/auto-trait-validation.stderr +++ b/tests/ui/auto-traits/auto-trait-validation.stderr @@ -1,5 +1,5 @@ error[E0567]: auto traits cannot have generic parameters - --> $DIR/auto-trait-validation.rs:5:19 + --> $DIR/auto-trait-validation.rs:6:19 | LL | auto trait Generic {} | -------^^^ help: remove the parameters @@ -7,7 +7,7 @@ LL | auto trait Generic {} | auto trait cannot have generic parameters error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:7:17 + --> $DIR/auto-trait-validation.rs:8:17 | LL | auto trait Bound : Copy {} | -----^^^^^^^ help: remove the super traits or lifetime bounds @@ -15,7 +15,7 @@ LL | auto trait Bound : Copy {} | auto traits cannot have super traits or lifetime bounds error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:9:25 + --> $DIR/auto-trait-validation.rs:10:25 | LL | auto trait LifetimeBound : 'static {} | -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds @@ -23,7 +23,7 @@ LL | auto trait LifetimeBound : 'static {} | auto traits cannot have super traits or lifetime bounds error[E0380]: auto traits cannot have associated items - --> $DIR/auto-trait-validation.rs:11:25 + --> $DIR/auto-trait-validation.rs:12:25 | LL | auto trait MyTrait { fn foo() {} } | ------- ---^^^----- diff --git a/tests/ui/auto-traits/auto-traits.rs b/tests/ui/auto-traits/auto-traits.rs index 6d8e1a52ec129..1e0fbcc1fdf63 100644 --- a/tests/ui/auto-traits/auto-traits.rs +++ b/tests/ui/auto-traits/auto-traits.rs @@ -19,8 +19,8 @@ fn take_auto_unsafe(_: T) {} fn main() { // Parse inside functions. - auto trait AutoInner {} - unsafe auto trait AutoUnsafeInner {} + auto trait AutoInner {} //~ WARN trait `AutoInner` is never used + unsafe auto trait AutoUnsafeInner {} //~ WARN trait `AutoUnsafeInner` is never used take_auto(0); take_auto(AutoBool(true)); diff --git a/tests/ui/auto-traits/auto-traits.stderr b/tests/ui/auto-traits/auto-traits.stderr new file mode 100644 index 0000000000000..34be8d3f67b8d --- /dev/null +++ b/tests/ui/auto-traits/auto-traits.stderr @@ -0,0 +1,16 @@ +warning: trait `AutoInner` is never used + --> $DIR/auto-traits.rs:22:16 + | +LL | auto trait AutoInner {} + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: trait `AutoUnsafeInner` is never used + --> $DIR/auto-traits.rs:23:23 + | +LL | unsafe auto trait AutoUnsafeInner {} + | ^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/auto-traits/issue-83857-ub.stderr b/tests/ui/auto-traits/issue-83857-ub.stderr index 80f9330eb8180..97f1a6032086e 100644 --- a/tests/ui/auto-traits/issue-83857-ub.stderr +++ b/tests/ui/auto-traits/issue-83857-ub.stderr @@ -4,7 +4,7 @@ error[E0277]: `Foo` cannot be sent between threads safely LL | fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `Foo` + = help: the trait `Send` is not implemented for `Foo`, which is required by `Foo: WithAssoc` note: required for `Foo` to implement `WithAssoc` --> $DIR/issue-83857-ub.rs:15:15 | diff --git a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr index e1dae35be006d..ebd3a556e7579 100644 --- a/tests/ui/auto-traits/str-contains-slice-conceptually.stderr +++ b/tests/ui/auto-traits/str-contains-slice-conceptually.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `[u8]: AutoTrait` is not satisfied in `str` --> $DIR/str-contains-slice-conceptually.rs:11:22 | LL | needs_auto_trait::(); - | ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]` + | ^^^ within `str`, the trait `AutoTrait` is not implemented for `[u8]`, which is required by `str: AutoTrait` | = note: `str` is considered to contain a `[u8]` slice for auto trait purposes note: required by a bound in `needs_auto_trait` diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs index 98359ef51b764..c0ed1e00f3b48 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs @@ -6,6 +6,7 @@ auto trait Magic : Sized where Option : Magic {} //~ ERROR E0568 impl Magic for T {} fn copy(x: T) -> (T, T) { (x, x) } +//~^ ERROR: use of moved value #[derive(Debug)] struct NoClone; diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 547b4bb54489d..dcf1c02bceefa 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -14,6 +14,21 @@ LL | auto trait Magic : Sized where Option : Magic {} | | | auto traits cannot have super traits or lifetime bounds -error: aborting due to 2 previous errors +error[E0382]: use of moved value: `x` + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:8:41 + | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | - - ^ value used here after move + | | | + | | value moved here + | move occurs because `x` has type `T`, which does not implement the `Copy` trait + | +help: consider further restricting this bound + | +LL | fn copy(x: T) -> (T, T) { (x, x) } + | ++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0568`. +Some errors have detailed explanations: E0382, E0568. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr index aa5585a5371f6..b7c9738991274 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)` --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:18 | LL | is_mytrait::<(MyS2, MyS)>(); - | ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2` + | ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`, which is required by `(MyS2, MyS): MyTrait` | = note: required because it appears within the type `(MyS2, MyS)` note: required by a bound in `is_mytrait` diff --git a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr index 2498af996eabd..e699422ae2b86 100644 --- a/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr +++ b/tests/ui/auto-traits/typeck-default-trait-impl-precedence.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u32: Signed` is not satisfied --> $DIR/typeck-default-trait-impl-precedence.rs:19:20 | LL | is_defaulted::<&'static u32>(); - | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32` + | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted` | note: required for `&'static u32` to implement `Defaulted` --> $DIR/typeck-default-trait-impl-precedence.rs:10:19 diff --git a/tests/ui/binding/irrefutable-if-let-without-else.fixed b/tests/ui/binding/irrefutable-if-let-without-else.fixed new file mode 100644 index 0000000000000..3d7f4695ca864 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.fixed @@ -0,0 +1,25 @@ +// run-rustfix +enum Enum { + Variant(i32), +} +struct Struct(i32); + +fn foo(x: Enum) -> i32 { + let Enum::Variant(value) = x; + value +} +fn bar(x: Enum) -> i32 { + let Enum::Variant(value) = x; + let x = value + 1; + x +} +fn baz(x: Struct) -> i32 { + let Struct(value) = x; + let x = value + 1; + x +} +fn main() { + let _ = foo(Enum::Variant(42)); + let _ = bar(Enum::Variant(42)); + let _ = baz(Struct(42)); +} diff --git a/tests/ui/binding/irrefutable-if-let-without-else.rs b/tests/ui/binding/irrefutable-if-let-without-else.rs new file mode 100644 index 0000000000000..5aaf4ace3f821 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.rs @@ -0,0 +1,28 @@ +// run-rustfix +enum Enum { + Variant(i32), +} +struct Struct(i32); + +fn foo(x: Enum) -> i32 { + if let Enum::Variant(value) = x { //~ ERROR `if` may be missing an `else` clause + value + } +} +fn bar(x: Enum) -> i32 { + if let Enum::Variant(value) = x { //~ ERROR `if` may be missing an `else` clause + let x = value + 1; + x + } +} +fn baz(x: Struct) -> i32 { + if let Struct(value) = x { //~ ERROR `if` may be missing an `else` clause + let x = value + 1; + x + } +} +fn main() { + let _ = foo(Enum::Variant(42)); + let _ = bar(Enum::Variant(42)); + let _ = baz(Struct(42)); +} diff --git a/tests/ui/binding/irrefutable-if-let-without-else.stderr b/tests/ui/binding/irrefutable-if-let-without-else.stderr new file mode 100644 index 0000000000000..e234cfdd945f3 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.stderr @@ -0,0 +1,61 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:8:5 + | +LL | fn foo(x: Enum) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Enum::Variant(value) = x { +LL | | value +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Enum::Variant(value) = x; +LL ~ value + | + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:13:5 + | +LL | fn bar(x: Enum) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Enum::Variant(value) = x { +LL | | let x = value + 1; +LL | | x +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Enum::Variant(value) = x; +LL ~ let x = value + 1; +LL ~ x + | + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:19:5 + | +LL | fn baz(x: Struct) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Struct(value) = x { +LL | | let x = value + 1; +LL | | x +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Struct(value) = x; +LL ~ let x = value + 1; +LL ~ x + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/binding/match-range.rs b/tests/ui/binding/match-range.rs index 1dca84dfd45ff..cb7b93e7cc65f 100644 --- a/tests/ui/binding/match-range.rs +++ b/tests/ui/binding/match-range.rs @@ -1,5 +1,4 @@ // run-pass -#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 #![feature(exclusive_range_pattern)] pub fn main() { diff --git a/tests/ui/binop/binary-op-suggest-deref.stderr b/tests/ui/binop/binary-op-suggest-deref.stderr index a98a2ab070666..8a226d712ff58 100644 --- a/tests/ui/binop/binary-op-suggest-deref.stderr +++ b/tests/ui/binop/binary-op-suggest-deref.stderr @@ -27,7 +27,7 @@ error[E0277]: can't compare `&{integer}` with `{integer}` LL | _ = foo == &0; | ^^ no implementation for `&{integer} == {integer}` | - = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}` + = help: the trait `PartialEq<{integer}>` is not implemented for `&{integer}`, which is required by `&&{integer}: PartialEq<&{integer}>` = note: required for `&&{integer}` to implement `PartialEq<&{integer}>` help: consider dereferencing here | @@ -65,7 +65,7 @@ error[E0277]: can't compare `&&{integer}` with `{integer}` LL | _ = &&foo == &&0; | ^^ no implementation for `&&{integer} == {integer}` | - = help: the trait `PartialEq<{integer}>` is not implemented for `&&{integer}` + = help: the trait `PartialEq<{integer}>` is not implemented for `&&{integer}`, which is required by `&&&&{integer}: PartialEq<&&{integer}>` = note: required for `&&&{integer}` to implement `PartialEq<&{integer}>` = note: 1 redundant requirement hidden = note: required for `&&&&{integer}` to implement `PartialEq<&&{integer}>` @@ -119,7 +119,7 @@ error[E0277]: can't compare `{integer}` with `&{integer}` LL | _ = &0 == foo; | ^^ no implementation for `{integer} == &{integer}` | - = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}` + = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`, which is required by `&{integer}: PartialEq<&&{integer}>` = note: required for `&{integer}` to implement `PartialEq<&&{integer}>` help: consider dereferencing here | @@ -157,7 +157,7 @@ error[E0277]: can't compare `{integer}` with `&&{integer}` LL | _ = &&0 == &&foo; | ^^ no implementation for `{integer} == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `{integer}` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `{integer}`, which is required by `&&{integer}: PartialEq<&&&&{integer}>` = note: required for `&{integer}` to implement `PartialEq<&&&{integer}>` = note: 1 redundant requirement hidden = note: required for `&&{integer}` to implement `PartialEq<&&&&{integer}>` @@ -173,7 +173,7 @@ error[E0277]: can't compare `Box>` with `&&{integer}` LL | _ = &Box::new(Box::new(42)) == &foo; | ^^ no implementation for `Box> == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>`, which is required by `&Box>: PartialEq<&&&{integer}>` = note: required for `&Box>` to implement `PartialEq<&&&{integer}>` help: consider dereferencing both sides of the expression | @@ -187,7 +187,7 @@ error[E0277]: can't compare `Box<{integer}>` with `&&{integer}` LL | _ = &Box::new(42) == &foo; | ^^ no implementation for `Box<{integer}> == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<{integer}>` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box<{integer}>`, which is required by `&Box<{integer}>: PartialEq<&&&{integer}>` = note: required for `&Box<{integer}>` to implement `PartialEq<&&&{integer}>` help: consider dereferencing both sides of the expression | @@ -201,7 +201,7 @@ error[E0277]: can't compare `Box>>>` with `&&{integer}` LL | _ = &Box::new(Box::new(Box::new(Box::new(42)))) == &foo; | ^^ no implementation for `Box>>> == &&{integer}` | - = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>>>` + = help: the trait `PartialEq<&&{integer}>` is not implemented for `Box>>>`, which is required by `&Box>>>: PartialEq<&&&{integer}>` = note: required for `&Box>>>` to implement `PartialEq<&&&{integer}>` help: consider dereferencing both sides of the expression | @@ -215,7 +215,7 @@ error[E0277]: can't compare `&&{integer}` with `Box>>>` LL | _ = &foo == &Box::new(Box::new(Box::new(Box::new(42)))); | ^^ no implementation for `&&{integer} == Box>>>` | - = help: the trait `PartialEq>>>>` is not implemented for `&&{integer}` + = help: the trait `PartialEq>>>>` is not implemented for `&&{integer}`, which is required by `&&&{integer}: PartialEq<&Box>>>>` = note: required for `&&&{integer}` to implement `PartialEq<&Box>>>>` help: consider dereferencing both sides of the expression | diff --git a/tests/ui/issues/issue-62375.rs b/tests/ui/binop/issue-62375.rs similarity index 100% rename from tests/ui/issues/issue-62375.rs rename to tests/ui/binop/issue-62375.rs diff --git a/tests/ui/issues/issue-62375.stderr b/tests/ui/binop/issue-62375.stderr similarity index 100% rename from tests/ui/issues/issue-62375.stderr rename to tests/ui/binop/issue-62375.stderr diff --git a/tests/ui/binop/issue-77910-1.rs b/tests/ui/binop/issue-77910-1.rs index 95bbd6a60ec86..4b7ee77b46dc8 100644 --- a/tests/ui/binop/issue-77910-1.rs +++ b/tests/ui/binop/issue-77910-1.rs @@ -1,6 +1,6 @@ fn foo(s: &i32) -> &i32 { let xs; - xs + xs //~ ERROR: isn't initialized } fn main() { let y; diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr index 263a35d982911..6402e5681884c 100644 --- a/tests/ui/binop/issue-77910-1.stderr +++ b/tests/ui/binop/issue-77910-1.stderr @@ -22,7 +22,20 @@ LL | assert_eq!(foo, y); = help: use parentheses to call this function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-1.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0369. +Some errors have detailed explanations: E0277, E0369, E0381. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/binop/issue-77910-2.rs b/tests/ui/binop/issue-77910-2.rs index 2bb48d3657617..5ea03e82b2fe9 100644 --- a/tests/ui/binop/issue-77910-2.rs +++ b/tests/ui/binop/issue-77910-2.rs @@ -1,6 +1,6 @@ fn foo(s: &i32) -> &i32 { let xs; - xs + xs //~ ERROR: isn't initialized } fn main() { let y; diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr index e58ae0fad9b4d..a14560ff188ee 100644 --- a/tests/ui/binop/issue-77910-2.stderr +++ b/tests/ui/binop/issue-77910-2.stderr @@ -11,6 +11,20 @@ help: use parentheses to call this function LL | if foo(/* &i32 */) == y {} | ++++++++++++ -error: aborting due to 1 previous error +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-2.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0369`. +Some errors have detailed explanations: E0369, E0381. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/block-result/issue-22645.stderr b/tests/ui/block-result/issue-22645.stderr index 1064848f5139e..2a267ce792fde 100644 --- a/tests/ui/block-result/issue-22645.stderr +++ b/tests/ui/block-result/issue-22645.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied --> $DIR/issue-22645.rs:15:5 | LL | b + 3 - | ^ the trait `Scalar` is not implemented for `{integer}` + | ^ the trait `Scalar` is not implemented for `{integer}`, which is required by `Bob: Add<_>` | = help: the trait `Scalar` is implemented for `f64` note: required for `Bob` to implement `Add<{integer}>` diff --git a/tests/ui/box/unit/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr index 49547872d1a7b..8ea6edb48a7fc 100644 --- a/tests/ui/box/unit/unique-object-noncopyable.stderr +++ b/tests/ui/box/unit/unique-object-noncopyable.stderr @@ -12,6 +12,9 @@ LL | let _z = y.clone(); which is required by `Box: Clone` `dyn Foo: Clone` which is required by `Box: Clone` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` error: aborting due to 1 previous error diff --git a/tests/ui/box/unit/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr index d2bf72249c451..69428604b197f 100644 --- a/tests/ui/box/unit/unique-pinned-nocopy.stderr +++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr @@ -10,9 +10,6 @@ LL | let _j = i.clone(); = note: the following trait bounds were not satisfied: `R: Clone` which is required by `Box: Clone` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `Clone` help: consider annotating `R` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs index 2edc52c6f55f0..7e8820cb2c65d 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_imports)] diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs index 8d24771578444..50914b1de53f2 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Simple test case of implementing a trait with super-builtin-kinds. // pretty-expanded FIXME #23616 diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs index f999dfff786eb..0577acc572ad5 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Tests correct implementation of traits with super-builtin-kinds // using a bounded type parameter. diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs index 249481467e646..be6a6bb8b1755 100644 --- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs @@ -8,7 +8,7 @@ trait Foo { fn foo(&self, _: T) -> u32 { 42 } } -trait Bar { +trait Bar { //~ WARN trait `Bar` is never used fn bar(&self) { println!("Bar!"); } } diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr new file mode 100644 index 0000000000000..952687e98d0ef --- /dev/null +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/cast-rfc0401-vtable-kinds.rs:11:7 + | +LL | trait Bar { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/cast/enum-to-numeric-cast.rs b/tests/ui/cast/enum-to-numeric-cast.rs new file mode 100644 index 0000000000000..d5ab2a6a1fed7 --- /dev/null +++ b/tests/ui/cast/enum-to-numeric-cast.rs @@ -0,0 +1,46 @@ +// Tests that `as` casts from enums to numeric types succeed +// only if the enum type is "unit-only" or "fieldless" as +// described here: https://doc.rust-lang.org/reference/items/enumerations.html#casting + +pub enum UnitOnly { + Foo, + Bar, + Baz, +} + +pub enum Fieldless { + Tuple(), + Struct{}, + Unit, +} + +pub enum NotUnitOnlyOrFieldless { + Foo, + Bar(u8), + Baz +} + +fn main() { + let unit_only = UnitOnly::Foo; + + let _ = unit_only as isize; + let _ = unit_only as i32; + let _ = unit_only as usize; + let _ = unit_only as u32; + + + let fieldless = Fieldless::Struct{}; + + let _ = fieldless as isize; + let _ = fieldless as i32; + let _ = fieldless as usize; + let _ = fieldless as u32; + + + let not_unit_only_or_fieldless = NotUnitOnlyOrFieldless::Foo; + + let _ = not_unit_only_or_fieldless as isize; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `isize` + let _ = not_unit_only_or_fieldless as i32; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `i32` + let _ = not_unit_only_or_fieldless as usize; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `usize` + let _ = not_unit_only_or_fieldless as u32; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `u32` +} diff --git a/tests/ui/cast/enum-to-numeric-cast.stderr b/tests/ui/cast/enum-to-numeric-cast.stderr new file mode 100644 index 0000000000000..1a49cb97451ce --- /dev/null +++ b/tests/ui/cast/enum-to-numeric-cast.stderr @@ -0,0 +1,35 @@ +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `isize` + --> $DIR/enum-to-numeric-cast.rs:42:13 + | +LL | let _ = not_unit_only_or_fieldless as isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `i32` + --> $DIR/enum-to-numeric-cast.rs:43:13 + | +LL | let _ = not_unit_only_or_fieldless as i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `usize` + --> $DIR/enum-to-numeric-cast.rs:44:13 + | +LL | let _ = not_unit_only_or_fieldless as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `u32` + --> $DIR/enum-to-numeric-cast.rs:45:13 + | +LL | let _ = not_unit_only_or_fieldless as u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/fat-ptr-cast-rpass.rs b/tests/ui/cast/fat-ptr-cast-rpass.rs index f5747eb8b9666..c79468cadddd9 100644 --- a/tests/ui/cast/fat-ptr-cast-rpass.rs +++ b/tests/ui/cast/fat-ptr-cast-rpass.rs @@ -3,7 +3,7 @@ #![feature(ptr_metadata)] trait Foo { - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } struct Bar; diff --git a/tests/ui/cast/fat-ptr-cast-rpass.stderr b/tests/ui/cast/fat-ptr-cast-rpass.stderr new file mode 100644 index 0000000000000..d01688e0cc3b0 --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/fat-ptr-cast-rpass.rs:6:8 + | +LL | trait Foo { + | --- method in this trait +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/cast/issue-88621.stderr b/tests/ui/cast/issue-88621.stderr index 0459ce5eabde5..201651a207a20 100644 --- a/tests/ui/cast/issue-88621.stderr +++ b/tests/ui/cast/issue-88621.stderr @@ -2,7 +2,9 @@ error[E0605]: non-primitive cast: `Kind2` as `u8` --> $DIR/issue-88621.rs:9:13 | LL | let _ = Kind2::Foo() as u8; - | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | ^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information error: aborting due to 1 previous error diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs new file mode 100644 index 0000000000000..a6e68e1b7101c --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs @@ -0,0 +1,12 @@ +// #120427 +// This test checks we won't suggest more than 3 span suggestions for cfg names +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value")) + +#[cfg(value)] +//~^ WARNING unexpected `cfg` condition name: `value` +fn x() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr new file mode 100644 index 0000000000000..82d471d715b83 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -0,0 +1,13 @@ +warning: unexpected `cfg` condition name: `value` + --> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7 + | +LL | #[cfg(value)] + | ^^^^^ + | + = help: expected names are: `bar`, `bee`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(value)` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs new file mode 100644 index 0000000000000..edde6244ed1a9 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs @@ -0,0 +1,12 @@ +// #120427 +// This test checks that when a single cfg has a value for user's specified name +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value")) + +#[cfg(my_value)] +//~^ WARNING unexpected `cfg` condition name: `my_value` +fn x() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr new file mode 100644 index 0000000000000..b88ee71a156a2 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -0,0 +1,21 @@ +warning: unexpected `cfg` condition name: `my_value` + --> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7 + | +LL | #[cfg(my_value)] + | ^^^^^^^^ + | + = help: expected names are: `bar`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(my_value)` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default +help: found config with similar value + | +LL | #[cfg(foo = "my_value")] + | ~~~~~~~~~~~~~~~~ +help: found config with similar value + | +LL | #[cfg(bar = "my_value")] + | ~~~~~~~~~~~~~~~~ + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs new file mode 100644 index 0000000000000..7a0c345b7ca76 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs @@ -0,0 +1,18 @@ +// #120427 +// This test checks that when a single cfg has a value for user's specified name +// suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]` +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg() + +#[cfg(linux)] +//~^ WARNING unexpected `cfg` condition name: `linux` +fn x() {} + +// will not suggest if the cfg has a value +#[cfg(linux = "os-name")] +//~^ WARNING unexpected `cfg` condition name: `linux` +fn y() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr new file mode 100644 index 0000000000000..c044755142419 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr @@ -0,0 +1,22 @@ +warning: unexpected `cfg` condition name: `linux` + --> $DIR/cfg-value-for-cfg-name.rs:9:7 + | +LL | #[cfg(linux)] + | ^^^^^ help: found config with similar value: `target_os = "linux"` + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(linux)` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition name: `linux` + --> $DIR/cfg-value-for-cfg-name.rs:14:7 + | +LL | #[cfg(linux = "os-name")] + | ^^^^^^^^^^^^^^^^^ + | + = help: to expect this configuration use `--check-cfg=cfg(linux, values("os-name"))` + = note: see for more information about checking conditional configuration + +warning: 2 warnings emitted + diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index d7d538c0b9e3e..652e573d6ef32 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -125,7 +125,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `preview2`, `psx`, `relibc`, `sgx`, `uclibc` + = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `psx`, `relibc`, `sgx`, `uclibc` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -134,7 +134,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_family` are: `unix`, `wasi`, `wasm`, `windows` + = note: expected values for `target_family` are: `unix`, `wasm`, `windows` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -143,7 +143,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/class-cast-to-trait.rs b/tests/ui/class-cast-to-trait.rs index 345d6efd2d90a..ca98e4c90031f 100644 --- a/tests/ui/class-cast-to-trait.rs +++ b/tests/ui/class-cast-to-trait.rs @@ -1,5 +1,5 @@ trait Noisy { - fn speak(&self); + fn speak(&mut self); } struct Cat { @@ -10,7 +10,7 @@ struct Cat { } impl Cat { - pub fn eat(&self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { println!("OM NOM NOM"); self.how_hungry -= 2; @@ -24,12 +24,12 @@ impl Cat { } impl Noisy for Cat { - fn speak(&self) { self.meow(); } + fn speak(&mut self) { self.meow(); } } impl Cat { - fn meow(&self) { + fn meow(&mut self) { println!("Meow"); self.meows += 1; if self.meows % 5 == 0 { diff --git a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr index d3cd8185f924b..e2a2db7c3f098 100644 --- a/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr +++ b/tests/ui/closure-expected-type/expect-infer-var-appearing-twice.stderr @@ -1,10 +1,13 @@ error[E0631]: type mismatch in closure arguments --> $DIR/expect-infer-var-appearing-twice.rs:14:5 | -LL | with_closure(|x: u32, y: i32| { - | ^^^^^^^^^^^^ ---------------- found signature defined here - | | - | expected due to this +LL | with_closure(|x: u32, y: i32| { + | ^ ---------------- found signature defined here + | _____| + | | +LL | | +LL | | }); + | |______^ expected due to this | = note: expected closure signature `fn(_, _) -> _` found closure signature `fn(u32, i32) -> _` diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs index a2290d850207d..16f7df1b36347 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -15,6 +15,6 @@ fn foo () -> impl FnMut()->() { c } fn main() { - let c = foo(); + let mut c = foo(); c(); } diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr index c83ba41976bcd..8a2aaade66503 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr @@ -5,8 +5,19 @@ LL | NUMBER_POINTER => (), | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/match-edge-cases_1.rs:29:13 + | +LL | NUMBER_POINTER => (), + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..b54341f82c794 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr @@ -0,0 +1,11 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/multivariant.rs:7:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs index 72652ef60349a..bc2386e5d23d8 100644 --- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs @@ -1,8 +1,11 @@ // Test precise capture of a multi-variant enum (when remaining variants are // visibly uninhabited). +// revisions: min_exhaustive_patterns exhaustive_patterns // edition:2021 // run-pass -#![feature(exhaustive_patterns)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] pub fn main() { diff --git a/tests/ui/closures/binder/async-closure-with-binder.rs b/tests/ui/closures/binder/async-closure-with-binder.rs index 4fa599d37cbd1..69d30f369e97d 100644 --- a/tests/ui/closures/binder/async-closure-with-binder.rs +++ b/tests/ui/closures/binder/async-closure-with-binder.rs @@ -1,8 +1,9 @@ // edition:2021 +// check-pass + #![feature(closure_lifetime_binder)] #![feature(async_closure)] + fn main() { - for<'a> async || (); - //~^ ERROR `for<...>` binders on `async` closures are not currently supported - //~^^ ERROR implicit types in closure signatures are forbidden when `for<...>` is present + for<'a> async || -> () {}; } diff --git a/tests/ui/closures/binder/async-closure-with-binder.stderr b/tests/ui/closures/binder/async-closure-with-binder.stderr deleted file mode 100644 index 1d4628b1a494a..0000000000000 --- a/tests/ui/closures/binder/async-closure-with-binder.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: `for<...>` binders on `async` closures are not currently supported - --> $DIR/async-closure-with-binder.rs:5:5 - | -LL | for<'a> async || (); - | ^^^^^^^ - -error: implicit types in closure signatures are forbidden when `for<...>` is present - --> $DIR/async-closure-with-binder.rs:5:5 - | -LL | for<'a> async || (); - | -------^^^^^^^^^ - | | - | `for<...>` is here - -error: aborting due to 2 previous errors - diff --git a/tests/ui/closures/binder/implicit-stuff.rs b/tests/ui/closures/binder/implicit-stuff.rs index 09e4c747afee8..c976c200b0c8e 100644 --- a/tests/ui/closures/binder/implicit-stuff.rs +++ b/tests/ui/closures/binder/implicit-stuff.rs @@ -24,4 +24,5 @@ fn main() { //~| ERROR `'_` cannot be used here let _ = for<'a> |x: &()| -> &'a () { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here let _ = for<'a> |x: &'a ()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here + //~^ ERROR: lifetime may not live long enough } diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr index cec2a60ba28c8..330a05a79bae3 100644 --- a/tests/ui/closures/binder/implicit-stuff.stderr +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -102,6 +102,15 @@ LL | let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { | | | `for<...>` is here -error: aborting due to 15 previous errors +error: lifetime may not live long enough + --> $DIR/implicit-stuff.rs:26:42 + | +LL | let _ = for<'a> |x: &'a ()| -> &() { x }; + | -- - ^ returning this value requires that `'a` must outlive `'1` + | | | + | | let's call the lifetime of this reference `'1` + | lifetime `'a` defined here + +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/closures/closure-move-sync.stderr b/tests/ui/closures/closure-move-sync.stderr index 2bb26b0c0b7d4..6cade0c09dd7e 100644 --- a/tests/ui/closures/closure-move-sync.stderr +++ b/tests/ui/closures/closure-move-sync.stderr @@ -10,7 +10,7 @@ LL | | LL | | }); | |_____^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>` + = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`, which is required by `{closure@$DIR/closure-move-sync.rs:6:27: 6:29}: Send` = note: required for `&std::sync::mpsc::Receiver<()>` to implement `Send` note: required because it's used within this closure --> $DIR/closure-move-sync.rs:6:27 diff --git a/tests/ui/closures/closure-return-type-must-be-sized.stderr b/tests/ui/closures/closure-return-type-must-be-sized.stderr index d4fc723fa8176..167d326e26edf 100644 --- a/tests/ui/closures/closure-return-type-must-be-sized.stderr +++ b/tests/ui/closures/closure-return-type-must-be-sized.stderr @@ -2,9 +2,9 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation --> $DIR/closure-return-type-must-be-sized.rs:54:5 | LL | a::foo:: dyn A>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -13,7 +13,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | a::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `a::bar` --> $DIR/closure-return-type-must-be-sized.rs:14:19 @@ -25,18 +25,18 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation --> $DIR/closure-return-type-must-be-sized.rs:56:5 | LL | a::baz:: dyn A>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:61:5 | LL | b::foo:: dyn A>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -45,7 +45,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | b::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: Fn()` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `b::bar` --> $DIR/closure-return-type-must-be-sized.rs:28:19 @@ -57,18 +57,18 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation --> $DIR/closure-return-type-must-be-sized.rs:63:5 | LL | b::baz:: dyn A>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time --> $DIR/closure-return-type-must-be-sized.rs:68:5 | LL | c::foo:: dyn A>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error[E0277]: the size for values of type `dyn A` cannot be known at compilation time @@ -77,7 +77,7 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation LL | c::bar:: dyn A, _>(); | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnMut()` = note: required because it appears within the type `fn() -> dyn A` note: required by a bound in `c::bar` --> $DIR/closure-return-type-must-be-sized.rs:42:19 @@ -89,9 +89,9 @@ error[E0277]: the size for values of type `dyn A` cannot be known at compilation --> $DIR/closure-return-type-must-be-sized.rs:70:5 | LL | c::baz:: dyn A>(); - | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A` + = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`, which is required by `fn() -> dyn A: FnOnce()` = note: required because it appears within the type `fn() -> dyn A` error: aborting due to 9 previous errors diff --git a/tests/ui/closures/issue-109188.rs b/tests/ui/closures/issue-109188.rs index cae1ced9958a7..03c8b415774cf 100644 --- a/tests/ui/closures/issue-109188.rs +++ b/tests/ui/closures/issue-109188.rs @@ -7,13 +7,13 @@ struct X(Y); struct Y; -fn consume_fnmut(f: &dyn FnMut()) { +fn consume_fnmut(f: &mut dyn FnMut()) { f(); } fn move_into_fnmut() { let x = move_into_fnmut(); - consume_fnmut(&|| { + consume_fnmut(&mut || { let Either::One(_t) = x; //~ ERROR mismatched types let Either::Two(_t) = x; //~ ERROR mismatched types }); diff --git a/tests/ui/closures/issue-111932.stderr b/tests/ui/closures/issue-111932.stderr index 937bdf3bea255..ff46b10d005dc 100644 --- a/tests/ui/closures/issue-111932.stderr +++ b/tests/ui/closures/issue-111932.stderr @@ -17,7 +17,7 @@ LL | println!("{:?}", foo); | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `dyn Foo` -note: required by a bound in `core::fmt::rt::Argument::<'a>::new_debug` +note: required by an implicit `Sized` bound in `core::fmt::rt::Argument::<'a>::new_debug` --> $SRC_DIR/core/src/fmt/rt.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) diff --git a/tests/ui/closures/issue-78720.rs b/tests/ui/closures/issue-78720.rs index 4cdb9f491130c..0e1f78ae3c69b 100644 --- a/tests/ui/closures/issue-78720.rs +++ b/tests/ui/closures/issue-78720.rs @@ -1,6 +1,7 @@ fn server() -> impl { //~^ ERROR at least one trait must be specified ().map2(|| "") + //~^ ERROR type annotations needed } trait FilterBase2 { diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr index 5d65c87b0fd61..d8d3811af5a74 100644 --- a/tests/ui/closures/issue-78720.stderr +++ b/tests/ui/closures/issue-78720.stderr @@ -5,7 +5,7 @@ LL | fn server() -> impl { | ^^^^ error[E0412]: cannot find type `F` in this scope - --> $DIR/issue-78720.rs:13:12 + --> $DIR/issue-78720.rs:14:12 | LL | _func: F, | ^ @@ -22,8 +22,14 @@ help: you might be missing a type parameter LL | struct Map2 { | +++ +error[E0282]: type annotations needed + --> $DIR/issue-78720.rs:3:5 + | +LL | ().map2(|| "") + | ^^^^^^^^^^^^^^ cannot infer type + error[E0308]: mismatched types - --> $DIR/issue-78720.rs:7:39 + --> $DIR/issue-78720.rs:8:39 | LL | fn map2(self, f: F) -> Map2 {} | ^^ expected `Map2`, found `()` @@ -32,7 +38,7 @@ LL | fn map2(self, f: F) -> Map2 {} found unit type `()` error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/issue-78720.rs:7:16 + --> $DIR/issue-78720.rs:8:16 | LL | fn map2(self, f: F) -> Map2 {} | ^^^^ doesn't have a size known at compile-time @@ -47,7 +53,7 @@ help: function arguments must have a statically known size, borrowed types alway LL | fn map2(&self, f: F) -> Map2 {} | + -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0308, E0412. +Some errors have detailed explanations: E0277, E0282, E0308, E0412. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr index 325652ef14ce5..9a49fc99ac31a 100644 --- a/tests/ui/closures/multiple-fn-bounds.stderr +++ b/tests/ui/closures/multiple-fn-bounds.stderr @@ -2,8 +2,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/multiple-fn-bounds.rs:10:5 | LL | foo(move |x| v); - | ^^^ -------- found signature defined here - | | + | ^^^^--------^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `fn(_) -> _` diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs index 6320d296373c0..72c14cd7a6919 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs @@ -2,8 +2,11 @@ // needs-llvm-components: arm #![feature(cmse_nonsecure_entry, no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} #[no_mangle] #[cmse_nonsecure_entry] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr index 4d34f0d75099d..c3fae3d8bbb67 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr @@ -1,5 +1,5 @@ error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI - --> $DIR/wrong-abi.rs:9:1 + --> $DIR/wrong-abi.rs:12:1 | LL | #[cmse_nonsecure_entry] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-82833-slice-miscompile.rs b/tests/ui/codegen/issue-82833-slice-miscompile.rs similarity index 100% rename from tests/ui/issues/issue-82833-slice-miscompile.rs rename to tests/ui/codegen/issue-82833-slice-miscompile.rs diff --git a/tests/ui/coercion/issue-14589.rs b/tests/ui/coercion/issue-14589.rs index f92385f8d7275..6f95b30be06ae 100644 --- a/tests/ui/coercion/issue-14589.rs +++ b/tests/ui/coercion/issue-14589.rs @@ -19,6 +19,6 @@ impl Test { fn send(&self, _: T) {} } -trait Foo { fn dummy(&self) { }} +trait Foo { fn dummy(&self) { }} //~ WARN method `dummy` is never used struct Output(#[allow(dead_code)] isize); impl Foo for Output {} diff --git a/tests/ui/coercion/issue-14589.stderr b/tests/ui/coercion/issue-14589.stderr new file mode 100644 index 0000000000000..37b7fce7462b3 --- /dev/null +++ b/tests/ui/coercion/issue-14589.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-14589.rs:22:16 + | +LL | trait Foo { fn dummy(&self) { }} + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-26905-rpass.rs b/tests/ui/coercion/issue-26905-rpass.rs similarity index 100% rename from tests/ui/issues/issue-26905-rpass.rs rename to tests/ui/coercion/issue-26905-rpass.rs diff --git a/tests/ui/issues/issue-26905.rs b/tests/ui/coercion/issue-26905.rs similarity index 100% rename from tests/ui/issues/issue-26905.rs rename to tests/ui/coercion/issue-26905.rs diff --git a/tests/ui/issues/issue-26905.stderr b/tests/ui/coercion/issue-26905.stderr similarity index 100% rename from tests/ui/issues/issue-26905.stderr rename to tests/ui/coercion/issue-26905.stderr diff --git a/tests/ui/coherence/associated-type2.rs b/tests/ui/coherence/associated-type2.rs new file mode 100644 index 0000000000000..2aadfb04af05d --- /dev/null +++ b/tests/ui/coherence/associated-type2.rs @@ -0,0 +1,20 @@ +//! A regression test for #120343. The overlap error was previously +//! silenced in coherence because projecting `<() as ToUnit>::Unit` +//! failed. Then then silenced the missing items error in the `ToUnit` +//! impl, causing us to not emit any errors and ICEing due to a +//! `span_delay_bug`. + +trait ToUnit { + type Unit; +} + +impl ToUnit for *const T {} +//~^ ERROR: not all trait items implemented + +trait Overlap {} + +impl Overlap for T {} + +impl Overlap<<*const T as ToUnit>::Unit> for T {} + +fn main() {} diff --git a/tests/ui/coherence/associated-type2.stderr b/tests/ui/coherence/associated-type2.stderr new file mode 100644 index 0000000000000..62d3d8b8ebd1c --- /dev/null +++ b/tests/ui/coherence/associated-type2.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Unit` + --> $DIR/associated-type2.rs:11:1 + | +LL | type Unit; + | --------- `Unit` from trait +... +LL | impl ToUnit for *const T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Unit` in implementation + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs index 6a9db217373f9..cdec81271d090 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs @@ -22,6 +22,7 @@ struct MyType { impl MyTrait for MyType { //~^ ERROR E0119 fn get(&self) -> usize { (*self).clone() } + //~^ ERROR incompatible type } fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr index ddb7474c2899a..471dfe1cae79d 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr @@ -7,6 +7,24 @@ LL | impl MyTrait for T { LL | impl MyTrait for MyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` -error: aborting due to 1 previous error +error[E0053]: method `get` has an incompatible type for trait + --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:24:22 + | +LL | fn get(&self) -> usize { (*self).clone() } + | ^^^^^ + | | + | expected `MyType`, found `usize` + | help: change the output type to match the trait: `MyType` + | +note: type in trait + --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:8:22 + | +LL | fn get(&self) -> T; + | ^ + = note: expected signature `fn(&MyType) -> MyType` + found signature `fn(&MyType) -> usize` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0053, E0119. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/coherence/coherence-multidispatch-tuple.rs b/tests/ui/coherence/coherence-multidispatch-tuple.rs index fa1d4bbb49665..b04b2a296b5b4 100644 --- a/tests/ui/coherence/coherence-multidispatch-tuple.rs +++ b/tests/ui/coherence/coherence-multidispatch-tuple.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_imports)] // pretty-expanded FIXME #23616 diff --git a/tests/ui/coherence/coherence-orphan.rs b/tests/ui/coherence/coherence-orphan.rs index bed782203af50..985cfe8716130 100644 --- a/tests/ui/coherence/coherence-orphan.rs +++ b/tests/ui/coherence/coherence-orphan.rs @@ -9,10 +9,13 @@ struct TheType; impl TheTrait for isize { } //~^ ERROR E0117 +//~| ERROR not all trait items implemented impl TheTrait for isize { } +//~^ ERROR not all trait items implemented impl TheTrait for TheType { } +//~^ ERROR not all trait items implemented impl !Send for Vec { } //~ ERROR E0117 //~^ WARNING diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index 9ec1d0dc32aa4..78fad837647b4 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -11,7 +11,7 @@ LL | impl TheTrait for isize { } = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/coherence-orphan.rs:17:1 + --> $DIR/coherence-orphan.rs:20:1 | LL | impl !Send for Vec { } | ^^^^^^^^^^^^^^^---------- @@ -22,7 +22,7 @@ LL | impl !Send for Vec { } = note: define and implement a trait or new type instead warning: cross-crate traits with a default impl, like `Send`, should not be specialized - --> $DIR/coherence-orphan.rs:17:1 + --> $DIR/coherence-orphan.rs:20:1 | LL | impl !Send for Vec { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,6 +34,31 @@ note: try using the same sequence of generic parameters as the struct definition --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: `#[warn(suspicious_auto_trait_impls)]` on by default -error: aborting due to 2 previous errors; 1 warning emitted +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:10:1 + | +LL | impl TheTrait for isize { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:14:1 + | +LL | impl TheTrait for isize { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:17:1 + | +LL | impl TheTrait for TheType { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error: aborting due to 5 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0046, E0117. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs index 97fd3f719bfbf..f1c2698bad5cc 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.rs +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -5,12 +5,15 @@ extern "Rust" { } pub struct ListS { + //~^ NOTE: required because it appears within the type len: usize, data: [T; 0], opaque: OpaqueListContents, } pub struct Interned<'a, T>(&'a T); +//~^ NOTE: required by an implicit `Sized` +//~| NOTE: required by the implicit `Sized` impl<'a, T> Clone for Interned<'a, T> { fn clone(&self) -> Self { @@ -23,6 +26,8 @@ impl<'a, T> Copy for Interned<'a, T> {} pub struct List<'tcx, T>(Interned<'tcx, ListS>); //~^ NOTE this field does not implement `Copy` //~| NOTE the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` +//~| NOTE: doesn't have a size known at compile-time +//~| ERROR: cannot be known at compilation time impl<'tcx, T> Clone for List<'tcx, T> { fn clone(&self) -> Self { diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index e79abe35597d4..fe5ae9b08b4b9 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/deep-bad-copy-reason.rs:33:24 + --> $DIR/deep-bad-copy-reason.rs:38:24 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ------------------------ this field does not implement `Copy` @@ -8,11 +8,34 @@ LL | impl<'tcx, T> Copy for List<'tcx, T> {} | ^^^^^^^^^^^^^ | note: the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` - --> $DIR/deep-bad-copy-reason.rs:23:26 + --> $DIR/deep-bad-copy-reason.rs:26:26 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0277]: the size for values of type `OpaqueListContents` cannot be known at compilation time + --> $DIR/deep-bad-copy-reason.rs:26:26 + | +LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `ListS`, the trait `Sized` is not implemented for `OpaqueListContents`, which is required by `ListS: Sized` +note: required because it appears within the type `ListS` + --> $DIR/deep-bad-copy-reason.rs:7:12 + | +LL | pub struct ListS { + | ^^^^^ +note: required by an implicit `Sized` bound in `Interned` + --> $DIR/deep-bad-copy-reason.rs:14:25 + | +LL | pub struct Interned<'a, T>(&'a T); + | ^ required by the implicit `Sized` requirement on this type parameter in `Interned` +help: consider relaxing the implicit `Sized` restriction + | +LL | pub struct Interned<'a, T: ?Sized>(&'a T); + | ++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 428ee902ea528..4ad8257d2c14b 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait>` for type `Alias<_>` - --> $DIR/opaques.rs:29:1 + --> $DIR/opaques.rs:30:1 | LL | impl Trait for T { | ---------------------- first implementation here @@ -7,6 +7,13 @@ LL | impl Trait for T { LL | impl Trait for defining_scope::Alias { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/opaques.rs:13:20 + | +LL | pub fn cast(x: Container, T>) -> Container { + | ^ cannot infer type for struct `Container, T>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0282. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index 2fa9dcebfdec4..73cd42bf3f25d 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -11,6 +11,7 @@ mod defining_scope { pub type Alias = impl Sized; pub fn cast(x: Container, T>) -> Container { + //[next]~^ ERROR type annotations needed x } } diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr index 1177965d0d2c2..771d661f615ec 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr @@ -2,7 +2,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_bad_empty_array.rs:10:13 | LL | check::<[NotParam; 0]>(); - | ^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 0]: ConstParamTy` | = note: required for `[NotParam; 0]` to implement `ConstParamTy` note: required by a bound in `check` diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr index 86d1c94e87f96..83c34c41f1059 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr @@ -2,7 +2,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:10:13 | LL | check::<&NotParam>(); - | ^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `&NotParam: ConstParamTy` | = note: required for `&NotParam` to implement `ConstParamTy` note: required by a bound in `check` @@ -15,7 +15,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:11:13 | LL | check::<[NotParam]>(); - | ^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam]: ConstParamTy` | = note: required for `[NotParam]` to implement `ConstParamTy` note: required by a bound in `check` @@ -28,7 +28,7 @@ error[E0277]: `NotParam` can't be used as a const parameter type --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:12:13 | LL | check::<[NotParam; 17]>(); - | ^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | ^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam`, which is required by `[NotParam; 17]: ConstParamTy` | = note: required for `[NotParam; 17]` to implement `ConstParamTy` note: required by a bound in `check` diff --git a/tests/ui/const-generics/associated-type-bound.rs b/tests/ui/const-generics/associated-type-bound.rs index 3044736b47e05..0a57352c10da1 100644 --- a/tests/ui/const-generics/associated-type-bound.rs +++ b/tests/ui/const-generics/associated-type-bound.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass trait Bar {} trait Foo { diff --git a/tests/ui/const-generics/condition-in-trait-const-arg.rs b/tests/ui/const-generics/condition-in-trait-const-arg.rs index 6f85237cf0aaf..74a663a53ec6b 100644 --- a/tests/ui/const-generics/condition-in-trait-const-arg.rs +++ b/tests/ui/const-generics/condition-in-trait-const-arg.rs @@ -1,5 +1,5 @@ // Checks that `impl Trait<{anon_const}> for Type` evaluates successfully. -// run-pass +// check-pass // revisions: full min #![cfg_attr(full, feature(generic_const_exprs))] diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs index 80013e7b4b230..ba41bf38a3379 100644 --- a/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.rs @@ -25,6 +25,6 @@ fn owo() -> impl Traitor { fn main() { rawr(); - uwu(); + uwu(); //~ ERROR: type annotations needed owo(); } diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr index a46bd53520b53..4ed1c0ded9f86 100644 --- a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -31,6 +31,18 @@ LL | 1_u64 | = help: the trait `Traitor<1, 2>` is implemented for `u64` -error: aborting due to 3 previous errors +error[E0282]: type annotations needed + --> $DIR/rp_impl_trait_fail.rs:28:5 + | +LL | uwu(); + | ^^^ cannot infer the value of the const parameter `N` declared on the function `uwu` + | +help: consider specifying the generic argument + | +LL | uwu::(); + | +++++ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0282. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/dyn-supertraits.rs b/tests/ui/const-generics/dyn-supertraits.rs index 3dee326a186e9..bb4924529824b 100644 --- a/tests/ui/const-generics/dyn-supertraits.rs +++ b/tests/ui/const-generics/dyn-supertraits.rs @@ -4,7 +4,7 @@ trait Foo { fn myfun(&self) -> usize; } trait Bar : Foo {} -trait Baz: Foo<3> {} +trait Baz: Foo<3> {} //~ WARN trait `Baz` is never used struct FooType; struct BarType; @@ -23,10 +23,10 @@ impl Foo<3> for BazType { impl Baz for BazType {} trait Foz {} -trait Boz: Foo<3> + Foz {} +trait Boz: Foo<3> + Foz {} //~ WARN trait `Boz` is never used trait Bok: Foo + Foz {} -struct FozType; +struct FozType; //~ WARN struct `FozType` is never constructed struct BozType; struct BokType; diff --git a/tests/ui/const-generics/dyn-supertraits.stderr b/tests/ui/const-generics/dyn-supertraits.stderr new file mode 100644 index 0000000000000..38b67ef4403a1 --- /dev/null +++ b/tests/ui/const-generics/dyn-supertraits.stderr @@ -0,0 +1,22 @@ +warning: trait `Baz` is never used + --> $DIR/dyn-supertraits.rs:7:7 + | +LL | trait Baz: Foo<3> {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: trait `Boz` is never used + --> $DIR/dyn-supertraits.rs:26:7 + | +LL | trait Boz: Foo<3> + Foz {} + | ^^^ + +warning: struct `FozType` is never constructed + --> $DIR/dyn-supertraits.rs:29:8 + | +LL | struct FozType; + | ^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/const-generics/ensure_is_evaluatable.stderr b/tests/ui/const-generics/ensure_is_evaluatable.stderr index a6f362308200a..b9bd9160b13c2 100644 --- a/tests/ui/const-generics/ensure_is_evaluatable.stderr +++ b/tests/ui/const-generics/ensure_is_evaluatable.stderr @@ -2,7 +2,7 @@ error: unconstrained generic constant --> $DIR/ensure_is_evaluatable.rs:9:5 | LL | bar() - | ^^^ + | ^^^^^ | = help: try adding a `where` bound using this expression: `where [(); N + 1]:` note: required by a bound in `bar` diff --git a/tests/ui/const-generics/fn_with_two_const_inputs.stderr b/tests/ui/const-generics/fn_with_two_const_inputs.stderr index ad32a688c03f7..ec31e02f144b8 100644 --- a/tests/ui/const-generics/fn_with_two_const_inputs.stderr +++ b/tests/ui/const-generics/fn_with_two_const_inputs.stderr @@ -2,7 +2,7 @@ error: unconstrained generic constant --> $DIR/fn_with_two_const_inputs.rs:12:5 | LL | bar() - | ^^^ + | ^^^^^ | = help: try adding a `where` bound using this expression: `where [(); N + 1]:` note: required by a bound in `bar` diff --git a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr index a6b736261e09c..6d8dd017734c0 100644 --- a/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr +++ b/tests/ui/const-generics/generic_arg_infer/infer-arg-test.stderr @@ -10,14 +10,14 @@ error: expected identifier, found reserved identifier `_` LL | fn bad_infer_fn<_>() {} | ^ expected identifier, found reserved identifier -error[E0392]: parameter `_` is never used +error[E0392]: type parameter `_` is never used --> $DIR/infer-arg-test.rs:7:17 | LL | struct BadInfer<_>; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `_` to be a const parameter, use `const _: usize` instead + = help: if you intended `_` to be a const parameter, use `const _: /* Type */` instead error[E0107]: struct takes 2 generic arguments but 3 generic arguments were supplied --> $DIR/infer-arg-test.rs:18:10 diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr index f2cc17bc517cd..6d3b0b8508c07 100644 --- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed for `Mask<_, N>` --> $DIR/issue-91614.rs:6:9 | LL | let y = Mask::<_, _>::splat(false); - | ^ ------------------- type must be known at this point + | ^ -------------------------- type must be known at this point | = note: cannot satisfy `_: MaskElement` = help: the following types implement trait `MaskElement`: diff --git a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr index cdf97bd88fd23..bd6fd67b89d74 100644 --- a/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr +++ b/tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr @@ -20,7 +20,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:17:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` | = note: expected constant `{ N as u128 }` found constant `{ O as u128 }` @@ -52,7 +52,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:20:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` | = note: expected constant `{ N as _ }` found constant `{ O as u128 }` @@ -66,7 +66,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:23:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` | = note: expected constant `12` found constant `13` @@ -80,7 +80,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:25:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` | = note: expected constant `13` found constant `14` @@ -112,7 +112,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:35:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }` | = note: expected constant `{ N as u128 }` found constant `{ O as u128 }` @@ -144,7 +144,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:38:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }` | = note: expected constant `{ N as _ }` found constant `{ O as u128 }` @@ -158,7 +158,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:41:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12`, found `13` | = note: expected constant `12` found constant `13` @@ -172,7 +172,7 @@ error[E0308]: mismatched types --> $DIR/abstract-const-as-cast-3.rs:43:5 | LL | assert_impl::>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13`, found `14` | = note: expected constant `13` found constant `14` diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr index 0742db398c9c4..87e26ce85dcfd 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr @@ -15,6 +15,18 @@ LL | ArrayHolder([0; Self::SIZE]) | = help: try adding a `where` bound using this expression: `where [(); Self::SIZE]:` -error: aborting due to 2 previous errors +error[E0282]: type annotations needed for `ArrayHolder` + --> $DIR/issue-62504.rs:26:9 + | +LL | let mut array = ArrayHolder::new(); + | ^^^^^^^^^ + | +help: consider giving `array` an explicit type, where the value of const parameter `X` is specified + | +LL | let mut array: ArrayHolder = ArrayHolder::new(); + | ++++++++++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr index 65822856e1d7c..1664669eee05a 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr @@ -22,6 +22,18 @@ note: tuple struct defined here LL | struct ArrayHolder([u32; X]); | ^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0282]: type annotations needed for `ArrayHolder` + --> $DIR/issue-62504.rs:26:9 + | +LL | let mut array = ArrayHolder::new(); + | ^^^^^^^^^ + | +help: consider giving `array` an explicit type, where the value of const parameter `X` is specified + | +LL | let mut array: ArrayHolder = ArrayHolder::new(); + | ++++++++++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.rs b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs index a97f4b8ff3131..6f40a9abfa796 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.rs +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.rs @@ -24,4 +24,5 @@ impl ArrayHolder { fn main() { let mut array = ArrayHolder::new(); + //~^ ERROR: type annotations needed } diff --git a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr index 9391b1c1a170a..3acccba026f26 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-85848.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied --> $DIR/issue-85848.rs:24:29 | LL | writes_to_specific_path(&cap); - | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()` + | ----------------------- ^^^^ the trait `_Contains<&C>` is not implemented for `()`, which is required by `&C: Delegates<()>` | | | required by a bound introduced by this call | @@ -58,7 +58,7 @@ error[E0308]: mismatched types --> $DIR/issue-85848.rs:24:5 | LL | writes_to_specific_path(&cap); - | ^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `{ contains::() }` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `{ contains::() }` | = note: expected constant `true` found constant `{ contains::() }` diff --git a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr index eba8b9b6257e5..7f6a154865ceb 100644 --- a/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr +++ b/tests/ui/const-generics/generic_const_exprs/obligation-cause.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/obligation-cause.rs:20:5 | LL | g::(); - | ^^^^^^^^^^ expected `false`, found `true` + | ^^^^^^^^^^^^ expected `false`, found `true` | = note: expected constant `false` found constant `true` diff --git a/tests/ui/const-generics/issue-46511.stderr b/tests/ui/const-generics/issue-46511.stderr index d57295fa2fae1..75d59ee40b3b7 100644 --- a/tests/ui/const-generics/issue-46511.stderr +++ b/tests/ui/const-generics/issue-46511.stderr @@ -7,11 +7,11 @@ LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-46511.rs:3:12 | LL | struct Foo<'a> - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/const-generics/issues/issue-67185-2.stderr b/tests/ui/const-generics/issues/issue-67185-2.stderr index a2e5b8053688b..24a2d60f2e1f0 100644 --- a/tests/ui/const-generics/issues/issue-67185-2.stderr +++ b/tests/ui/const-generics/issues/issue-67185-2.stderr @@ -26,7 +26,7 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} - | ^^^ the trait `Bar` is not implemented for `[u16; 3]` + | ^^^ the trait `Bar` is not implemented for `[u16; 3]`, which is required by `::Quaks: Bar` | = help: the following other types implement trait `Bar`: [u16; 4] @@ -44,7 +44,7 @@ error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} - | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` + | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`, which is required by `[::Quaks; 2]: Bar` | = help: the following other types implement trait `Bar`: [u16; 4] diff --git a/tests/ui/const-generics/issues/issue-67375.min.stderr b/tests/ui/const-generics/issues/issue-67375.min.stderr index 7671e3c468876..e871203ed9b89 100644 --- a/tests/ui/const-generics/issues/issue-67375.min.stderr +++ b/tests/ui/const-generics/issues/issue-67375.min.stderr @@ -7,14 +7,14 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-67375.rs:5:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-67945-1.min.stderr b/tests/ui/const-generics/issues/issue-67945-1.min.stderr index 1d071da903fa1..1de607644f570 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.min.stderr @@ -16,14 +16,14 @@ LL | let b = &*(&x as *const _ as *const S); = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-1.rs:7:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/issues/issue-67945-3.min.stderr b/tests/ui/const-generics/issues/issue-67945-3.min.stderr index e34869c79386b..0ccba18e953cf 100644 --- a/tests/ui/const-generics/issues/issue-67945-3.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-3.min.stderr @@ -7,14 +7,14 @@ LL | let x: Option = None; = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-3.rs:9:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-67945-4.min.stderr b/tests/ui/const-generics/issues/issue-67945-4.min.stderr index 280c6f4f2cdfe..83ae68e2dbf0e 100644 --- a/tests/ui/const-generics/issues/issue-67945-4.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-4.min.stderr @@ -7,14 +7,14 @@ LL | let x: Option> = None; = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-4.rs:8:12 | LL | struct Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.rs b/tests/ui/const-generics/issues/issue-69654-run-pass.rs index 63d7fde78ac8a..21d6270b1fafa 100644 --- a/tests/ui/const-generics/issues/issue-69654-run-pass.rs +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.rs @@ -1,5 +1,5 @@ // run-pass -trait Bar {} +trait Bar {} //~ WARN trait `Bar` is never used impl Bar for [u8; 7] {} struct Foo {} diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.stderr b/tests/ui/const-generics/issues/issue-69654-run-pass.stderr new file mode 100644 index 0000000000000..7b3cd4f375fd0 --- /dev/null +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/issue-69654-run-pass.rs:2:7 + | +LL | trait Bar {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/issues/issue-79674.stderr b/tests/ui/const-generics/issues/issue-79674.stderr index 1e7878e8da95c..595bb6faf8c00 100644 --- a/tests/ui/const-generics/issues/issue-79674.stderr +++ b/tests/ui/const-generics/issues/issue-79674.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-79674.rs:26:5 | LL | requires_distinct("str", 12); - | ^^^^^^^^^^^^^^^^^ expected `true`, found `false` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `true`, found `false` | = note: expected constant `true` found constant `false` diff --git a/tests/ui/const-generics/issues/issue-90318.rs b/tests/ui/const-generics/issues/issue-90318.rs index 909997340f36e..cebc1ce214208 100644 --- a/tests/ui/const-generics/issues/issue-90318.rs +++ b/tests/ui/const-generics/issues/issue-90318.rs @@ -13,6 +13,7 @@ fn consume(_val: T) where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, //~^ overly complex generic constant + //~| ERROR: cannot call { } @@ -20,6 +21,7 @@ fn test() where If<{ TypeId::of::() != TypeId::of::<()>() }>: True, //~^ overly complex generic constant + //~| ERROR: cannot call { } diff --git a/tests/ui/const-generics/issues/issue-90318.stderr b/tests/ui/const-generics/issues/issue-90318.stderr index f13fd795d7a10..471a6660ce0f3 100644 --- a/tests/ui/const-generics/issues/issue-90318.stderr +++ b/tests/ui/const-generics/issues/issue-90318.stderr @@ -10,7 +10,7 @@ LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, = note: this operation may be supported in the future error: overly complex generic constant - --> $DIR/issue-90318.rs:21:8 + --> $DIR/issue-90318.rs:22:8 | LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, | ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,5 +20,28 @@ LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const operator in constants + --> $DIR/issue-90318.rs:14:10 + | +LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot call non-const operator in constants + --> $DIR/issue-90318.rs:22:10 + | +LL | If<{ TypeId::of::() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr index 1fe0109771c5c..e42bb6e8cc561 100644 --- a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr +++ b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr @@ -13,5 +13,37 @@ LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to 2 previous errors +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `bug::{constant#0}` for CTFE... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { def: DefId(0:8 ~ late_bound_in_return_issue_77357[9394]::bug::{constant#0}), args: [T/#0] }: usize), bound_vars: [] }`... + = note: ...which again requires evaluating type-level constant, completing the cycle + = note: cycle used when normalizing `&dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]>` + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr index 07da6ede7251b..989be74d1b0d9 100644 --- a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr @@ -2,7 +2,7 @@ error[E0284]: type annotations needed --> $DIR/parent_generics_of_encoding_impl_trait.rs:9:5 | LL | generics_of_parent_impl_trait::foo([()]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `foo` | note: required by a bound in `foo` --> $DIR/auxiliary/generics_of_parent_impl_trait.rs:6:48 diff --git a/tests/ui/const-generics/unused-type-param-suggestion.rs b/tests/ui/const-generics/unused-type-param-suggestion.rs index 2251512c4596e..fb0ccb4fdcd72 100644 --- a/tests/ui/const-generics/unused-type-param-suggestion.rs +++ b/tests/ui/const-generics/unused-type-param-suggestion.rs @@ -1,4 +1,27 @@ #![crate_type="lib"] -struct Example; -//~^ ERROR parameter +struct S; +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +//~| HELP if you intended `N` to be a const parameter + +// Ensure that we don't emit the const param suggestion here: +struct T; +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` + +type A = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +//~| HELP if you intended `N` to be a const parameter + +// Ensure that we don't emit the const param suggestion here: +type B = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +type C = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` +type D = (); +//~^ ERROR type parameter `N` is never used +//~| HELP consider removing `N` diff --git a/tests/ui/const-generics/unused-type-param-suggestion.stderr b/tests/ui/const-generics/unused-type-param-suggestion.stderr index 6e985f56666bd..67b704d8bc725 100644 --- a/tests/ui/const-generics/unused-type-param-suggestion.stderr +++ b/tests/ui/const-generics/unused-type-param-suggestion.stderr @@ -1,12 +1,54 @@ -error[E0392]: parameter `N` is never used - --> $DIR/unused-type-param-suggestion.rs:3:16 +error[E0392]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:3:10 | -LL | struct Example; - | ^ unused parameter +LL | struct S; + | ^ unused type parameter | = help: consider removing `N`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `N` to be a const parameter, use `const N: usize` instead + = help: if you intended `N` to be a const parameter, use `const N: /* Type */` instead -error: aborting due to 1 previous error +error[E0392]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:9:10 + | +LL | struct T; + | ^ unused type parameter + | + = help: consider removing `N`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:13:8 + | +LL | type A = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + = help: if you intended `N` to be a const parameter, use `const N: /* Type */` instead + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:19:8 + | +LL | type B = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:22:8 + | +LL | type C = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + +error[E0091]: type parameter `N` is never used + --> $DIR/unused-type-param-suggestion.rs:25:8 + | +LL | type D = (); + | ^ unused type parameter + | + = help: consider removing `N` or referring to it in the body of the type alias + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0392`. +Some errors have detailed explanations: E0091, E0392. +For more information about an error, try `rustc --explain E0091`. diff --git a/tests/ui/consts/const-block-item.rs b/tests/ui/consts/const-block-item.rs index cf0d4441d4a9b..a04f4db263bb2 100644 --- a/tests/ui/consts/const-block-item.rs +++ b/tests/ui/consts/const-block-item.rs @@ -2,7 +2,7 @@ #![allow(unused_imports)] mod foo { - pub trait Value { + pub trait Value { //~ WARN trait `Value` is never used fn value(&self) -> usize; } } diff --git a/tests/ui/consts/const-block-item.stderr b/tests/ui/consts/const-block-item.stderr new file mode 100644 index 0000000000000..04658742b56ce --- /dev/null +++ b/tests/ui/consts/const-block-item.stderr @@ -0,0 +1,10 @@ +warning: trait `Value` is never used + --> $DIR/const-block-item.rs:5:15 + | +LL | pub trait Value { + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr index b13df67b423bb..14bce10f78744 100644 --- a/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr +++ b/tests/ui/consts/const-blocks/fn-call-in-non-const.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/fn-call-in-non-const.rs:14:32 | LL | let _: [Option; 2] = [no_copy(); 2]; - | ^^^^^^^^^ the trait `Copy` is not implemented for `Bar` + | ^^^^^^^^^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/consts/const-blocks/migrate-fail.stderr b/tests/ui/consts/const-blocks/migrate-fail.stderr index 3c116026e5804..3887658f74835 100644 --- a/tests/ui/consts/const-blocks/migrate-fail.stderr +++ b/tests/ui/consts/const-blocks/migrate-fail.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/migrate-fail.rs:11:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array @@ -18,7 +18,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/migrate-fail.rs:17:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/consts/const-blocks/nll-fail.stderr b/tests/ui/consts/const-blocks/nll-fail.stderr index ff2b62da66828..a2ea833f650e3 100644 --- a/tests/ui/consts/const-blocks/nll-fail.stderr +++ b/tests/ui/consts/const-blocks/nll-fail.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/nll-fail.rs:11:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array @@ -18,7 +18,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied --> $DIR/nll-fail.rs:17:38 | LL | let arr: [Option; 2] = [x; 2]; - | ^ the trait `Copy` is not implemented for `Bar` + | ^ the trait `Copy` is not implemented for `Bar`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 36249bf3f6d4e..b0b1378bb7de0 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/trait-error.rs:5:6 | LL | [Foo(String::new()); 4]; - | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`, which is required by `Foo: Copy` | note: required for `Foo` to implement `Copy` --> $DIR/trait-error.rs:1:10 diff --git a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs new file mode 100644 index 0000000000000..3f1f208459d17 --- /dev/null +++ b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.rs @@ -0,0 +1,5 @@ +// Regression test for issue #120615. + +fn main() { + [(); loop {}].field; //~ ERROR constant evaluation is taking a long time +} diff --git a/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr new file mode 100644 index 0000000000000..9d62bbc2187f7 --- /dev/null +++ b/tests/ui/consts/const-eval/field-access-after-const-eval-fail-in-ty.stderr @@ -0,0 +1,17 @@ +error: constant evaluation is taking a long time + --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10 + | +LL | [(); loop {}].field; + | ^^^^^^^ + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/field-access-after-const-eval-fail-in-ty.rs:4:10 + | +LL | [(); loop {}].field; + | ^^^^^^^ + = note: `#[deny(long_running_const_eval)]` on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs index 3341f3c78e0d6..47105de453cb1 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.rs +++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs @@ -1,4 +1,4 @@ -#![feature(const_mut_refs)] +#![feature(const_mut_refs, const_intrinsic_copy)] const MISALIGNED_LOAD: () = unsafe { diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr index 8eee392d15cd5..40fc4a876e9e5 100644 --- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr +++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr @@ -40,7 +40,6 @@ help: the constant being evaluated | LL | const Y: u32 = simple_loop(35); | ^^^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: constant evaluation is taking a long time --> $DIR/ctfe-simple-loop.rs:9:5 diff --git a/tests/ui/consts/const-fn-in-vec.stderr b/tests/ui/consts/const-fn-in-vec.stderr index 4593034bfaea3..12098e8199cd7 100644 --- a/tests/ui/consts/const-fn-in-vec.stderr +++ b/tests/ui/consts/const-fn-in-vec.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:1:47 | LL | static _MAYBE_STRINGS: [Option; 5] = [None; 5]; - | ^^^^ the trait `Copy` is not implemented for `String` + | ^^^^ the trait `Copy` is not implemented for `String`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array @@ -31,7 +31,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/const-fn-in-vec.rs:9:48 | LL | let _maybe_strings: [Option; 5] = [None; 5]; - | ^^^^ the trait `Copy` is not implemented for `String` + | ^^^^ the trait `Copy` is not implemented for `String`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index bec7b80890536..c834046c5b07f 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -3,6 +3,9 @@ const _: () = { for _ in 0..5 {} //~^ error: `for` is not allowed in a `const` + //~| ERROR: cannot convert + //~| ERROR: cannot call + //~| ERROR: mutable references }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index df79c00f024fd..413d144ca0ac3 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -8,6 +8,37 @@ LL | for _ in 0..5 {} = help: add `#![feature(const_for)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-try-feature-gate.rs b/tests/ui/consts/const-try-feature-gate.rs index 0839c23a0b99b..1cc045bf61249 100644 --- a/tests/ui/consts/const-try-feature-gate.rs +++ b/tests/ui/consts/const-try-feature-gate.rs @@ -3,6 +3,8 @@ const fn t() -> Option<()> { Some(())?; //~^ error: `?` is not allowed in a `const fn` + //~| ERROR: cannot convert + //~| ERROR: cannot determine None } diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index c5aeed3317cca..efa1fb107f624 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -8,6 +8,29 @@ LL | Some(())?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions + --> $DIR/const-try-feature-gate.rs:4:5 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions + --> $DIR/const-try-feature-gate.rs:4:5 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const_in_pattern/accept_structural.rs b/tests/ui/consts/const_in_pattern/accept_structural.rs index 1f56f581c0270..69b4e75c62236 100644 --- a/tests/ui/consts/const_in_pattern/accept_structural.rs +++ b/tests/ui/consts/const_in_pattern/accept_structural.rs @@ -63,4 +63,18 @@ fn main() { const ADDR_OF: &OND = &None; match &None { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + + // These ones are more subtle: the final value is fine, but statically analyzing the expression + // that computes the value would likely (incorrectly) have us conclude that this may match on + // values that do not have structural equality. + const INDEX: Option = [None, Some(NoDerive(10))][0]; + match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; + + const fn build() -> Option { None } + const CALL: Option = build(); + match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; + + impl NoDerive { const fn none() -> Option { None } } + const METHOD_CALL: Option = NoDerive::none(); + match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; } diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs index a38731ceb8a86..ac89b7925ffec 100644 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs +++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs @@ -12,6 +12,7 @@ impl PartialEq for CustomEq { } #[derive(PartialEq, Eq)] +#[allow(unused)] enum Foo { Bar, Baz, @@ -21,7 +22,7 @@ enum Foo { const BAR_BAZ: Foo = if 42 == 42 { Foo::Bar } else { - Foo::Baz + Foo::Qux(CustomEq) // dead arm }; fn main() { diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs deleted file mode 100644 index 34b1422dfb3cb..0000000000000 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs +++ /dev/null @@ -1,38 +0,0 @@ -// check-pass - -struct CustomEq; - -impl Eq for CustomEq {} -impl PartialEq for CustomEq { - fn eq(&self, _: &Self) -> bool { - false - } -} - -#[derive(PartialEq, Eq)] -enum Foo { - Bar, - Baz, - Qux(CustomEq), -} - -// We know that `BAR_BAZ` will always be `Foo::Bar` and thus eligible for structural matching, but -// dataflow will be more conservative. -const BAR_BAZ: Foo = if 42 == 42 { - Foo::Bar -} else { - Foo::Qux(CustomEq) -}; - -fn main() { - match Foo::Qux(CustomEq) { - BAR_BAZ => panic!(), - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details - //~| WARN this was previously accepted - //~| NOTE see issue #73448 - //~| NOTE `#[warn(nontrivial_structural_match)]` on by default - _ => {} - } -} diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr deleted file mode 100644 index c473c00f8dbbd..0000000000000 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr +++ /dev/null @@ -1,14 +0,0 @@ -warning: to use a constant of type `CustomEq` in a pattern, the constant's initializer must be trivial or `CustomEq` must be annotated with `#[derive(PartialEq)]` - --> $DIR/custom-eq-branch-warn.rs:29:9 - | -LL | BAR_BAZ => panic!(), - | ^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - = note: `#[warn(nontrivial_structural_match)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index 1546f23908c6f..bc1015c173426 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -5,7 +5,7 @@ LL | C => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 | @@ -19,7 +19,7 @@ LL | C_INNER => {} | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9 @@ -28,7 +28,7 @@ LL | D => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9 @@ -37,7 +37,67 @@ LL | STR => {} | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: aborting due to 4 previous errors +Future incompatibility report: Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:10:9 + | +LL | C => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9 + | +LL | C_INNER => {} + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9 + | +LL | D => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9 + | +LL | STR => {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 441aeecbc6d95..f5931f0cad08b 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -5,7 +5,7 @@ LL | FOO => println!("foo"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-44333.rs:3:9 | @@ -19,7 +19,37 @@ LL | BAR => println!("bar"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:19:9 + | +LL | FOO => println!("foo"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:21:9 + | +LL | BAR => println!("bar"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/issue-73431.stderr b/tests/ui/consts/const_in_pattern/issue-73431.stderr deleted file mode 100644 index c82dea4aa50df..0000000000000 --- a/tests/ui/consts/const_in_pattern/issue-73431.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448. diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index 196930baed5de..71d4138104db1 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -100,5 +100,5 @@ fn main() { //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details //~| WARN previously accepted by the compiler but is being phased out - //~| NOTE for more information, see issue #62411 + //~| NOTE for more information, see } diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index da32b6d698bb5..2c7aaf89aa787 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -86,7 +86,7 @@ LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops") | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -97,3 +97,20 @@ LL | #![warn(indirect_structural_match)] error: aborting due to 9 previous errors; 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/reject_non_structural.rs:98:29 + | +LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/reject_non_structural.rs:14:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs b/tests/ui/consts/const_in_pattern/warn_corner_cases.rs deleted file mode 100644 index 75f1965921c91..0000000000000 --- a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs +++ /dev/null @@ -1,41 +0,0 @@ -// run-pass - -// This test is checking our logic for structural match checking by enumerating -// the different kinds of const expressions. This test is collecting cases where -// we have accepted the const expression as a pattern in the past but we want -// to begin warning the user that a future version of Rust may start rejecting -// such const expressions. - -// The specific corner cases we are exploring here are instances where the -// const-evaluator computes a value that *does* meet the conditions for -// structural-match, but the const expression itself has abstractions (like -// calls to const functions) that may fit better with a type-based analysis -// rather than a commitment to a specific value. - -#![warn(indirect_structural_match)] - -#[derive(Copy, Clone, Debug)] -struct NoDerive(#[allow(dead_code)] u32); - -// This impl makes `NoDerive` irreflexive. -impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } -impl Eq for NoDerive { } - -fn main() { - const INDEX: Option = [None, Some(NoDerive(10))][0]; - match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted - - const fn build() -> Option { None } - const CALL: Option = build(); - match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted - - impl NoDerive { const fn none() -> Option { None } } - const METHOD_CALL: Option = NoDerive::none(); - match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted -} diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr b/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr deleted file mode 100644 index 8ffd035ebec61..0000000000000 --- a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr +++ /dev/null @@ -1,36 +0,0 @@ -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:26:47 - | -LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - = note: `#[warn(nontrivial_structural_match)]` on by default - -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:32:47 - | -LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:38:47 - | -LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; - | ^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -warning: 3 warnings emitted - diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index 2b8561a264488..5b7f8d29df7c6 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -51,10 +51,16 @@ const _: i32 = { let mut x = 0; for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR: cannot call + //~| ERROR: mutable references + //~| ERROR: cannot convert x += i; } for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR: cannot call + //~| ERROR: mutable references + //~| ERROR: cannot convert x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index 725adf723392d..e162a404ace8f 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -2,6 +2,9 @@ error[E0658]: `for` is not allowed in a `const` --> $DIR/loop.rs:53:5 | LL | / for i in 0..4 { +LL | | +LL | | +LL | | LL | | x += i; LL | | } | |_____^ @@ -11,9 +14,12 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:57:5 + --> $DIR/loop.rs:60:5 | LL | / for i in 0..4 { +LL | | +LL | | +LL | | LL | | x += i; LL | | } | |_____^ @@ -22,6 +28,67 @@ LL | | } = help: add `#![feature(const_for)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot convert `std::ops::Range` into an iterator in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs index 7d85a412b4722..5c6957df40566 100644 --- a/tests/ui/consts/control-flow/try.rs +++ b/tests/ui/consts/control-flow/try.rs @@ -4,6 +4,8 @@ const fn opt() -> Option { let x = Some(2); x?; //~ ERROR `?` is not allowed in a `const fn` + //~^ ERROR: cannot convert + //~| ERROR: cannot determine None } diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr index f4b88de9dfab3..f4c42c4d819b9 100644 --- a/tests/ui/consts/control-flow/try.stderr +++ b/tests/ui/consts/control-flow/try.stderr @@ -8,6 +8,29 @@ LL | x?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Option` in constant functions + --> $DIR/try.rs:6:5 + | +LL | x?; + | ^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option` in constant functions + --> $DIR/try.rs:6:5 + | +LL | x?; + | ^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index e6ea4108f4045..afe89461f031f 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -74,6 +74,100 @@ LL | T: ~const FnMut<()> + ~const Destruct, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 11 previous errors +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:17:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const Fn<()> + ~const Destruct + ~const std::ops::Fn<()>, + | +++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:13:23 + | +LL | const fn tester_fn(f: T) -> T::Output + | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:24:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const FnMut<()> + ~const Destruct + ~const std::ops::FnMut<()>, + | ++++++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:20:27 + | +LL | const fn tester_fn_mut(mut f: T) -> T::Output + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:31:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const FnOnce<()> + ~const std::ops::FnOnce<()>, + | +++++++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:34:21 + | +LL | const fn test_fn(mut f: T) -> (T::Output, T::Output, T::Output) + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:48:25 + | +LL | const fn test_fn_mut(mut f: T) -> (T::Output, T::Output) + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const operator in constants + --> $DIR/fn_trait_refs.rs:72:17 + | +LL | assert!(test_one == (1, 1, 1)); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const operator in constants + --> $DIR/fn_trait_refs.rs:75:17 + | +LL | assert!(test_two == (2, 2)); + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 20 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0493, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.rs b/tests/ui/consts/invalid-inline-const-in-match-arm.rs index 4d2d8fb1303ce..0654fd82fbc59 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.rs +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(inline_const_pat)] fn main() { diff --git a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr index db7db4b613181..a88c16158f324 100644 --- a/tests/ui/consts/invalid-inline-const-in-match-arm.stderr +++ b/tests/ui/consts/invalid-inline-const-in-match-arm.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const closure in constants - --> $DIR/invalid-inline-const-in-match-arm.rs:6:17 + --> $DIR/invalid-inline-const-in-match-arm.rs:5:17 | LL | const { (|| {})() } => {} | ^^^^^^^^^ diff --git a/tests/ui/consts/issue-104609.rs b/tests/ui/consts/issue-104609.rs index 01fd1c48cf803..9ee83b409c16f 100644 --- a/tests/ui/consts/issue-104609.rs +++ b/tests/ui/consts/issue-104609.rs @@ -5,6 +5,7 @@ fn foo() { unsafe fn bar() { std::mem::transmute::<_, *mut _>(1_u8); + //~^ ERROR: type annotations needed } fn main() {} diff --git a/tests/ui/consts/issue-104609.stderr b/tests/ui/consts/issue-104609.stderr index 8d0526978ed9e..fe84d83725fd2 100644 --- a/tests/ui/consts/issue-104609.stderr +++ b/tests/ui/consts/issue-104609.stderr @@ -4,6 +4,13 @@ error[E0425]: cannot find value `oops` in this scope LL | oops; | ^^^^ not found in this scope -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-104609.rs:7:5 + | +LL | std::mem::transmute::<_, *mut _>(1_u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Dst` declared on the function `transmute` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0282, E0425. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr index 03c47030c0e3f..b8c983eb7b81c 100644 --- a/tests/ui/consts/issue-54954.stderr +++ b/tests/ui/consts/issue-54954.stderr @@ -11,7 +11,7 @@ error[E0790]: cannot call associated function on trait without specifying the co --> $DIR/issue-54954.rs:1:24 | LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait ... LL | / const fn const_val() -> usize { LL | | diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr new file mode 100644 index 0000000000000..d5c5f76b90a01 --- /dev/null +++ b/tests/ui/consts/issue-89088.stderr @@ -0,0 +1,17 @@ +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-89088.rs:19:9 + | +LL | FOO => todo!(), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-89088.rs:5:10 + | +LL | #![allow(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr index 1f6abc0ce7c82..ace449fae9ce6 100644 --- a/tests/ui/consts/promoted_const_call.stderr +++ b/tests/ui/consts/promoted_const_call.stderr @@ -6,26 +6,6 @@ LL | let _: &'static _ = &id(&Panic); | | | the destructor for this type cannot be evaluated in constants -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:11: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:11: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:17:26 | @@ -68,7 +48,7 @@ LL | let _: &'static _ = &&(Panic, 0).1; LL | } | - temporary value is freed at the end of this statement -error: aborting due to 7 previous errors +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/tests/ui/consts/promoted_const_call3.rs b/tests/ui/consts/promoted_const_call3.rs index 6d68a2de70e47..dc05a3b584424 100644 --- a/tests/ui/consts/promoted_const_call3.rs +++ b/tests/ui/consts/promoted_const_call3.rs @@ -2,13 +2,14 @@ pub const fn id(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 +}; +pub const _: () = { 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 +}; +pub const _: () = { let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); //~^ ERROR: temporary value dropped while borrowed }; diff --git a/tests/ui/consts/promoted_const_call3.stderr b/tests/ui/consts/promoted_const_call3.stderr index af17457a10a1b..34c833d5bb77c 100644 --- a/tests/ui/consts/promoted_const_call3.stderr +++ b/tests/ui/consts/promoted_const_call3.stderr @@ -1,53 +1,22 @@ -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 | 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 +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call3.rs:8: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` + | ^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:12:26 + --> $DIR/promoted_const_call3.rs:13:26 | LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -58,7 +27,7 @@ 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 + --> $DIR/promoted_const_call3.rs:18:26 | LL | let _: &'static _ = &String::new(); | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -69,7 +38,7 @@ 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 + --> $DIR/promoted_const_call3.rs:21:26 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -80,7 +49,7 @@ 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 + --> $DIR/promoted_const_call3.rs:21:30 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement @@ -89,7 +58,7 @@ LL | let _: &'static _ = &id(&String::new()); | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:24:26 + --> $DIR/promoted_const_call3.rs:25:26 | LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -99,7 +68,7 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to 10 previous errors +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/tests/ui/consts/promoted_const_call5.rs b/tests/ui/consts/promoted_const_call5.rs index 3ac8d358ce485..41b3988949e65 100644 --- a/tests/ui/consts/promoted_const_call5.rs +++ b/tests/ui/consts/promoted_const_call5.rs @@ -25,9 +25,9 @@ pub const fn new_manually_drop(t: T) -> std::mem::ManuallyDrop { 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 +}; +const _: () = { let _: &'static _ = &new_manually_drop(new_string()); //~^ ERROR: temporary value dropped while borrowed }; diff --git a/tests/ui/consts/promoted_const_call5.stderr b/tests/ui/consts/promoted_const_call5.stderr index f736220b18333..1b5fa4352837e 100644 --- a/tests/ui/consts/promoted_const_call5.stderr +++ b/tests/ui/consts/promoted_const_call5.stderr @@ -6,26 +6,6 @@ LL | let _: &'static _ = &id(&new_string()); | | | 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 | @@ -68,7 +48,7 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to 7 previous errors +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/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.stderr index 843d6d9e04ba7..4089c850c8021 100644 --- a/tests/ui/consts/too_generic_eval_ice.stderr +++ b/tests/ui/consts/too_generic_eval_ice.stderr @@ -22,13 +22,13 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]` = help: the following other types implement trait `PartialEq`: - <[A; N] as PartialEq<[B; N]>> - <[A; N] as PartialEq<[B]>> - <[A; N] as PartialEq<&[B]>> - <[A; N] as PartialEq<&mut [B]>> + <[T; N] as PartialEq<[U; N]>> + <[T; N] as PartialEq<[U]>> + <[T; N] as PartialEq<&[U]>> + <[T; N] as PartialEq<&mut [U]>> <[T] as PartialEq>> - <[A] as PartialEq<[B]>> - <[B] as PartialEq<[A; N]>> + <[T] as PartialEq<[U; N]>> + <[T] as PartialEq<[U]>> <&[T] as PartialEq>> and 3 others diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs index 852a5b3b46a21..936931acbe2c8 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs @@ -5,7 +5,7 @@ fn main() { match &b""[..] { - ZST => {} + ZST => {} //~ ERROR: could not evaluate constant pattern } } diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr index 6bc7e7203aa74..e0d658db99760 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -7,6 +7,12 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; = note: source type: `usize` (word size) = note: target type: `&[u8]` (2 * word size) -error: aborting due to 1 previous error +error: could not evaluate constant pattern + --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9 + | +LL | ZST => {} + | ^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index bb8f606edf8e8..c19d1a6199d83 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -4,6 +4,51 @@ error[E0635]: unknown feature `const_convert` LL | #![feature(const_convert)] | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions + --> $DIR/try-operator.rs:10:9 + | +LL | Err(())?; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/result.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Result` in constant functions + --> $DIR/try-operator.rs:10:9 + | +LL | Err(())?; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/result.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions + --> $DIR/try-operator.rs:18:9 + | +LL | None?; + | ^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions + --> $DIR/try-operator.rs:18:9 + | +LL | None?; + | ^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/underscore_const_names.rs b/tests/ui/consts/underscore_const_names.rs index d0e625bf1997a..e2ae5a9d53aac 100644 --- a/tests/ui/consts/underscore_const_names.rs +++ b/tests/ui/consts/underscore_const_names.rs @@ -2,12 +2,12 @@ #![deny(unused)] -trait Trt {} +pub trait Trt {} pub struct Str {} impl Trt for Str {} macro_rules! check_impl { - ($struct:ident,$trait:ident) => { + ($struct:ident, $trait:ident) => { const _ : () = { use std::marker::PhantomData; struct ImplementsTrait(PhantomData); diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 08147a4afaf37..ee4a0f6a8436b 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -4,5 +4,38 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn unwrap_or_else T>(self, f: F) -> T { | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/unstable-const-fn-in-libcore.rs:24:26 + | +LL | Opt::None => f(), + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn unwrap_or_else T + ~const std::ops::FnOnce<()>>(self, f: F) -> T { + | +++++++++++++++++++++++++++++ + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:60 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0493]: destructor of `Opt` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:54 + | +LL | const fn unwrap_or_else T>(self, f: F) -> T { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to 4 previous errors +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr index 82a6d0495c003..1d4804501d8bc 100644 --- a/tests/ui/coroutine/clone-impl.stderr +++ b/tests/ui/coroutine/clone-impl.stderr @@ -5,7 +5,7 @@ LL | let gen_clone_0 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:40:14 @@ -25,7 +25,7 @@ LL | let gen_clone_0 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:36:23: 36:30}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield --> $DIR/clone-impl.rs:38:9 @@ -47,7 +47,7 @@ LL | let gen_clone_1 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:56:14 @@ -67,7 +67,7 @@ LL | let gen_clone_1 = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}`, the trait `Copy` is not implemented for `Vec`, which is required by `{coroutine@$DIR/clone-impl.rs:46:23: 46:30}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield --> $DIR/clone-impl.rs:52:9 @@ -90,7 +90,7 @@ LL | let gen_non_clone = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Copy` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Copy` | note: captured value does not implement `Copy` --> $DIR/clone-impl.rs:64:14 @@ -115,7 +115,7 @@ LL | let gen_non_clone = move || { | ------- within this `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}`, the trait `Clone` is not implemented for `NonClone`, which is required by `{coroutine@$DIR/clone-impl.rs:62:25: 62:32}: Clone` | note: captured value does not implement `Clone` --> $DIR/clone-impl.rs:64:14 diff --git a/tests/ui/coroutine/drop-tracking-parent-expression.stderr b/tests/ui/coroutine/drop-tracking-parent-expression.stderr index 6cd4ec83377d9..21aa35b9579bc 100644 --- a/tests/ui/coroutine/drop-tracking-parent-expression.stderr +++ b/tests/ui/coroutine/drop-tracking-parent-expression.stderr @@ -2,7 +2,7 @@ error: coroutine cannot be sent between threads safely --> $DIR/drop-tracking-parent-expression.rs:23:13 | LL | assert_send(g); - | ^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^ coroutine is not `Send` ... LL | / type_combinations!( LL | | // OK @@ -13,7 +13,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | @@ -42,7 +42,7 @@ error: coroutine cannot be sent between threads safely --> $DIR/drop-tracking-parent-expression.rs:23:13 | LL | assert_send(g); - | ^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^ coroutine is not `Send` ... LL | / type_combinations!( LL | | // OK @@ -53,7 +53,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | @@ -82,7 +82,7 @@ error: coroutine cannot be sent between threads safely --> $DIR/drop-tracking-parent-expression.rs:23:13 | LL | assert_send(g); - | ^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^ coroutine is not `Send` ... LL | / type_combinations!( LL | | // OK @@ -93,7 +93,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client` + = help: within `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/drop-tracking-parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-tracking-parent-expression.rs:21:22 | diff --git a/tests/ui/coroutine/drop-yield-twice.stderr b/tests/ui/coroutine/drop-yield-twice.stderr index b37c27015fb2e..c6a9e20b8b51f 100644 --- a/tests/ui/coroutine/drop-yield-twice.stderr +++ b/tests/ui/coroutine/drop-yield-twice.stderr @@ -1,10 +1,15 @@ error: coroutine cannot be sent between threads safely --> $DIR/drop-yield-twice.rs:7:5 | -LL | assert_send(|| { - | ^^^^^^^^^^^ coroutine is not `Send` +LL | / assert_send(|| { +LL | | let guard = Foo(42); +LL | | yield; +LL | | drop(guard); +LL | | yield; +LL | | }) + | |______^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo` + = help: within `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}`, the trait `Send` is not implemented for `Foo`, which is required by `{coroutine@$DIR/drop-yield-twice.rs:7:17: 7:19}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/drop-yield-twice.rs:9:9 | diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr index 38f114ff7747f..c8a6522dbd938 100644 --- a/tests/ui/coroutine/issue-105084.stderr +++ b/tests/ui/coroutine/issue-105084.stderr @@ -29,7 +29,7 @@ LL | let mut g = || { | -- within this `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}` ... LL | let mut h = copy(g); - | ^^^^ within `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>` + | ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}`, the trait `Copy` is not implemented for `Box<(i32, ())>`, which is required by `{coroutine@$DIR/issue-105084.rs:14:17: 14:19}: Copy` | note: coroutine does not implement `Copy` as this value is used across a yield --> $DIR/issue-105084.rs:21:22 diff --git a/tests/ui/coroutine/issue-68112.stderr b/tests/ui/coroutine/issue-68112.stderr index 5efa72ad5fe02..ded325eda544c 100644 --- a/tests/ui/coroutine/issue-68112.stderr +++ b/tests/ui/coroutine/issue-68112.stderr @@ -2,9 +2,9 @@ error: coroutine cannot be sent between threads safely --> $DIR/issue-68112.rs:40:5 | LL | require_send(send_gen); - | ^^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:33:20: 33:22}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: coroutine is not `Send` as this value is used across a yield --> $DIR/issue-68112.rs:36:9 @@ -24,9 +24,9 @@ error[E0277]: `RefCell` cannot be shared between threads safely --> $DIR/issue-68112.rs:64:5 | LL | require_send(send_gen); - | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{coroutine@$DIR/issue-68112.rs:60:20: 60:22}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this coroutine diff --git a/tests/ui/coroutine/not-send-sync.stderr b/tests/ui/coroutine/not-send-sync.stderr index b33a1e63aafd2..9228340c710dd 100644 --- a/tests/ui/coroutine/not-send-sync.stderr +++ b/tests/ui/coroutine/not-send-sync.stderr @@ -1,10 +1,15 @@ error: coroutine cannot be shared between threads safely --> $DIR/not-send-sync.rs:14:5 | -LL | assert_sync(|| { - | ^^^^^^^^^^^ coroutine is not `Sync` - | - = help: within `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync` +LL | / assert_sync(|| { +LL | | +LL | | let a = NotSync; +LL | | yield; +LL | | drop(a); +LL | | }); + | |______^ coroutine is not `Sync` + | + = help: within `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{coroutine@$DIR/not-send-sync.rs:14:17: 14:19}: Sync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/not-send-sync.rs:17:9 | @@ -21,10 +26,15 @@ LL | fn assert_sync(_: T) {} error: coroutine cannot be sent between threads safely --> $DIR/not-send-sync.rs:21:5 | -LL | assert_send(|| { - | ^^^^^^^^^^^ coroutine is not `Send` +LL | / assert_send(|| { +LL | | +LL | | let a = NotSend; +LL | | yield; +LL | | drop(a); +LL | | }); + | |______^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend` + = help: within `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}`, the trait `Send` is not implemented for `NotSend`, which is required by `{coroutine@$DIR/not-send-sync.rs:21:17: 21:19}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/not-send-sync.rs:24:9 | diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr index 6b611bc3f103e..5b3737069e6c1 100644 --- a/tests/ui/coroutine/parent-expression.stderr +++ b/tests/ui/coroutine/parent-expression.stderr @@ -2,7 +2,7 @@ error: coroutine cannot be sent between threads safely --> $DIR/parent-expression.rs:23:13 | LL | assert_send(g); - | ^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^ coroutine is not `Send` ... LL | / type_combinations!( LL | | // OK @@ -13,7 +13,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client` + = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `derived_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | @@ -42,7 +42,7 @@ error: coroutine cannot be sent between threads safely --> $DIR/parent-expression.rs:23:13 | LL | assert_send(g); - | ^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^ coroutine is not `Send` ... LL | / type_combinations!( LL | | // OK @@ -53,7 +53,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client` + = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `significant_drop::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | @@ -82,7 +82,7 @@ error: coroutine cannot be sent between threads safely --> $DIR/parent-expression.rs:23:13 | LL | assert_send(g); - | ^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^ coroutine is not `Send` ... LL | / type_combinations!( LL | | // OK @@ -93,7 +93,7 @@ LL | | }; LL | | ); | |_____- in this macro invocation | - = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client` + = help: within `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}`, the trait `Send` is not implemented for `insignificant_dtor::Client`, which is required by `{coroutine@$DIR/parent-expression.rs:17:21: 17:28}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/parent-expression.rs:21:22 | diff --git a/tests/ui/coroutine/polymorphize-args.rs b/tests/ui/coroutine/polymorphize-args.rs new file mode 100644 index 0000000000000..de44d667656c4 --- /dev/null +++ b/tests/ui/coroutine/polymorphize-args.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zpolymorphize=on +// build-pass + +#![feature(coroutines, coroutine_trait)] + +use std::ops::Coroutine; +use std::pin::Pin; +use std::thread; + +fn main() { + let mut foo = || yield; + thread::spawn(move || match Pin::new(&mut foo).resume(()) { + s => panic!("bad state: {:?}", s), + }) + .join() + .unwrap(); +} diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr index bcdcbc154cf0a..1b9ca632f0cb6 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-1.stderr @@ -2,9 +2,9 @@ error: coroutine cannot be sent between threads safely --> $DIR/coroutine-print-verbose-1.rs:37:5 | LL | require_send(send_gen); - | ^^^^^^^^^^^^ coroutine is not `Send` + | ^^^^^^^^^^^^^^^^^^^^^^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{test1::{closure#0} upvar_tys=() witness={test1::{closure#0}}}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-1.rs:35:9 @@ -23,9 +23,9 @@ error[E0277]: `RefCell` cannot be shared between threads safely --> $DIR/coroutine-print-verbose-1.rs:56:5 | LL | require_send(send_gen); - | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely + | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `{test2::{closure#0} upvar_tys=() witness={test2::{closure#0}}}: Send` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Arc>` to implement `Send` note: required because it's used within this coroutine diff --git a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr index 165302ab1406f..26c9c27743c01 100644 --- a/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr +++ b/tests/ui/coroutine/print/coroutine-print-verbose-2.stderr @@ -1,10 +1,15 @@ error: coroutine cannot be shared between threads safely --> $DIR/coroutine-print-verbose-2.rs:17:5 | -LL | assert_sync(|| { - | ^^^^^^^^^^^ coroutine is not `Sync` - | - = help: within `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync` +LL | / assert_sync(|| { +LL | | +LL | | let a = NotSync; +LL | | yield; +LL | | drop(a); +LL | | }); + | |______^ coroutine is not `Sync` + | + = help: within `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}`, the trait `Sync` is not implemented for `NotSync`, which is required by `{main::{closure#0} upvar_tys=() witness={main::{closure#0}}}: Sync` note: coroutine is not `Sync` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:20:9 | @@ -21,10 +26,15 @@ LL | fn assert_sync(_: T) {} error: coroutine cannot be sent between threads safely --> $DIR/coroutine-print-verbose-2.rs:24:5 | -LL | assert_send(|| { - | ^^^^^^^^^^^ coroutine is not `Send` +LL | / assert_send(|| { +LL | | +LL | | let a = NotSend; +LL | | yield; +LL | | drop(a); +LL | | }); + | |______^ coroutine is not `Send` | - = help: within `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend` + = help: within `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}`, the trait `Send` is not implemented for `NotSend`, which is required by `{main::{closure#1} upvar_tys=() witness={main::{closure#1}}}: Send` note: coroutine is not `Send` as this value is used across a yield --> $DIR/coroutine-print-verbose-2.rs:27:9 | diff --git a/tests/ui/coroutine/ref-upvar-not-send.stderr b/tests/ui/coroutine/ref-upvar-not-send.stderr index 7f18c6fba775f..0f91bcf40533f 100644 --- a/tests/ui/coroutine/ref-upvar-not-send.stderr +++ b/tests/ui/coroutine/ref-upvar-not-send.stderr @@ -10,7 +10,7 @@ LL | | let _x = x; LL | | }); | |_____^ coroutine is not `Send` | - = help: the trait `Sync` is not implemented for `*mut ()` + = help: the trait `Sync` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:15:17: 15:24}: Send` note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync` --> $DIR/ref-upvar-not-send.rs:19:18 | @@ -34,7 +34,7 @@ LL | | let _y = y; LL | | }); | |_____^ coroutine is not `Send` | - = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()` + = help: within `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}`, the trait `Send` is not implemented for `*mut ()`, which is required by `{coroutine@$DIR/ref-upvar-not-send.rs:23:17: 23:24}: Send` note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send` --> $DIR/ref-upvar-not-send.rs:27:18 | diff --git a/tests/ui/coroutine/sized-yield.stderr b/tests/ui/coroutine/sized-yield.stderr index bbecaffa95a12..4e8dc13201de3 100644 --- a/tests/ui/coroutine/sized-yield.stderr +++ b/tests/ui/coroutine/sized-yield.stderr @@ -18,7 +18,7 @@ LL | Pin::new(&mut gen).resume(()); | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` -note: required by a bound in `CoroutineState` +note: required by an implicit `Sized` bound in `CoroutineState` --> $SRC_DIR/core/src/ops/coroutine.rs:LL:COL error: aborting due to 2 previous errors diff --git a/tests/ui/coroutine/unresolved-ct-var.stderr b/tests/ui/coroutine/unresolved-ct-var.stderr index da2ec272f9fff..8b87bac05acb2 100644 --- a/tests/ui/coroutine/unresolved-ct-var.stderr +++ b/tests/ui/coroutine/unresolved-ct-var.stderr @@ -8,7 +8,7 @@ LL | let s = std::array::from_fn(|_| ()).await; | | help: remove the `.await` | this call returns `[(); _]` | - = help: the trait `Future` is not implemented for `[(); _]` + = help: the trait `Future` is not implemented for `[(); _]`, which is required by `[(); _]: IntoFuture` = note: [(); _] must be a future or must implement `IntoFuture` to be awaited = note: required for `[(); _]` to implement `IntoFuture` diff --git a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr index f28f8913508f2..8f8bec9945847 100644 --- a/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr +++ b/tests/ui/coroutine/yield-outside-coroutine-issue-78653.stderr @@ -10,7 +10,7 @@ error[E0277]: `{integer}` is not an iterator LL | yield || for i in 0 { } | ^ `{integer}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{integer}` + = help: the trait `Iterator` is not implemented for `{integer}`, which is required by `{integer}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{integer}` to implement `IntoIterator` diff --git a/tests/ui/default-method-parsing.rs b/tests/ui/default-method-parsing.rs index 9ffb8d94a59b3..5001d58f0a48e 100644 --- a/tests/ui/default-method-parsing.rs +++ b/tests/ui/default-method-parsing.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/delegation/target-expr-pass.rs b/tests/ui/delegation/target-expr-pass.rs index 56068dfce01d7..4ccb81c292aa5 100644 --- a/tests/ui/delegation/target-expr-pass.rs +++ b/tests/ui/delegation/target-expr-pass.rs @@ -14,14 +14,14 @@ reuse to_reuse::foo {{ x + self }} -trait Trait { +trait Trait { //~ WARN trait `Trait` is never used fn bar(&self, x: i32) -> i32 { x } } -struct F; +struct F; //~ WARN struct `F` is never constructed impl Trait for F {} -struct S(F); +struct S(F); //~ WARN struct `S` is never constructed impl Trait for S { reuse ::bar { #[allow(unused_imports)] diff --git a/tests/ui/delegation/target-expr-pass.stderr b/tests/ui/delegation/target-expr-pass.stderr index ea594f8a26a5b..dd1f3a14e0bd8 100644 --- a/tests/ui/delegation/target-expr-pass.stderr +++ b/tests/ui/delegation/target-expr-pass.stderr @@ -7,5 +7,25 @@ LL | #![feature(fn_delegation)] = note: see issue #118212 for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +warning: trait `Trait` is never used + --> $DIR/target-expr-pass.rs:17:7 + | +LL | trait Trait { + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: struct `F` is never constructed + --> $DIR/target-expr-pass.rs:21:8 + | +LL | struct F; + | ^ + +warning: struct `S` is never constructed + --> $DIR/target-expr-pass.rs:24:8 + | +LL | struct S(F); + | ^ + +warning: 4 warnings emitted diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 61268ffc7f852..13ba80243a5eb 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -15,9 +15,6 @@ note: trait bound `NotClone: Clone` was not satisfied | LL | #[derive(Clone)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `Clone` help: consider annotating `NotClone` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr index 3f6c39bf9396e..b10805ac8f06f 100644 --- a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr @@ -7,7 +7,7 @@ LL | #[derive(Debug)] LL | x: Error | ^^^^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/derives/derives-span-Debug-enum.stderr b/tests/ui/derives/derives-span-Debug-enum.stderr index eaeffaeb84956..0329744390166 100644 --- a/tests/ui/derives/derives-span-Debug-enum.stderr +++ b/tests/ui/derives/derives-span-Debug-enum.stderr @@ -7,7 +7,7 @@ LL | #[derive(Debug)] LL | Error | ^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/derives/derives-span-Debug-struct.stderr b/tests/ui/derives/derives-span-Debug-struct.stderr index 4a725e260deae..369c0b56ac4e8 100644 --- a/tests/ui/derives/derives-span-Debug-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-struct.stderr @@ -7,7 +7,7 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr index 2f816e1c85b25..abfef9ef35425 100644 --- a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr @@ -7,7 +7,7 @@ LL | struct Struct( LL | Error | ^^^^^ `Error` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Error` + = help: the trait `Debug` is not implemented for `Error`, which is required by `&Error: Debug` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` diff --git a/tests/ui/derives/issue-36617.rs b/tests/ui/derives/issue-36617.rs index 08f293d2ebb06..236ec7748cbdd 100644 --- a/tests/ui/derives/issue-36617.rs +++ b/tests/ui/derives/issue-36617.rs @@ -1,16 +1,16 @@ -#![derive(Copy)] //~ ERROR cannot determine resolution for the attribute macro `derive` +#![derive(Copy)] //~^ ERROR `derive` attribute cannot be used at crate level -#![test]//~ ERROR cannot determine resolution for the attribute macro `test` +#![test] //~^ ERROR `test` attribute cannot be used at crate level -#![test_case]//~ ERROR cannot determine resolution for the attribute macro `test_case` +#![test_case] //~^ ERROR `test_case` attribute cannot be used at crate level -#![bench]//~ ERROR cannot determine resolution for the attribute macro `bench` +#![bench] //~^ ERROR `bench` attribute cannot be used at crate level -#![global_allocator]//~ ERROR cannot determine resolution for the attribute macro `global_allocator` +#![global_allocator] //~^ ERROR `global_allocator` attribute cannot be used at crate level fn main() {} diff --git a/tests/ui/derives/issue-36617.stderr b/tests/ui/derives/issue-36617.stderr index 98be7963e5ef9..3de1d87c5046c 100644 --- a/tests/ui/derives/issue-36617.stderr +++ b/tests/ui/derives/issue-36617.stderr @@ -1,43 +1,3 @@ -error: cannot determine resolution for the attribute macro `derive` - --> $DIR/issue-36617.rs:1:4 - | -LL | #![derive(Copy)] - | ^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-36617.rs:4:4 - | -LL | #![test] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `test_case` - --> $DIR/issue-36617.rs:7:4 - | -LL | #![test_case] - | ^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `bench` - --> $DIR/issue-36617.rs:10:4 - | -LL | #![bench] - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `global_allocator` - --> $DIR/issue-36617.rs:13:4 - | -LL | #![global_allocator] - | ^^^^^^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `derive` attribute cannot be used at crate level --> $DIR/issue-36617.rs:1:1 | @@ -113,5 +73,5 @@ LL - #![global_allocator] LL + #[global_allocator] | -error: aborting due to 10 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/deriving/deriving-bounds.rs b/tests/ui/deriving/deriving-bounds.rs index f0b921d0e7c0e..f3e7cf99437d5 100644 --- a/tests/ui/deriving/deriving-bounds.rs +++ b/tests/ui/deriving/deriving-bounds.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #[derive(Copy, Clone)] struct Test; diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr index 384899ea43334..f76701860efb5 100644 --- a/tests/ui/deriving/issue-103157.stderr +++ b/tests/ui/deriving/issue-103157.stderr @@ -5,7 +5,7 @@ LL | #[derive(PartialEq, Eq)] | -- in this derive macro expansion ... LL | Float(Option), - | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64` + | ^^^^^^^^^^^ the trait `Eq` is not implemented for `f64`, which is required by `Option: Eq` | = help: the following other types implement trait `Eq`: isize diff --git a/tests/ui/diagnostic-width/tabs-trimming.rs b/tests/ui/diagnostic-width/tabs-trimming.rs index ade21753b457c..96babde33e9a4 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.rs +++ b/tests/ui/diagnostic-width/tabs-trimming.rs @@ -8,6 +8,7 @@ match money { v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT //~^ ERROR variable `v` is not bound in all patterns + //~| ERROR possibly-uninitialized v => println!("Enough money {}", v), } } diff --git a/tests/ui/diagnostic-width/tabs-trimming.stderr b/tests/ui/diagnostic-width/tabs-trimming.stderr index 2aa4fc18c3d65..85103fbf6f591 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.stderr +++ b/tests/ui/diagnostic-width/tabs-trimming.stderr @@ -7,6 +7,18 @@ LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Lon | | pattern doesn't bind `v` | variable not in all patterns -error: aborting due to 1 previous error +error[E0381]: used binding `v` is possibly-uninitialized + --> $DIR/tabs-trimming.rs:9:67 + | +LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... + | - ^ `v` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions + | binding declared here but left uninitialized + | + = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0381, E0408. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/did_you_mean/recursion_limit.stderr b/tests/ui/did_you_mean/recursion_limit.stderr index bff57a63deb16..2ecee2030b03f 100644 --- a/tests/ui/did_you_mean/recursion_limit.stderr +++ b/tests/ui/did_you_mean/recursion_limit.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `J: Send` --> $DIR/recursion_limit.rs:34:5 | LL | is_send::(); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit`) note: required because it appears within the type `I` diff --git a/tests/ui/drop/drop-struct-as-object.rs b/tests/ui/drop/drop-struct-as-object.rs index 377027a4fc5f2..1aa6877704253 100644 --- a/tests/ui/drop/drop-struct-as-object.rs +++ b/tests/ui/drop/drop-struct-as-object.rs @@ -12,7 +12,7 @@ struct Cat { } trait Dummy { - fn get(&self) -> usize; + fn get(&self) -> usize; //~ WARN method `get` is never used } impl Dummy for Cat { diff --git a/tests/ui/drop/drop-struct-as-object.stderr b/tests/ui/drop/drop-struct-as-object.stderr new file mode 100644 index 0000000000000..10527c968ed70 --- /dev/null +++ b/tests/ui/drop/drop-struct-as-object.stderr @@ -0,0 +1,12 @@ +warning: method `get` is never used + --> $DIR/drop-struct-as-object.rs:15:8 + | +LL | trait Dummy { + | ----- method in this trait +LL | fn get(&self) -> usize; + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.rs b/tests/ui/drop/recursion-check-on-erroneous-impl.rs new file mode 100644 index 0000000000000..733c8b0b08590 --- /dev/null +++ b/tests/ui/drop/recursion-check-on-erroneous-impl.rs @@ -0,0 +1,11 @@ +// can't use build-fail, because this also fails check-fail, but +// the ICE from #120787 only reproduces on build-fail. +// compile-flags: --emit=mir + +struct PrintOnDrop<'a>(&'a str); + +impl Drop for PrintOnDrop<'_> { + fn drop() {} //~ ERROR method `drop` has a `&mut self` declaration in the trait +} + +fn main() {} diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.stderr b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr new file mode 100644 index 0000000000000..831adb88cefac --- /dev/null +++ b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr @@ -0,0 +1,11 @@ +error[E0186]: method `drop` has a `&mut self` declaration in the trait, but not in the impl + --> $DIR/recursion-check-on-erroneous-impl.rs:8:5 + | +LL | fn drop() {} + | ^^^^^^^^^ expected `&mut self` in impl + | + = note: `drop` from trait: `fn(&mut Self)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0186`. diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr index c7e9854340f09..554e81bee10a5 100644 --- a/tests/ui/dst/dst-bad-deep-2.stderr +++ b/tests/ui/dst/dst-bad-deep-2.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilati LL | let h: &(([isize],),) = &(*g,); | ^^^^^ doesn't have a size known at compile-time | - = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]` + = help: within `(([isize],),)`, the trait `Sized` is not implemented for `[isize]`, which is required by `(([isize],),): Sized` = note: required because it appears within the type `([isize],)` = note: required because it appears within the type `(([isize],),)` = note: tuples must have a statically known size to be initialized diff --git a/tests/ui/dst/dst-bad-deep.stderr b/tests/ui/dst/dst-bad-deep.stderr index 1b0f9738ab09a..4f180e593f8ae 100644 --- a/tests/ui/dst/dst-bad-deep.stderr +++ b/tests/ui/dst/dst-bad-deep.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[isize]` cannot be known at compilati LL | let h: &Fat> = &Fat { ptr: *g }; | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Fat>`, the trait `Sized` is not implemented for `[isize]` + = help: within `Fat>`, the trait `Sized` is not implemented for `[isize]`, which is required by `Fat>: Sized` note: required because it appears within the type `Fat<[isize]>` --> $DIR/dst-bad-deep.rs:6:8 | diff --git a/tests/ui/dst/dst-sized-trait-param.stderr b/tests/ui/dst/dst-sized-trait-param.stderr index 60e9de90332cc..2ac666c8a2cc7 100644 --- a/tests/ui/dst/dst-sized-trait-param.stderr +++ b/tests/ui/dst/dst-sized-trait-param.stderr @@ -5,11 +5,11 @@ LL | impl Foo<[isize]> for usize { } | ^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[isize]` -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/dst-sized-trait-param.rs:5:11 | LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized - | ^ required by this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: consider relaxing the implicit `Sized` restriction | LL | trait Foo : Sized { fn take(self, x: &T) { } } // Note: T is sized diff --git a/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr index 6752a484448c5..2d7956f1958c5 100644 --- a/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr +++ b/tests/ui/dst/issue-90528-unsizing-not-suggestion-110063.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `[u8; 1]: Test` is not satisfied --> $DIR/issue-90528-unsizing-not-suggestion-110063.rs:11:22 | LL | let x: [u8; 1] = needs_test(); - | ^^^^^^^^^^ the trait `Test` is not implemented for `[u8; 1]` + | ^^^^^^^^^^^^ the trait `Test` is not implemented for `[u8; 1]` | = help: the trait `Test` is implemented for `&[u8]` note: required by a bound in `needs_test` diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs index a074b5fa5f7aa..23ca36b71e00f 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs @@ -6,14 +6,6 @@ fn function(x: &SomeTrait, y: Box) { //~| WARN this is accepted in the current edition //~| ERROR trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition let _x: &SomeTrait = todo!(); //~^ ERROR trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr index f70b329eafb0f..711bfa188ecd8 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -30,7 +30,7 @@ LL | fn function(x: &SomeTrait, y: Box) { | +++ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:17:14 + --> $DIR/dyn-2018-edition-lint.rs:9:14 | LL | let _x: &SomeTrait = todo!(); | ^^^^^^^^^ @@ -42,61 +42,5 @@ help: if this is an object-safe trait, use `dyn` LL | let _x: &dyn SomeTrait = todo!(); | +++ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:17 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn function(x: &dyn SomeTrait, y: Box) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:17 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn function(x: &dyn SomeTrait, y: Box) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:35 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn function(x: &SomeTrait, y: Box) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:35 - | -LL | fn function(x: &SomeTrait, y: Box) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn function(x: &SomeTrait, y: Box) { - | +++ - -error: aborting due to 7 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/dynamically-sized-types/dst-coercions.rs b/tests/ui/dynamically-sized-types/dst-coercions.rs index 66688e93fb80d..1efdf1de0e61c 100644 --- a/tests/ui/dynamically-sized-types/dst-coercions.rs +++ b/tests/ui/dynamically-sized-types/dst-coercions.rs @@ -5,7 +5,7 @@ // pretty-expanded FIXME #23616 struct S; -trait T { fn dummy(&self) { } } +trait T { fn dummy(&self) { } } //~ WARN method `dummy` is never used impl T for S {} pub fn main() { diff --git a/tests/ui/dynamically-sized-types/dst-coercions.stderr b/tests/ui/dynamically-sized-types/dst-coercions.stderr new file mode 100644 index 0000000000000..e4721ce50a045 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-coercions.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/dst-coercions.rs:8:14 + | +LL | trait T { fn dummy(&self) { } } + | - ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/empty-type-parameter-list.rs b/tests/ui/empty-type-parameter-list.rs index e168cd03b2746..23d09fbf281d0 100644 --- a/tests/ui/empty-type-parameter-list.rs +++ b/tests/ui/empty-type-parameter-list.rs @@ -3,7 +3,7 @@ // no type parameters at all struct S<>; -trait T<> {} +trait T<> {} //~ WARN trait `T` is never used enum E<> { V } impl<> T<> for S<> {} impl T for E {} diff --git a/tests/ui/empty-type-parameter-list.stderr b/tests/ui/empty-type-parameter-list.stderr new file mode 100644 index 0000000000000..31a5015e99349 --- /dev/null +++ b/tests/ui/empty-type-parameter-list.stderr @@ -0,0 +1,10 @@ +warning: trait `T` is never used + --> $DIR/empty-type-parameter-list.rs:6:7 + | +LL | trait T<> {} + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr index fac3ce07aeb92..1341b03cb56e4 100644 --- a/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr +++ b/tests/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr @@ -6,14 +6,14 @@ LL | Some = std::mem::size_of::(), | = note: type parameters may not be used in enum discriminant values -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-70453-generics-in-discr-ice.rs:7:20 | LL | enum MyWeirdOption { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/enum/enum-and-module-in-same-scope.rs b/tests/ui/enum/enum-and-module-in-same-scope.rs index cc6e199bd7ca0..8e69c89d792ff 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.rs +++ b/tests/ui/enum/enum-and-module-in-same-scope.rs @@ -5,6 +5,7 @@ enum Foo { mod Foo { //~ ERROR the name `Foo` is defined multiple times pub static X: isize = 42; fn f() { f() } // Check that this does not result in a resolution error + //~^ WARN cannot return without recursing } fn main() {} diff --git a/tests/ui/enum/enum-and-module-in-same-scope.stderr b/tests/ui/enum/enum-and-module-in-same-scope.stderr index 0293acd6201b2..f1c02af595ffd 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.stderr +++ b/tests/ui/enum/enum-and-module-in-same-scope.stderr @@ -9,6 +9,17 @@ LL | mod Foo { | = note: `Foo` must be defined only once in the type namespace of this module -error: aborting due to 1 previous error +warning: function cannot return without recursing + --> $DIR/enum-and-module-in-same-scope.rs:7:5 + | +LL | fn f() { f() } // Check that this does not result in a resolution error + | ^^^^^^ --- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/enum/issue-67945-1.stderr b/tests/ui/enum/issue-67945-1.stderr index 878fa322f02d5..ce0ea77763663 100644 --- a/tests/ui/enum/issue-67945-1.stderr +++ b/tests/ui/enum/issue-67945-1.stderr @@ -6,14 +6,14 @@ LL | let x: S = 0; | = note: type parameters may not be used in enum discriminant values -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-1.rs:1:10 | LL | enum Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/enum/issue-67945-2.stderr b/tests/ui/enum/issue-67945-2.stderr index f8ec12d470acf..96bd08f841a40 100644 --- a/tests/ui/enum/issue-67945-2.stderr +++ b/tests/ui/enum/issue-67945-2.stderr @@ -6,14 +6,14 @@ LL | Var = type_ascribe!(0, S), | = note: type parameters may not be used in enum discriminant values -error[E0392]: parameter `S` is never used +error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-2.rs:3:10 | LL | enum Bug { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `S` to be a const parameter, use `const S: usize` instead + = help: if you intended `S` to be a const parameter, use `const S: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0091.stderr b/tests/ui/error-codes/E0091.stderr index a596b75e481de..c1427ec66863a 100644 --- a/tests/ui/error-codes/E0091.stderr +++ b/tests/ui/error-codes/E0091.stderr @@ -1,14 +1,20 @@ -error[E0091]: type parameter `T` is unused +error[E0091]: type parameter `T` is never used --> $DIR/E0091.rs:1:10 | LL | type Foo = u32; | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0091]: type parameter `B` is unused +error[E0091]: type parameter `B` is never used --> $DIR/E0091.rs:2:14 | LL | type Foo2 = Box; | ^ unused type parameter + | + = help: consider removing `B` or referring to it in the body of the type alias + = help: if you intended `B` to be a const parameter, use `const B: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0117.rs b/tests/ui/error-codes/E0117.rs index 406d24e366614..32b9863806c04 100644 --- a/tests/ui/error-codes/E0117.rs +++ b/tests/ui/error-codes/E0117.rs @@ -1,4 +1,5 @@ impl Drop for u32 {} //~ ERROR E0117 //~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions +//~| ERROR not all trait items implemented fn main() {} diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr index f144aa9f72c13..058a64b20d171 100644 --- a/tests/ui/error-codes/E0117.stderr +++ b/tests/ui/error-codes/E0117.stderr @@ -15,7 +15,15 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums, LL | impl Drop for u32 {} | ^^^ must be a struct, enum, or union in the current crate -error: aborting due to 2 previous errors +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/E0117.rs:1:1 + | +LL | impl Drop for u32 {} + | ^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `fn drop(&mut self) { todo!() }` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0117, E0120. -For more information about an error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0046, E0117, E0120. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/error-codes/E0120.rs b/tests/ui/error-codes/E0120.rs index a0a301a06e2ed..35f544fddfbfc 100644 --- a/tests/ui/error-codes/E0120.rs +++ b/tests/ui/error-codes/E0120.rs @@ -3,6 +3,7 @@ trait MyTrait { fn foo() {} } impl Drop for dyn MyTrait { //~^ ERROR E0120 fn drop(&mut self) {} + } fn main() {} diff --git a/tests/ui/error-codes/E0277-2.stderr b/tests/ui/error-codes/E0277-2.stderr index 9a262f7559075..f4e18e3bb539c 100644 --- a/tests/ui/error-codes/E0277-2.stderr +++ b/tests/ui/error-codes/E0277-2.stderr @@ -4,7 +4,7 @@ error[E0277]: `*const u8` cannot be sent between threads safely LL | is_send::(); | ^^^ `*const u8` cannot be sent between threads safely | - = help: within `Foo`, the trait `Send` is not implemented for `*const u8` + = help: within `Foo`, the trait `Send` is not implemented for `*const u8`, which is required by `Foo: Send` note: required because it appears within the type `Baz` --> $DIR/E0277-2.rs:9:8 | diff --git a/tests/ui/error-codes/E0277.stderr b/tests/ui/error-codes/E0277.stderr index 0b0d2b09720cd..aeb97290cf856 100644 --- a/tests/ui/error-codes/E0277.stderr +++ b/tests/ui/error-codes/E0277.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | fn f(p: Path) { } | ^ doesn't have a size known at compile-time | - = help: within `Path`, the trait `Sized` is not implemented for `[u8]` + = help: within `Path`, the trait `Sized` is not implemented for `[u8]`, which is required by `Path: Sized` note: required because it appears within the type `Path` --> $SRC_DIR/std/src/path.rs:LL:COL = help: unsized fn params are gated as an unstable feature diff --git a/tests/ui/error-codes/E0283.stderr b/tests/ui/error-codes/E0283.stderr index 6008809f050f8..fc08395a2b0df 100644 --- a/tests/ui/error-codes/E0283.stderr +++ b/tests/ui/error-codes/E0283.stderr @@ -5,7 +5,7 @@ LL | fn create() -> u32; | ------------------- `Coroutine::create` defined here ... LL | let cont: u32 = Coroutine::create(); - | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/error-codes/E0374.rs b/tests/ui/error-codes/E0374.rs index 41fcedc328df1..47b9bea978e40 100644 --- a/tests/ui/error-codes/E0374.rs +++ b/tests/ui/error-codes/E0374.rs @@ -1,7 +1,7 @@ #![feature(coerce_unsized)] use std::ops::CoerceUnsized; -struct Foo { +struct Foo { //~ ERROR `T` is never used a: i32, } diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 148fa1348ab66..77f351b28ef24 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -7,6 +7,15 @@ LL | | where T: CoerceUnsized {} | = note: expected a single field to be coerced, none found -error: aborting due to 1 previous error +error[E0392]: type parameter `T` is never used + --> $DIR/E0374.rs:4:12 + | +LL | struct Foo { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0374`. +Some errors have detailed explanations: E0374, E0392. +For more information about an error, try `rustc --explain E0374`. diff --git a/tests/ui/error-codes/E0375.rs b/tests/ui/error-codes/E0375.rs index 0c03a8761df01..eaf99dd384230 100644 --- a/tests/ui/error-codes/E0375.rs +++ b/tests/ui/error-codes/E0375.rs @@ -3,7 +3,7 @@ use std::ops::CoerceUnsized; struct Foo { a: i32, - b: T, + b: T, //~ ERROR E0277 c: U, } diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr index 0a5e4128ae9d7..d5340022d68ce 100644 --- a/tests/ui/error-codes/E0375.stderr +++ b/tests/ui/error-codes/E0375.stderr @@ -7,6 +7,32 @@ LL | impl CoerceUnsized> for Foo {} = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) -error: aborting due to 1 previous error +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/E0375.rs:6:8 + | +LL | struct Foo { + | - this type parameter needs to be `Sized` +LL | a: i32, +LL | b: T, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct Foo { +LL + struct Foo { + | +help: borrowed types always have a statically known size + | +LL | b: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | b: Box, + | ++++ + + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0375`. +Some errors have detailed explanations: E0277, E0375. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0392.stderr b/tests/ui/error-codes/E0392.stderr index ecbfd5584d5a3..9971267e9270d 100644 --- a/tests/ui/error-codes/E0392.stderr +++ b/tests/ui/error-codes/E0392.stderr @@ -1,11 +1,11 @@ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/E0392.rs:1:10 | LL | enum Foo { Bar } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index d27fade487fe2..754867061c7f8 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -20,7 +20,7 @@ LL | fn baz $DIR/E0401.rs:24:25 | LL | impl Iterator for A { @@ -29,7 +29,7 @@ LL | impl Iterator for A { LL | fn helper(sel: &Self) -> u8 { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | refer to the type directly here instead error[E0283]: type annotations needed diff --git a/tests/ui/error-codes/E0582.rs b/tests/ui/error-codes/E0582.rs index ff25012d0f925..b6513170b137e 100644 --- a/tests/ui/error-codes/E0582.rs +++ b/tests/ui/error-codes/E0582.rs @@ -19,7 +19,7 @@ fn mk_unexpected_char_err<'a>() -> Option<&'a i32> { } fn foo<'a>(data: &mut Chars<'a>) { - bar(mk_unexpected_char_err) + bar(mk_unexpected_char_err) //~ ERROR mismatched types } fn bar(t: F) diff --git a/tests/ui/error-codes/E0582.stderr b/tests/ui/error-codes/E0582.stderr index 81a2f004653d2..64b527cdcc2a2 100644 --- a/tests/ui/error-codes/E0582.stderr +++ b/tests/ui/error-codes/E0582.stderr @@ -10,6 +10,21 @@ error[E0582]: binding for associated type `Item` references lifetime `'a`, which LL | where F: for<'a> Iterator | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/E0582.rs:22:5 + | +LL | bar(mk_unexpected_char_err) + | ^^^ one type is more general than the other + | + = note: expected enum `Option<&_>` + found enum `Option<&'a _>` +note: the lifetime requirement is introduced here + --> $DIR/E0582.rs:28:30 + | +LL | where F: for<'a> Fn() -> Option<&'a i32> + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0582`. +Some errors have detailed explanations: E0308, E0582. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0637.rs b/tests/ui/error-codes/E0637.rs index 382ce3ed01f34..e107ea9521b62 100644 --- a/tests/ui/error-codes/E0637.rs +++ b/tests/ui/error-codes/E0637.rs @@ -2,9 +2,9 @@ fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { //~^ ERROR: `'_` cannot be used here [E0637] //~| ERROR: missing lifetime specifier if str1.len() > str2.len() { - str1 + str1 //~ ERROR: lifetime may not live long enough } else { - str2 + str2 //~ ERROR: lifetime may not live long enough } } diff --git a/tests/ui/error-codes/E0637.stderr b/tests/ui/error-codes/E0637.stderr index d9db89ddb0c97..217881b8e7c0e 100644 --- a/tests/ui/error-codes/E0637.stderr +++ b/tests/ui/error-codes/E0637.stderr @@ -27,7 +27,25 @@ help: consider introducing a higher-ranked lifetime here LL | T: for<'a> Into<&'a u32>, | +++++++ ++ -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/E0637.rs:5:9 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | - let's call the lifetime of this reference `'1` +... +LL | str1 + | ^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/E0637.rs:7:9 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | - let's call the lifetime of this reference `'2` +... +LL | str2 + | ^^^^ returning this value requires that `'2` must outlive `'static` + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0106, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/error-codes/E0790.stderr b/tests/ui/error-codes/E0790.stderr index f559abae39780..6338a10b6af9d 100644 --- a/tests/ui/error-codes/E0790.stderr +++ b/tests/ui/error-codes/E0790.stderr @@ -5,7 +5,7 @@ LL | fn my_fn(); | ----------- `MyTrait::my_fn` defined here ... LL | MyTrait::my_fn(); - | ^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | @@ -33,7 +33,7 @@ LL | fn my_fn(); | ----------- `MyTrait::my_fn` defined here ... LL | inner::MyTrait::my_fn(); - | ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | @@ -61,7 +61,7 @@ LL | fn my_fn(); | ----------- `MyTrait2::my_fn` defined here ... LL | MyTrait2::my_fn(); - | ^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr index 9228a047e8785..bd4e934822751 100644 --- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr +++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:53:46 | LL | want(Wrapper { value: Burrito { filling: q } }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -38,7 +38,7 @@ LL | want(Some(())); | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `()` + = help: the trait `Iterator` is not implemented for `()`, which is required by `Option<()>: T1` = help: the trait `T1` is implemented for `Option` note: required for `Option<()>` to implement `T1` --> $DIR/blame-trait-error.rs:21:20 @@ -109,7 +109,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:65:45 | LL | want(&ExampleTuple::ExampleTupleVariant(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -134,7 +134,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:68:31 | LL | want(&ExampleTupleVariant(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -159,7 +159,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:71:50 | LL | want(&ExampleOtherTuple::ExampleTupleVariant(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -184,7 +184,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:74:44 | LL | want(&ExampleDifferentTupleVariantName(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -209,7 +209,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:77:45 | LL | want(&ExampleYetAnotherTupleVariantName(q)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleTuple: T1` | | | required by a bound introduced by this call | @@ -234,7 +234,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:80:56 | LL | want(&ExampleStruct::ExampleStructVariant { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -257,7 +257,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:83:41 | LL | want(&ExampleStructVariant { field: q }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | | | required by a bound introduced by this call | @@ -282,7 +282,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:86:61 | LL | want(&ExampleOtherStruct::ExampleStructVariant { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -305,7 +305,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:89:54 | LL | want(&ExampleDifferentStructVariantName { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -328,7 +328,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:92:55 | LL | want(&ExampleYetAnotherStructVariantName { field: q }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleStruct: T1` | note: required for `ExampleStruct` to implement `T1` --> $DIR/blame-trait-error.rs:45:9 @@ -351,7 +351,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:95:38 | LL | want(&ExampleActuallyTupleStruct(q, 0)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleActuallyTupleStruct: T1` | | | required by a bound introduced by this call | @@ -376,7 +376,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error.rs:98:43 | LL | want(&ExampleActuallyTupleStructOther(q, 0)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&ExampleActuallyTupleStruct: T1` | | | required by a bound introduced by this call | diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr index b6a24e12bcc76..a2df6843f43b9 100644 --- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr +++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:81:60 | LL | want(Wrapper { value: Burrito { spicy: false, filling: q } }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | note: required for `Burrito` to implement `T2` --> $DIR/blame-trait-error-spans-on-exprs.rs:22:13 @@ -32,7 +32,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:85:84 | LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | note: required for `BurritoKinds` to implement `T2` --> $DIR/blame-trait-error-spans-on-exprs.rs:32:13 @@ -62,7 +62,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:89:39 | LL | want(Wrapper { value: Taco(false, q) }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -94,7 +94,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:93:53 | LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -126,7 +126,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:97:74 | LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } }); - | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | note: required for `GenericBurrito` to implement `T2` --> $DIR/blame-trait-error-spans-on-exprs.rs:47:16 @@ -156,7 +156,7 @@ error[E0277]: the trait bound `Q: T2` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:101:14 | LL | want((3, q)); - | ---- ^ the trait `T2` is not implemented for `Q` + | ---- ^ the trait `T2` is not implemented for `Q`, which is required by `({integer}, Q): T1` | | | required by a bound introduced by this call | @@ -181,7 +181,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:105:31 | LL | want(Wrapper { value: (3, q) }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper<({integer}, Q)>: T1` | | | required by a bound introduced by this call | @@ -213,7 +213,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:109:15 | LL | want(((3, q), 5)); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `(({integer}, Q), {integer}): T1` | | | required by a bound introduced by this call | @@ -245,7 +245,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:112:49 | LL | want(DoubleWrapper { item: Wrapper { value: q } }); - | ---- ^ the trait `T1` is not implemented for `Q` + | ---- ^ the trait `T1` is not implemented for `Q`, which is required by `DoubleWrapper: T1` | | | required by a bound introduced by this call | @@ -270,7 +270,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:115:88 | LL | want(DoubleWrapper { item: Wrapper { value: DoubleWrapper { item: Wrapper { value: q } } } }); - | ---- required by a bound introduced by this call ^ the trait `T1` is not implemented for `Q` + | ---- required by a bound introduced by this call ^ the trait `T1` is not implemented for `Q`, which is required by `DoubleWrapper>: T1` | note: required for `DoubleWrapper` to implement `T1` --> $DIR/blame-trait-error-spans-on-exprs.rs:72:13 @@ -295,7 +295,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:119:27 | LL | want(Wrapper { value: AliasBurrito { spiciness: q, filling: q } }); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`, which is required by `Wrapper>: T1` | | | required by a bound introduced by this call | @@ -327,7 +327,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:122:35 | LL | want(Two { a: Two { a: (), b: q }, b: () }); - | ---- ^ the trait `T1` is not implemented for `Q` + | ---- ^ the trait `T1` is not implemented for `Q`, which is required by `Two, ()>: T1` | | | required by a bound introduced by this call | @@ -354,7 +354,7 @@ error[E0277]: the trait bound `Q: T1` is not satisfied LL | want( | ---- required by a bound introduced by this call LL | Two { a: Two { a: (), b: Two { a: Two { a: (), b: q }, b: () } }, b: () }, - | ^ the trait `T1` is not implemented for `Q` + | ^ the trait `T1` is not implemented for `Q`, which is required by `Two, ()>>, ()>: T1` | note: required for `Two, ()>` to implement `T1` --> $DIR/blame-trait-error-spans-on-exprs.rs:66:19 @@ -379,7 +379,7 @@ error[E0277]: the trait bound `Q: T3` is not satisfied --> $DIR/blame-trait-error-spans-on-exprs.rs:133:44 | LL | want(&Burrito { spicy: false, filling: q }); - | ---- ^ the trait `T3` is not implemented for `Q` + | ---- ^ the trait `T3` is not implemented for `Q`, which is required by `&Burrito: T1` | | | required by a bound introduced by this call | diff --git a/tests/ui/explicit-tail-calls/return-mismatches.rs b/tests/ui/explicit-tail-calls/return-mismatches.rs index 935a1a1d28b02..8094a192913bc 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.rs +++ b/tests/ui/explicit-tail-calls/return-mismatches.rs @@ -13,7 +13,7 @@ fn _f1() { become _g1(); //~ error: mismatched types } -fn _g1() -> ! { +fn _g1() -> ! { //~ WARN: cannot return without recursing become _g1(); } diff --git a/tests/ui/explicit-tail-calls/return-mismatches.stderr b/tests/ui/explicit-tail-calls/return-mismatches.stderr index 1dcc35797c130..31c7a46ded911 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.stderr +++ b/tests/ui/explicit-tail-calls/return-mismatches.stderr @@ -22,6 +22,17 @@ error[E0308]: mismatched types LL | become _g2(); | ^^^^^^^^^^^^ expected `u32`, found `u16` -error: aborting due to 3 previous errors +warning: function cannot return without recursing + --> $DIR/return-mismatches.rs:16:1 + | +LL | fn _g1() -> ! { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | become _g1(); + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed index bb093a4af4a3e..3c71587c8e399 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![allow(dropping_references)] struct Foo { diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs index 1a9f89c054f39..075d4cbe02b31 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![allow(dropping_references)] struct Foo { diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr index d2d69ce6daf72..13b6ee9987e88 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr @@ -1,5 +1,5 @@ error[E0040]: explicit use of destructor method - --> $DIR/explicit-call-to-supertrait-dtor.rs:22:14 + --> $DIR/explicit-call-to-supertrait-dtor.rs:23:14 | LL | self.drop(); | ^^^^ explicit destructor calls not allowed diff --git a/tests/ui/expr/if/if-no-match-bindings.rs b/tests/ui/expr/if/if-no-match-bindings.rs index ca3df0fdde45d..d36a436397b46 100644 --- a/tests/ui/expr/if/if-no-match-bindings.rs +++ b/tests/ui/expr/if/if-no-match-bindings.rs @@ -6,6 +6,7 @@ fn b_ref<'a>() -> &'a bool { &true } fn b_mut_ref<'a>() -> &'a mut bool { &mut true } +//~^ ERROR: cannot return reference to temporary fn main() { // This is OK: diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr index 737a5d604483f..18f3b6b168ecc 100644 --- a/tests/ui/expr/if/if-no-match-bindings.stderr +++ b/tests/ui/expr/if/if-no-match-bindings.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:18:8 + --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_ref() {} | ^^^^^^^ expected `bool`, found `&bool` @@ -10,7 +10,7 @@ LL | if *b_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:19:8 + --> $DIR/if-no-match-bindings.rs:20:8 | LL | if b_mut_ref() {} | ^^^^^^^^^^^ expected `bool`, found `&mut bool` @@ -21,7 +21,7 @@ LL | if *b_mut_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:20:8 + --> $DIR/if-no-match-bindings.rs:21:8 | LL | if &true {} | ^^^^^ expected `bool`, found `&bool` @@ -33,7 +33,7 @@ LL + if true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:21:8 + --> $DIR/if-no-match-bindings.rs:22:8 | LL | if &mut true {} | ^^^^^^^^^ expected `bool`, found `&mut bool` @@ -45,7 +45,7 @@ LL + if true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:24:11 + --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_ref() {} | ^^^^^^^ expected `bool`, found `&bool` @@ -56,7 +56,7 @@ LL | while *b_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:25:11 + --> $DIR/if-no-match-bindings.rs:26:11 | LL | while b_mut_ref() {} | ^^^^^^^^^^^ expected `bool`, found `&mut bool` @@ -67,7 +67,7 @@ LL | while *b_mut_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:26:11 + --> $DIR/if-no-match-bindings.rs:27:11 | LL | while &true {} | ^^^^^ expected `bool`, found `&bool` @@ -79,7 +79,7 @@ LL + while true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:27:11 + --> $DIR/if-no-match-bindings.rs:28:11 | LL | while &mut true {} | ^^^^^^^^^ expected `bool`, found `&mut bool` @@ -90,6 +90,16 @@ LL - while &mut true {} LL + while true {} | -error: aborting due to 8 previous errors +error[E0515]: cannot return reference to temporary value + --> $DIR/if-no-match-bindings.rs:8:38 + | +LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + | ^^^^^---- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0515. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/extenv/issue-55897.rs b/tests/ui/extenv/issue-55897.rs index b7533f41351da..b6500e5405933 100644 --- a/tests/ui/extenv/issue-55897.rs +++ b/tests/ui/extenv/issue-55897.rs @@ -4,7 +4,6 @@ mod unresolved_env { use env; //~ ERROR unresolved import `env` include!(concat!(env!("NON_EXISTENT"), "/data.rs")); - //~^ ERROR cannot determine resolution for the macro `env` } mod nonexistent_env { diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr index 401db827813a9..2e8c05cca867f 100644 --- a/tests/ui/extenv/issue-55897.stderr +++ b/tests/ui/extenv/issue-55897.stderr @@ -1,5 +1,5 @@ error: environment variable `NON_EXISTENT` not defined at compile time - --> $DIR/issue-55897.rs:11:22 + --> $DIR/issue-55897.rs:10:22 | LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: suffixes on string literals are invalid - --> $DIR/issue-55897.rs:16:22 + --> $DIR/issue-55897.rs:15:22 | LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ invalid suffix `suffix` @@ -33,14 +33,6 @@ help: consider importing this module instead LL | use std::env; | ~~~~~~~~ -error: cannot determine resolution for the macro `env` - --> $DIR/issue-55897.rs:6:22 - | -LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); - | ^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 79efcc5d8b041..6ad3effe0e26e 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -1,11 +1,6 @@ error: extern location for std does not exist: -error: `#[panic_handler]` function required, but not found +error: requires `sized` lang_item -error: unwinding panics are not supported without std - | - = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/extern-mod-syntax.rs b/tests/ui/extern-mod-syntax.rs deleted file mode 100644 index 65dfa6a0f5790..0000000000000 --- a/tests/ui/extern-mod-syntax.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -#![allow(unused_imports)] -#![no_std] - -extern crate std; -use std::ffi::c_void; - -pub fn main() { - std::println!("Hello world!"); -} diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index a79caced111bb..7428e6a60b520 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -5,11 +5,11 @@ LL | assert_sized::(); | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `A` -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -21,17 +21,17 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim LL | assert_sized::(); | ^^^ doesn't have a size known at compile-time | - = help: within `Foo`, the trait `Sized` is not implemented for `A` + = help: within `Foo`, the trait `Sized` is not implemented for `A`, which is required by `Foo: Sized` note: required because it appears within the type `Foo` --> $DIR/extern-types-unsized.rs:9:8 | LL | struct Foo { | ^^^ -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -43,17 +43,17 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim LL | assert_sized::>(); | ^^^^^^ doesn't have a size known at compile-time | - = help: within `Bar`, the trait `Sized` is not implemented for `A` + = help: within `Bar`, the trait `Sized` is not implemented for `A`, which is required by `Bar: Sized` note: required because it appears within the type `Bar` --> $DIR/extern-types-unsized.rs:14:8 | LL | struct Bar { | ^^^ -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} @@ -65,17 +65,17 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim LL | assert_sized::>>(); | ^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Bar>`, the trait `Sized` is not implemented for `A` + = help: within `Bar>`, the trait `Sized` is not implemented for `A`, which is required by `Bar>: Sized` note: required because it appears within the type `Bar` --> $DIR/extern-types-unsized.rs:14:8 | LL | struct Bar { | ^^^ -note: required by a bound in `assert_sized` +note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | LL | fn assert_sized() {} - | ^ required by this bound in `assert_sized` + | ^ required by the implicit `Sized` requirement on this type parameter in `assert_sized` help: consider relaxing the implicit `Sized` restriction | LL | fn assert_sized() {} diff --git a/tests/ui/issues/issue-16250.rs b/tests/ui/extern/issue-16250.rs similarity index 100% rename from tests/ui/issues/issue-16250.rs rename to tests/ui/extern/issue-16250.rs diff --git a/tests/ui/issues/issue-16250.stderr b/tests/ui/extern/issue-16250.stderr similarity index 100% rename from tests/ui/issues/issue-16250.stderr rename to tests/ui/extern/issue-16250.stderr diff --git a/tests/ui/issues/issue-47725.rs b/tests/ui/extern/issue-47725.rs similarity index 100% rename from tests/ui/issues/issue-47725.rs rename to tests/ui/extern/issue-47725.rs diff --git a/tests/ui/issues/issue-47725.stderr b/tests/ui/extern/issue-47725.stderr similarity index 100% rename from tests/ui/issues/issue-47725.stderr rename to tests/ui/extern/issue-47725.stderr diff --git a/tests/ui/extern/no-mangle-associated-fn.rs b/tests/ui/extern/no-mangle-associated-fn.rs index ecd44abbf264c..56afd8b90926e 100644 --- a/tests/ui/extern/no-mangle-associated-fn.rs +++ b/tests/ui/extern/no-mangle-associated-fn.rs @@ -12,7 +12,7 @@ impl Foo { } } -trait Bar { +trait Bar { //~ WARN trait `Bar` is never used fn qux() -> u8; } diff --git a/tests/ui/extern/no-mangle-associated-fn.stderr b/tests/ui/extern/no-mangle-associated-fn.stderr new file mode 100644 index 0000000000000..772cbf6cf7dd7 --- /dev/null +++ b/tests/ui/extern/no-mangle-associated-fn.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/no-mangle-associated-fn.rs:15:7 + | +LL | trait Bar { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs deleted file mode 100644 index 465b81d7fe33c..0000000000000 --- a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.rs +++ /dev/null @@ -1,30 +0,0 @@ -// compile-flags: --crate-type=rlib -#![no_core] -#![feature(no_core, lang_items)] -#[lang="sized"] -trait Sized { } - -extern "amdgpu-kernel" fn fu() {} //~ ERROR amdgpu-kernel ABI is experimental -//~^ ERROR is not a supported ABI - -trait T { - extern "amdgpu-kernel" fn mu(); //~ ERROR amdgpu-kernel ABI is experimental - extern "amdgpu-kernel" fn dmu() {} //~ ERROR amdgpu-kernel ABI is experimental - //~^ ERROR is not a supported ABI -} - -struct S; -impl T for S { - extern "amdgpu-kernel" fn mu() {} //~ ERROR amdgpu-kernel ABI is experimental - //~^ ERROR is not a supported ABI -} - -impl S { - extern "amdgpu-kernel" fn imu() {} //~ ERROR amdgpu-kernel ABI is experimental - //~^ ERROR is not a supported ABI -} - -type TAU = extern "amdgpu-kernel" fn(); //~ ERROR amdgpu-kernel ABI is experimental - -extern "amdgpu-kernel" {} //~ ERROR amdgpu-kernel ABI is experimental -//~^ ERROR is not a supported ABI diff --git a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr b/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr deleted file mode 100644 index c5ae52c789b67..0000000000000 --- a/tests/ui/feature-gates/feature-gate-abi_amdgpu_kernel.stderr +++ /dev/null @@ -1,104 +0,0 @@ -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:8 - | -LL | extern "amdgpu-kernel" fn fu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:11:12 - | -LL | extern "amdgpu-kernel" fn mu(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:12 - | -LL | extern "amdgpu-kernel" fn dmu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:12 - | -LL | extern "amdgpu-kernel" fn mu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:12 - | -LL | extern "amdgpu-kernel" fn imu() {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:27:19 - | -LL | type TAU = extern "amdgpu-kernel" fn(); - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: amdgpu-kernel ABI is experimental and subject to change - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:8 - | -LL | extern "amdgpu-kernel" {} - | ^^^^^^^^^^^^^^^ - | - = note: see issue #51575 for more information - = help: add `#![feature(abi_amdgpu_kernel)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:29:1 - | -LL | extern "amdgpu-kernel" {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:7:1 - | -LL | extern "amdgpu-kernel" fn fu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:12:5 - | -LL | extern "amdgpu-kernel" fn dmu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:18:5 - | -LL | extern "amdgpu-kernel" fn mu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target - --> $DIR/feature-gate-abi_amdgpu_kernel.rs:23:5 - | -LL | extern "amdgpu-kernel" fn imu() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors - -Some errors have detailed explanations: E0570, E0658. -For more information about an error, try `rustc --explain E0570`. diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs index 073599edad7b9..f87d3aab635c0 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -11,7 +11,6 @@ impl Tr1 for S1 { type As1 = S2; } trait _Tr3 { type A: Iterator; //~^ ERROR associated type bounds are unstable - //~| ERROR the trait bound `<::A as Iterator>::Item: Copy` is not satisfied type B: Iterator; //~^ ERROR associated type bounds are unstable diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr index efab91f25f0d2..855a29953f1b0 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -9,7 +9,7 @@ LL | type A: Iterator; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:16:22 + --> $DIR/feature-gate-associated_type_bounds.rs:15:22 | LL | type B: Iterator; | ^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | type B: Iterator; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:20:20 + --> $DIR/feature-gate-associated_type_bounds.rs:19:20 | LL | struct _St1> { | ^^^^^^^^ @@ -29,7 +29,7 @@ LL | struct _St1> { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:27:18 + --> $DIR/feature-gate-associated_type_bounds.rs:26:18 | LL | enum _En1> { | ^^^^^^^^ @@ -39,7 +39,7 @@ LL | enum _En1> { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:34:19 + --> $DIR/feature-gate-associated_type_bounds.rs:33:19 | LL | union _Un1> { | ^^^^^^^^ @@ -49,7 +49,7 @@ LL | union _Un1> { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:41:37 + --> $DIR/feature-gate-associated_type_bounds.rs:40:37 | LL | type _TaWhere1 where T: Iterator = T; | ^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | type _TaWhere1 where T: Iterator = T; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:44:22 + --> $DIR/feature-gate-associated_type_bounds.rs:43:22 | LL | fn _apit(_: impl Tr1) {} | ^^^^^^^^^ @@ -69,7 +69,7 @@ LL | fn _apit(_: impl Tr1) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:46:26 + --> $DIR/feature-gate-associated_type_bounds.rs:45:26 | LL | fn _apit_dyn(_: &dyn Tr1) {} | ^^^^^^^^^ @@ -79,7 +79,7 @@ LL | fn _apit_dyn(_: &dyn Tr1) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:49:24 + --> $DIR/feature-gate-associated_type_bounds.rs:48:24 | LL | fn _rpit() -> impl Tr1 { S1 } | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | fn _rpit() -> impl Tr1 { S1 } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:52:31 + --> $DIR/feature-gate-associated_type_bounds.rs:51:31 | LL | fn _rpit_dyn() -> Box> { Box::new(S1) } | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | fn _rpit_dyn() -> Box> { Box::new(S1) } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:55:23 + --> $DIR/feature-gate-associated_type_bounds.rs:54:23 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -109,7 +109,7 @@ LL | const _cdef: impl Tr1 = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:61:24 + --> $DIR/feature-gate-associated_type_bounds.rs:60:24 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^ @@ -119,7 +119,7 @@ LL | static _sdef: impl Tr1 = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:68:21 + --> $DIR/feature-gate-associated_type_bounds.rs:67:21 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^ @@ -129,7 +129,7 @@ LL | let _: impl Tr1 = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in const types - --> $DIR/feature-gate-associated_type_bounds.rs:55:14 + --> $DIR/feature-gate-associated_type_bounds.rs:54:14 | LL | const _cdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL | const _cdef: impl Tr1 = S1; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in static types - --> $DIR/feature-gate-associated_type_bounds.rs:61:15 + --> $DIR/feature-gate-associated_type_bounds.rs:60:15 | LL | static _sdef: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -145,25 +145,14 @@ LL | static _sdef: impl Tr1 = S1; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/feature-gate-associated_type_bounds.rs:68:12 + --> $DIR/feature-gate-associated_type_bounds.rs:67:12 | LL | let _: impl Tr1 = S1; | ^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0277]: the trait bound `<::A as Iterator>::Item: Copy` is not satisfied - --> $DIR/feature-gate-associated_type_bounds.rs:12:28 - | -LL | type A: Iterator; - | ^^^^ the trait `Copy` is not implemented for `<::A as Iterator>::Item` - | -help: consider further restricting the associated type - | -LL | trait _Tr3 where <::A as Iterator>::Item: Copy { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0277, E0562, E0658. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0562, E0658. +For more information about an error, try `rustc --explain E0562`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs index b600ad23eee64..801956c33395d 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs @@ -13,4 +13,5 @@ extern "C" { fn main() { assert_eq!(FOO, 3); + //~^ ERROR extern static is unsafe } diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr index 0e1fe5572a982..62b72e3505994 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr @@ -8,6 +8,15 @@ LL | #[cfg_attr(target_thread_local, thread_local)] = help: add `#![feature(cfg_target_thread_local)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/feature-gate-cfg-target-thread-local.rs:15:16 + | +LL | assert_eq!(FOO, 3); + | ^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.rs b/tests/ui/feature-gates/feature-gate-custom_mir.rs index 0126dde2f7d4b..e100df08ee70d 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.rs +++ b/tests/ui/feature-gates/feature-gate-custom_mir.rs @@ -1,10 +1,15 @@ #![feature(core_intrinsics)] extern crate core; +use core::intrinsics::mir::*; //~ custom_mir #[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite pub fn foo(_x: i32) -> i32 { - 0 + mir! { + { + Return() //~ custom_mir + } + } } fn main() { diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr index 34899e5e66c08..118eab144bf7f 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite - --> $DIR/feature-gate-custom_mir.rs:5:1 + --> $DIR/feature-gate-custom_mir.rs:6:1 | LL | #[custom_mir(dialect = "built")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,6 +7,24 @@ LL | #[custom_mir(dialect = "built")] = help: add `#![feature(custom_mir)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable + --> $DIR/feature-gate-custom_mir.rs:4:5 + | +LL | use core::intrinsics::mir::*; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable + --> $DIR/feature-gate-custom_mir.rs:10:13 + | +LL | Return() + | ^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs deleted file mode 100644 index f354534356c21..0000000000000 --- a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![crate_type = "lib"] - -extern "C" { - #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature - pub fn foo(); -} diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr deleted file mode 100644 index 8d19874c36a0c..0000000000000 --- a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature - --> $DIR/feature-gate-ffi_returns_twice.rs:4:5 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #58314 for more information - = help: add `#![feature(ffi_returns_twice)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index 8e93b194174ff..dc561234809af 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -6,12 +6,14 @@ use std::arch::asm; //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked() { asm!("", options(noreturn)) + //~^ ERROR: requires unsafe } #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { asm!("", options(noreturn)) + //~^ ERROR: requires unsafe } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr index e1b826582171f..ffdf31e147aed 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr @@ -9,7 +9,7 @@ LL | #[naked] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:11:1 + --> $DIR/feature-gate-naked_functions.rs:12:1 | LL | #[naked] | ^^^^^^^^ @@ -18,6 +18,23 @@ LL | #[naked] = help: add `#![feature(naked_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/feature-gate-naked_functions.rs:8:5 + | +LL | asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/feature-gate-naked_functions.rs:15:5 + | +LL | asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/feature-gates/feature-gate-never_type.rs b/tests/ui/feature-gates/feature-gate-never_type.rs index be8c27dbb1b02..f5d28a4877fdf 100644 --- a/tests/ui/feature-gates/feature-gate-never_type.rs +++ b/tests/ui/feature-gates/feature-gate-never_type.rs @@ -13,5 +13,14 @@ impl Foo for Meeshka { type Wub = !; //~ ERROR type is experimental } +fn look_ma_no_feature_gate !>() {} //~ ERROR type is experimental +fn tadam(f: &dyn Fn() -> !) {} //~ ERROR type is experimental +fn panic() -> ! { + panic!(); +} +fn toudoum() -> impl Fn() -> ! { //~ ERROR type is experimental + panic +} + fn main() { } diff --git a/tests/ui/feature-gates/feature-gate-never_type.stderr b/tests/ui/feature-gates/feature-gate-never_type.stderr index 0fca58519ce13..33e4e019b18d3 100644 --- a/tests/ui/feature-gates/feature-gate-never_type.stderr +++ b/tests/ui/feature-gates/feature-gate-never_type.stderr @@ -48,6 +48,36 @@ LL | type Wub = !; = help: add `#![feature(never_type)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:16:43 + | +LL | fn look_ma_no_feature_gate !>() {} + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:17:26 + | +LL | fn tadam(f: &dyn Fn() -> !) {} + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the `!` type is experimental + --> $DIR/feature-gate-never_type.rs:21:30 + | +LL | fn toudoum() -> impl Fn() -> ! { + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr index 1b87ebd9f20ce..7fc726409ce40 100644 --- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -94,7 +94,7 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at LL | fn unsized_local() where Dst: Sized { | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)` + = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`, which is required by `Dst<(dyn A + 'static)>: Sized` note: required because it appears within the type `Dst<(dyn A + 'static)>` --> $DIR/feature-gate-trivial_bounds.rs:48:8 | diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs index 1285cca6b8b7c..37b7d52fafcae 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs @@ -8,7 +8,7 @@ fn main() { extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change fn atomic_fence(); } - atomic_fence(); + atomic_fence(); //~ ERROR: is unsafe 42 }); } diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr index b0ed6e6076051..3dc11b5612ca9 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -7,6 +7,15 @@ LL | extern "rust-intrinsic" { = help: add `#![feature(intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0133]: call to unsafe function `main::atomic_fence` is unsafe and requires unsafe function or block + --> $DIR/feature-gated-feature-in-macro-arg.rs:11:9 + | +LL | atomic_fence(); + | ^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.rs b/tests/ui/feature-gates/issue-43106-gating-of-bench.rs index 796325b79af66..841383a008f54 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-bench.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.rs @@ -5,6 +5,5 @@ #![feature(custom_inner_attributes)] #![bench = "4100"] -//~^ ERROR cannot determine resolution for the attribute macro `bench` -//~^^ ERROR `bench` attribute cannot be used at crate level +//~^ ERROR `bench` attribute cannot be used at crate level fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr index 8270d46d492a9..912c2746f3835 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-bench.stderr @@ -1,17 +1,9 @@ -error: cannot determine resolution for the attribute macro `bench` - --> $DIR/issue-43106-gating-of-bench.rs:7:4 - | -LL | #![bench = "4100"] - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `bench` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-bench.rs:7:1 | LL | #![bench = "4100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +LL | LL | fn main() {} | ---- the inner attribute doesn't annotate this function | @@ -21,5 +13,5 @@ LL - #![bench = "4100"] LL + #[bench = "4100"] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.rs b/tests/ui/feature-gates/issue-43106-gating-of-test.rs index 39835c9268eef..38c92d933fdd8 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-test.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-test.rs @@ -2,6 +2,5 @@ #![allow(soft_unstable)] #![test = "4200"] -//~^ ERROR cannot determine resolution for the attribute macro `test` -//~^^ ERROR `test` attribute cannot be used at crate level +//~^ ERROR `test` attribute cannot be used at crate level fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr index 922c9861aa3c1..2fc220dc47bd1 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-test.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-test.stderr @@ -1,17 +1,9 @@ -error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-43106-gating-of-test.rs:4:4 - | -LL | #![test = "4200"] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `test` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-test.rs:4:1 | LL | #![test = "4200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +LL | LL | fn main() {} | ---- the inner attribute doesn't annotate this function | @@ -21,5 +13,5 @@ LL - #![test = "4200"] LL + #[test = "4200"] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/ffi_returns_twice.rs b/tests/ui/ffi_returns_twice.rs deleted file mode 100644 index 8195d0e486369..0000000000000 --- a/tests/ui/ffi_returns_twice.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(ffi_returns_twice)] -#![crate_type = "lib"] - -#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions -pub fn foo() {} - -#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions -macro_rules! bar { - () => () -} - -extern "C" { - #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions - static INT: i32; -} diff --git a/tests/ui/ffi_returns_twice.stderr b/tests/ui/ffi_returns_twice.stderr deleted file mode 100644 index 0abe7613f1493..0000000000000 --- a/tests/ui/ffi_returns_twice.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:4:1 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:7:1 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:13:5 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0724`. diff --git a/tests/ui/fmt/ifmt-unimpl.stderr b/tests/ui/fmt/ifmt-unimpl.stderr index c0650ff17c5ed..58531c61bbe80 100644 --- a/tests/ui/fmt/ifmt-unimpl.stderr +++ b/tests/ui/fmt/ifmt-unimpl.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `str: UpperHex` is not satisfied --> $DIR/ifmt-unimpl.rs:2:21 | LL | format!("{:X}", "3"); - | ---- ^^^ the trait `UpperHex` is not implemented for `str` + | ---- ^^^ the trait `UpperHex` is not implemented for `str`, which is required by `&str: UpperHex` | | | required by a bound introduced by this call | diff --git a/tests/ui/fmt/send-sync.stderr b/tests/ui/fmt/send-sync.stderr index 6c9c7941eb339..aa377553c5041 100644 --- a/tests/ui/fmt/send-sync.stderr +++ b/tests/ui/fmt/send-sync.stderr @@ -6,7 +6,7 @@ LL | send(format_args!("{:?}", c)); | | | required by a bound introduced by this call | - = help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque` + = help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Send` = note: required because it appears within the type `&core::fmt::rt::Opaque` note: required because it appears within the type `core::fmt::rt::Argument<'_>` --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL @@ -28,7 +28,7 @@ LL | sync(format_args!("{:?}", c)); | | | required by a bound introduced by this call | - = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque` + = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`, which is required by `Arguments<'_>: Sync` = note: required because it appears within the type `&core::fmt::rt::Opaque` note: required because it appears within the type `core::fmt::rt::Argument<'_>` --> $SRC_DIR/core/src/fmt/rt.rs:LL:COL diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs index 33daa1ea0b400..81f2027286791 100644 --- a/tests/ui/fn/suggest-return-closure.rs +++ b/tests/ui/fn/suggest-return-closure.rs @@ -17,10 +17,16 @@ fn fn_mut() -> _ { //~| SUGGESTION impl FnMut(char) //~| NOTE for more information on `Fn` traits and closure types let x = String::new(); - |c| { + //~^ HELP: consider changing this to be mutable + |c| { //~ NOTE: value captured here x.push(c); + //~^ ERROR: does not live long enough + //~| NOTE: does not live long enough + //~| NOTE: cannot borrow as mutable + //~| ERROR: not declared as mutable } -} +} //~ NOTE: borrow later used here +//~^ NOTE: dropped here fn fun() -> _ { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr index 341044469ea37..8e80a11fe1b08 100644 --- a/tests/ui/fn/suggest-return-closure.stderr +++ b/tests/ui/fn/suggest-return-closure.stderr @@ -21,7 +21,7 @@ LL | fn fn_mut() -> _ { = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/suggest-return-closure.rs:25:13 + --> $DIR/suggest-return-closure.rs:31:13 | LL | fn fun() -> _ { | ^ @@ -31,6 +31,29 @@ LL | fn fun() -> _ { | = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html -error: aborting due to 3 previous errors +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/suggest-return-closure.rs:22:9 + | +LL | let x = String::new(); + | - help: consider changing this to be mutable: `mut x` +... +LL | x.push(c); + | ^ cannot borrow as mutable + +error[E0597]: `x` does not live long enough + --> $DIR/suggest-return-closure.rs:22:9 + | +LL | |c| { + | --- value captured here +LL | x.push(c); + | ^ borrowed value does not live long enough +... +LL | } + | -- borrow later used here + | | + | `x` dropped here while still borrowed + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0596, E0597. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/for/for-c-in-str.stderr b/tests/ui/for/for-c-in-str.stderr index 475cf8c887491..2544df646299b 100644 --- a/tests/ui/for/for-c-in-str.stderr +++ b/tests/ui/for/for-c-in-str.stderr @@ -4,7 +4,7 @@ error[E0277]: `&str` is not an iterator LL | for c in "asdf" { | ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | - = help: the trait `Iterator` is not implemented for `&str` + = help: the trait `Iterator` is not implemented for `&str`, which is required by `&str: IntoIterator` = note: required for `&str` to implement `IntoIterator` error: aborting due to 1 previous error diff --git a/tests/ui/for/for-loop-bogosity.stderr b/tests/ui/for/for-loop-bogosity.stderr index 194a2fa08ceab..143e4a4efd1f0 100644 --- a/tests/ui/for/for-loop-bogosity.stderr +++ b/tests/ui/for/for-loop-bogosity.stderr @@ -4,7 +4,7 @@ error[E0277]: `MyStruct` is not an iterator LL | for x in bogus { | ^^^^^ `MyStruct` is not an iterator | - = help: the trait `Iterator` is not implemented for `MyStruct` + = help: the trait `Iterator` is not implemented for `MyStruct`, which is required by `MyStruct: IntoIterator` = note: required for `MyStruct` to implement `IntoIterator` error: aborting due to 1 previous error diff --git a/tests/ui/function-pointer/unsized-ret.stderr b/tests/ui/function-pointer/unsized-ret.stderr index 66116273ff4d6..81d603f4b20e3 100644 --- a/tests/ui/function-pointer/unsized-ret.stderr +++ b/tests/ui/function-pointer/unsized-ret.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | foo:: str, _>(None, ()); | ^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> str`, the trait `Sized` is not implemented for `str` + = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`, which is required by `fn() -> str: Fn<_>` = note: required because it appears within the type `fn() -> str` note: required by a bound in `foo` --> $DIR/unsized-ret.rs:5:11 @@ -18,7 +18,7 @@ error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot LL | foo:: fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = 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)` + = 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)`, which is required by `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a): Fn<_>` = note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)` note: required by a bound in `foo` --> $DIR/unsized-ret.rs:5:11 diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr index 685c2794967b2..314a5509da8bc 100644 --- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr +++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `::Bar<()>: Eq` is not satisfied --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30 | LL | type Bar: Baz = i32; - | ^^^ the trait `Eq` is not implemented for `::Bar<()>` + | ^^^ the trait `Eq` is not implemented for `::Bar<()>`, which is required by `i32: Baz` | note: required for `i32` to implement `Baz` --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23 diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.rs b/tests/ui/generic-associated-types/bugs/issue-88460.rs index 224e696ad2c9c..3d2b225f0cd01 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88460.rs +++ b/tests/ui/generic-associated-types/bugs/issue-88460.rs @@ -1,7 +1,4 @@ -// check-fail -// known-bug: #88460 - -// This should pass, but has a missed normalization due to HRTB. +// check-pass pub trait Marker {} diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.stderr b/tests/ui/generic-associated-types/bugs/issue-88460.stderr deleted file mode 100644 index 74418a0c0bd52..0000000000000 --- a/tests/ui/generic-associated-types/bugs/issue-88460.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied - --> $DIR/issue-88460.rs:28:10 - | -LL | test(Foo); - | ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` - | | - | required by a bound introduced by this call - | - = help: the trait `Marker` is implemented for `()` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/issue-88460.rs:28:10 - | -LL | test(Foo); - | -----^^^- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant -note: required by a bound in `test` - --> $DIR/issue-88460.rs:15:27 - | -LL | fn test(value: T) - | ---- required by a bound in this function -... -LL | for<'a> T::Assoc<'a>: Marker, - | ^^^^^^ required by this bound in `test` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr index 84210eeb1a62b..b19280b45c248 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -7,6 +7,12 @@ LL | fn from_iter LendingIterator = A>>(iter: T) -> Self LL | fn from_iter LendingIterator = A>>(mut iter: I) -> Self { | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` -error: aborting due to 1 previous error +error: `Self` does not live long enough + --> $DIR/lending_iterator.rs:34:9 + | +LL | >::from_iter(self) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs index 247761dd04bf4..8bec78d6ecd7b 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.rs +++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs @@ -32,6 +32,7 @@ pub trait LendingIterator { Self: for<'q> LendingIterator = A>, { >::from_iter(self) + //[base]~^ ERROR: does not live long enough } } diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 261070d1db4bf..c3b119e21443d 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -25,7 +25,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/impl_bounds.rs:18:33 | LL | type C = String where Self: Copy; - | ^^^^ the trait `Copy` is not implemented for `T` + | ^^^^ the trait `Copy` is not implemented for `T`, which is required by `Fooy: Copy` | note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 @@ -50,7 +50,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/impl_bounds.rs:20:24 | LL | fn d() where Self: Copy {} - | ^^^^ the trait `Copy` is not implemented for `T` + | ^^^^ the trait `Copy` is not implemented for `T`, which is required by `Fooy: Copy` | note: required for `Fooy` to implement `Copy` --> $DIR/impl_bounds.rs:10:10 diff --git a/tests/ui/generic-associated-types/issue-101020.stderr b/tests/ui/generic-associated-types/issue-101020.stderr index 9c3753c2d1809..7faab4e527463 100644 --- a/tests/ui/generic-associated-types/issue-101020.stderr +++ b/tests/ui/generic-associated-types/issue-101020.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a mut (): Foo<&'a mut ()>` is not satis --> $DIR/issue-101020.rs:31:22 | LL | (&mut EmptyIter).consume(()); - | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()` + | ^^^^^^^ the trait `for<'a> Foo<&'a mut ()>` is not implemented for `&'a mut ()`, which is required by `for<'a> &'a mut (): FuncInput<'a, &'a mut ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-101020.rs:28:1 diff --git a/tests/ui/generic-associated-types/issue-70304.rs b/tests/ui/generic-associated-types/issue-70304.rs index 8898d4c7d1352..935d3f7a4ba8f 100644 --- a/tests/ui/generic-associated-types/issue-70304.rs +++ b/tests/ui/generic-associated-types/issue-70304.rs @@ -52,4 +52,5 @@ fn create_doc() -> impl Document = DocCursorImpl<'_>> { pub fn main() { let doc = create_doc(); let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); + //~^ ERROR: `doc` does not live long enough } diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr index 9b02c1b076837..8e012cc6d9367 100644 --- a/tests/ui/generic-associated-types/issue-70304.stderr +++ b/tests/ui/generic-associated-types/issue-70304.stderr @@ -27,7 +27,21 @@ LL | type Cursor<'a>: DocCursor<'a>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 for more information -error: aborting due to 3 previous errors +error[E0597]: `doc` does not live long enough + --> $DIR/issue-70304.rs:54:59 + | +LL | let doc = create_doc(); + | --- binding `doc` declared here +LL | let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); + | ------------^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `doc` is borrowed for `'static` +LL | +LL | } + | - `doc` dropped here while still borrowed + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0106, E0637. +Some errors have detailed explanations: E0106, E0597, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/generic-associated-types/issue-74684-2.rs b/tests/ui/generic-associated-types/issue-74684-2.rs index ff243af2cb390..96cdb01be3b60 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.rs +++ b/tests/ui/generic-associated-types/issue-74684-2.rs @@ -10,7 +10,7 @@ impl Fun for T { fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { let a = [0; 1]; - let x = T::identity(&a); + let x = T::identity(&a); //~ ERROR: does not live long enough todo!() } diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr index e50e3df85b363..d39513ec523af 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.stderr +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -17,6 +17,23 @@ note: required by a bound in `bug` LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { | ^^^^^^^^^^^^ required by this bound in `bug` -error: aborting due to 1 previous error +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-2.rs:13:25 + | +LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; + | - binding `a` declared here +LL | let x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +LL | todo!() +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0597. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-74824.stderr b/tests/ui/generic-associated-types/issue-74824.stderr index e5638d90ee8e7..942d9583be1b1 100644 --- a/tests/ui/generic-associated-types/issue-74824.stderr +++ b/tests/ui/generic-associated-types/issue-74824.stderr @@ -14,7 +14,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/issue-74824.rs:6:26 | LL | type Copy: Copy = Box; - | ^^^^^^ the trait `Clone` is not implemented for `T` + | ^^^^^^ the trait `Clone` is not implemented for `T`, which is required by `::Copy: Copy` | = note: required for `Box` to implement `Clone` = note: required for `::Copy` to implement `Copy` diff --git a/tests/ui/generic-associated-types/issue-80433.rs b/tests/ui/generic-associated-types/issue-80433.rs index bdba78c2ccd26..6d23427f16f8c 100644 --- a/tests/ui/generic-associated-types/issue-80433.rs +++ b/tests/ui/generic-associated-types/issue-80433.rs @@ -22,11 +22,12 @@ fn test_simpler<'a>(dst: &'a mut impl TestMut) //~^ ERROR missing generics for associated type { for n in 0i16..100 { - *dst.test_mut() = n.into(); + *dst.test_mut() = n.into(); //~ ERROR: cannot borrow + //~^ ERROR: borrowed data escapes outside of function } } fn main() { let mut t1: E = Default::default(); - test_simpler(&mut t1); + test_simpler(&mut t1); //~ ERROR does not live long enough } diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr index ab1fb7944180f..2bbf87ff1ff4f 100644 --- a/tests/ui/generic-associated-types/issue-80433.stderr +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -25,6 +25,43 @@ LL | type Output<'a>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 for more information -error: aborting due to 2 previous errors +error[E0499]: cannot borrow `*dst` as mutable more than once at a time + --> $DIR/issue-80433.rs:25:10 + | +LL | *dst.test_mut() = n.into(); + | ^^^----------- + | | + | `*dst` was mutably borrowed here in the previous iteration of the loop + | argument requires that `*dst` is borrowed for `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-80433.rs:25:10 + | +LL | fn test_simpler<'a>(dst: &'a mut impl TestMut) + | -- --- `dst` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | *dst.test_mut() = n.into(); + | ^^^^^^^^^^^^^^ + | | + | `dst` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0597]: `t1` does not live long enough + --> $DIR/issue-80433.rs:32:18 + | +LL | let mut t1: E = Default::default(); + | ------ binding `t1` declared here +LL | test_simpler(&mut t1); + | -------------^^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `t1` is borrowed for `'static` +LL | } + | - `t1` dropped here while still borrowed + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0499, E0521, E0597. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-88287.stderr b/tests/ui/generic-associated-types/issue-88287.stderr index 79ac6d0f10bd2..54ecc5cfcd810 100644 --- a/tests/ui/generic-associated-types/issue-88287.stderr +++ b/tests/ui/generic-associated-types/issue-88287.stderr @@ -7,11 +7,11 @@ LL | type SearchFutureTy<'f, A, B: 'f> LL | async move { todo!() } | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `>` +note: required by an implicit `Sized` bound in `>` --> $DIR/issue-88287.rs:24:6 | LL | impl SearchableResourceExt for T - | ^ required by this bound in `>` + | ^ required by the implicit `Sized` requirement on this type parameter in `>` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - A: SearchableResource + ?Sized + 'f, diff --git a/tests/ui/generic-associated-types/issue-88360.fixed b/tests/ui/generic-associated-types/issue-88360.fixed index 3dea8bf7ac81d..6fb1e2559c0ac 100644 --- a/tests/ui/generic-associated-types/issue-88360.fixed +++ b/tests/ui/generic-associated-types/issue-88360.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait GatTrait { type Gat<'a> where Self: 'a; diff --git a/tests/ui/generic-associated-types/issue-88360.rs b/tests/ui/generic-associated-types/issue-88360.rs index 4d4c7ea318078..c8f07955b6129 100644 --- a/tests/ui/generic-associated-types/issue-88360.rs +++ b/tests/ui/generic-associated-types/issue-88360.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait GatTrait { type Gat<'a> where Self: 'a; diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr index 49d36acadd657..488e50d2843bf 100644 --- a/tests/ui/generic-associated-types/issue-88360.stderr +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-88360.rs:15:9 + --> $DIR/issue-88360.rs:16:9 | LL | trait SuperTrait | - found this type parameter diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs index add4d58f86a0d..92ce4a0970f36 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs @@ -5,7 +5,7 @@ trait X { type Y; } -trait M { +trait M { //~ NOTE fn f(&self) {} } diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr index 1dd463f996ce6..61512dd46582d 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr @@ -14,6 +14,12 @@ LL | impl = i32>> M for T {} | ^^^^^^^^^^^^ - - | | | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `M` defines an item `f`, perhaps you need to implement it + --> $DIR/method-unsatisfied-assoc-type-predicate.rs:8:1 + | +LL | trait M { + | ^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/generic-const-items/parameter-defaults.stderr b/tests/ui/generic-const-items/parameter-defaults.stderr index 697423e8dc399..b8220af5d0e93 100644 --- a/tests/ui/generic-const-items/parameter-defaults.stderr +++ b/tests/ui/generic-const-items/parameter-defaults.stderr @@ -8,7 +8,7 @@ error[E0282]: type annotations needed for `Option` --> $DIR/parameter-defaults.rs:13:9 | LL | let _ = NONE; - | ^ + | ^ ---- type must be known at this point | help: consider giving this pattern a type, where the type for type parameter `T` is specified | diff --git a/tests/ui/generics/generic-extern.rs b/tests/ui/generics/generic-extern.rs index 3690d6fd07d29..36fa5eaafd672 100644 --- a/tests/ui/generics/generic-extern.rs +++ b/tests/ui/generics/generic-extern.rs @@ -3,5 +3,5 @@ extern "C" { } fn main() { - foo::(); + foo::(); //~ ERROR requires unsafe } diff --git a/tests/ui/generics/generic-extern.stderr b/tests/ui/generics/generic-extern.stderr index 4d9f6fedef14e..a3f2882531638 100644 --- a/tests/ui/generics/generic-extern.stderr +++ b/tests/ui/generics/generic-extern.stderr @@ -6,6 +6,15 @@ LL | fn foo(); | = help: replace the type parameters with concrete types like `u32` -error: aborting due to 1 previous error +error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block + --> $DIR/generic-extern.rs:6:5 + | +LL | foo::(); + | ^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0044`. +Some errors have detailed explanations: E0044, E0133. +For more information about an error, try `rustc --explain E0044`. diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed index aa6d6310f5fe3..f51040358c0b3 100644 --- a/tests/ui/generics/generic-no-mangle.fixed +++ b/tests/ui/generics/generic-no-mangle.fixed @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![deny(no_mangle_generic_items)] diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs index 8a59ca75aafd2..02015331c5712 100644 --- a/tests/ui/generics/generic-no-mangle.rs +++ b/tests/ui/generics/generic-no-mangle.rs @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![deny(no_mangle_generic_items)] #[no_mangle] diff --git a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr index 3f4f50562e252..3739829455bde 100644 --- a/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr +++ b/tests/ui/generics/issue-61631-default-type-param-can-reference-self-in-trait.stderr @@ -6,10 +6,10 @@ LL | impl Tsized for () {} | = help: the trait `Sized` is not implemented for `[()]` note: required by a bound in `Tsized` - --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:14 + --> $DIR/issue-61631-default-type-param-can-reference-self-in-trait.rs:17:17 | LL | trait Tsized {} - | ^^^^^^^^^^^^^^^^^ required by this bound in `Tsized` + | ^^^^^ required by this bound in `Tsized` error: aborting due to 1 previous error diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs index dac973473490e..99de7845d7b65 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs @@ -4,4 +4,5 @@ fn main() { let xs = [13, 1, 5, 2, 3, 1, 21, 8]; let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; //~^ `X..` patterns in slices are experimental + //~| ERROR: refutable pattern } diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr index 8ae8f052e5be4..b011044f4ddc4 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr @@ -8,6 +8,21 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0005]: refutable pattern in local binding + --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:5:9 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `[i32; 8]` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0005, E0658. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs index a2a4c62fa0295..33b99259dfec9 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs @@ -1,7 +1,6 @@ // Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges. #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] fn main() {} diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr index 6b20a820b7302..1e68235303b2e 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:14:8 | LL | m!(0f32, f32::NEG_INFINITY..); | ^^^^ pattern `_` not covered @@ -11,7 +11,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() } | ++++++++++++++ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8 | LL | m!(0f32, ..f32::INFINITY); | ^^^^ pattern `_` not covered @@ -23,7 +23,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() } | ++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:24:8 | LL | m!('a', ..core::char::MAX); | ^^^ pattern `'\u{10ffff}'` not covered @@ -35,7 +35,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8 | LL | m!('a', ..ALMOST_MAX); | ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered @@ -47,7 +47,7 @@ LL | match $s { $($t)+ => {}, '\u{10fffe}'..='\u{10ffff}' => todo!() } | ++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\0'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8 | LL | m!('a', ALMOST_MIN..); | ^^^ pattern `'\0'` not covered @@ -59,7 +59,7 @@ LL | match $s { $($t)+ => {}, '\0' => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8 | LL | m!('a', ..=ALMOST_MAX); | ^^^ pattern `'\u{10ffff}'` not covered @@ -71,7 +71,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() } | +++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `'b'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8 | LL | m!('a', ..=VAL | VAL_2..); | ^^^ pattern `'b'` not covered @@ -83,7 +83,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() } | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `'b'` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8 | LL | m!('a', ..VAL_1 | VAL_2..); | ^^^ pattern `'b'` not covered @@ -95,7 +95,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() } | ++++++++++++++++ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:39:12 | LL | m!(0, ..u8::MAX); | ^ pattern `u8::MAX` not covered @@ -107,7 +107,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `254_u8..=u8::MAX` not covered @@ -119,7 +119,7 @@ LL | match $s { $($t)+ => {}, 254_u8..=u8::MAX => todo!() } | +++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u8` not covered @@ -131,7 +131,7 @@ LL | match $s { $($t)+ => {}, 0_u8 => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `u8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u8::MAX` not covered @@ -143,7 +143,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u8` not covered @@ -155,7 +155,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u8` not covered @@ -167,7 +167,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:52:12 | LL | m!(0, ..u16::MAX); | ^ pattern `u16::MAX` not covered @@ -179,7 +179,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `65534_u16..=u16::MAX` not covered @@ -191,7 +191,7 @@ LL | match $s { $($t)+ => {}, 65534_u16..=u16::MAX => todo!() } | +++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u16` not covered @@ -203,7 +203,7 @@ LL | match $s { $($t)+ => {}, 0_u16 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u16::MAX` not covered @@ -215,7 +215,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u16` not covered @@ -227,7 +227,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u16` not covered @@ -239,7 +239,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:65:12 | LL | m!(0, ..u32::MAX); | ^ pattern `u32::MAX` not covered @@ -251,7 +251,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `4294967294_u32..=u32::MAX` not covered @@ -263,7 +263,7 @@ LL | match $s { $($t)+ => {}, 4294967294_u32..=u32::MAX => todo!() } | ++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u32` not covered @@ -275,7 +275,7 @@ LL | match $s { $($t)+ => {}, 0_u32 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u32::MAX` not covered @@ -287,7 +287,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u32` not covered @@ -299,7 +299,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u32` not covered @@ -311,7 +311,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:78:12 | LL | m!(0, ..u64::MAX); | ^ pattern `u64::MAX` not covered @@ -323,7 +323,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `18446744073709551614_u64..=u64::MAX` not covered @@ -335,7 +335,7 @@ LL | match $s { $($t)+ => {}, 18446744073709551614_u64..=u64::MAX => tod | ++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u64` not covered @@ -347,7 +347,7 @@ LL | match $s { $($t)+ => {}, 0_u64 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u64::MAX` not covered @@ -359,7 +359,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u64` not covered @@ -371,7 +371,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u64` not covered @@ -383,7 +383,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:91:12 | LL | m!(0, ..u128::MAX); | ^ pattern `u128::MAX` not covered @@ -395,7 +395,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered @@ -407,7 +407,7 @@ LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `0_u128` not covered @@ -419,7 +419,7 @@ LL | match $s { $($t)+ => {}, 0_u128 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `u128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `u128::MAX` not covered @@ -431,7 +431,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_u128` not covered @@ -443,7 +443,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_u128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_u128` not covered @@ -455,7 +455,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:107:12 | LL | m!(0, ..i8::MAX); | ^ pattern `i8::MAX` not covered @@ -467,7 +467,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `126_i8..=i8::MAX` not covered @@ -479,7 +479,7 @@ LL | match $s { $($t)+ => {}, 126_i8..=i8::MAX => todo!() } | +++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i8::MIN` not covered @@ -491,7 +491,7 @@ LL | match $s { $($t)+ => {}, i8::MIN => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i8::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i8::MAX` not covered @@ -503,7 +503,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i8` not covered @@ -515,7 +515,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i8` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i8` not covered @@ -527,7 +527,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() } | ++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:120:12 | LL | m!(0, ..i16::MAX); | ^ pattern `i16::MAX` not covered @@ -539,7 +539,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `32766_i16..=i16::MAX` not covered @@ -551,7 +551,7 @@ LL | match $s { $($t)+ => {}, 32766_i16..=i16::MAX => todo!() } | +++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i16::MIN` not covered @@ -563,7 +563,7 @@ LL | match $s { $($t)+ => {}, i16::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i16::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i16::MAX` not covered @@ -575,7 +575,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i16` not covered @@ -587,7 +587,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i16` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i16` not covered @@ -599,7 +599,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:133:12 | LL | m!(0, ..i32::MAX); | ^ pattern `i32::MAX` not covered @@ -611,7 +611,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `2147483646_i32..=i32::MAX` not covered @@ -623,7 +623,7 @@ LL | match $s { $($t)+ => {}, 2147483646_i32..=i32::MAX => todo!() } | ++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i32::MIN` not covered @@ -635,7 +635,7 @@ LL | match $s { $($t)+ => {}, i32::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i32::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i32::MAX` not covered @@ -647,7 +647,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i32` not covered @@ -659,7 +659,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i32` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i32` not covered @@ -671,7 +671,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:146:12 | LL | m!(0, ..i64::MAX); | ^ pattern `i64::MAX` not covered @@ -683,7 +683,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `9223372036854775806_i64..=i64::MAX` not covered @@ -695,7 +695,7 @@ LL | match $s { $($t)+ => {}, 9223372036854775806_i64..=i64::MAX => todo | +++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i64::MIN` not covered @@ -707,7 +707,7 @@ LL | match $s { $($t)+ => {}, i64::MIN => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i64::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i64::MAX` not covered @@ -719,7 +719,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() } | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i64` not covered @@ -731,7 +731,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i64` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i64` not covered @@ -743,7 +743,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() } | +++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:159:12 | LL | m!(0, ..i128::MAX); | ^ pattern `i128::MAX` not covered @@ -755,7 +755,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12 | LL | m!(0, ..ALMOST_MAX); | ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered @@ -767,7 +767,7 @@ LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MIN` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 | LL | m!(0, ALMOST_MIN..); | ^ pattern `i128::MIN` not covered @@ -779,7 +779,7 @@ LL | match $s { $($t)+ => {}, i128::MIN => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MAX` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 | LL | m!(0, ..=ALMOST_MAX); | ^ pattern `i128::MAX` not covered @@ -791,7 +791,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12 | LL | m!(0, ..=VAL | VAL_2..); | ^ pattern `43_i128` not covered @@ -803,7 +803,7 @@ LL | match $s { $($t)+ => {}, 43_i128 => todo!() } | ++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `43_i128` not covered - --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12 + --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12 | LL | m!(0, ..VAL_1 | VAL_2..); | ^ pattern `43_i128` not covered diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs index 526a797e9d649..33506a5c444a7 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs @@ -23,6 +23,7 @@ fn syntax2() { macro_rules! mac { ($e:expr) => { let ...$e; //~ ERROR range-to patterns with `...` are not allowed + //~^ ERROR refutable pattern in local binding } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr index ddffeaf978059..6832f21f25e99 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -33,5 +33,24 @@ LL | mac!(0); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17 + | +LL | let ...$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ...$e; { todo!() } + | ++ +++++++++++ + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs index 30173b1b4be03..cff0c42eb52fc 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs @@ -1,6 +1,9 @@ fn main() { let x = 42; match x { + //~^ ERROR: non-exhaustive patterns + //~| NOTE: not covered + //~| NOTE: matched value is of type 0..=73 => {}, 74..=> {}, //~^ ERROR unexpected `>` after inclusive range diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr index 8dfc46069f13f..ecb43e83c70ee 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr @@ -1,5 +1,5 @@ error: unexpected `>` after inclusive range - --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14 + --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:8:14 | LL | 74..=> {}, | ---^ @@ -11,5 +11,19 @@ help: add a space between the pattern and `=>` LL | 74.. => {}, | + -error: aborting due to 1 previous error +error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` not covered + --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:3:11 + | +LL | match x { + | ^ pattern `i32::MIN..=-1_i32` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 74..=> {}, +LL ~ i32::MIN..=-1_i32 => todo!(), + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs index 6567c8cc67cb0..2f1ec65897211 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs @@ -16,7 +16,9 @@ fn bar() { macro_rules! mac { ($e:expr) => { let $e...; //~ ERROR inclusive range with no end + //~^ ERROR: refutable pattern let $e..=; //~ ERROR inclusive range with no end + //~^ ERROR: refutable pattern } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr index 3ad84b0ef26f8..cb9e48e70e391 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -43,7 +43,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/half-open-range-pats-inclusive-no-end.rs:19:19 + --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19 | LL | let $e..=; | ^^^ help: use `..` instead @@ -54,6 +54,43 @@ LL | mac!(0); = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-no-end.rs:18:17 + | +LL | let $e...; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e...; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:17 + | +LL | let $e..=; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..=; { todo!() } + | ++ +++++++++++ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0586`. +Some errors have detailed explanations: E0005, E0586. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs index 6c6ba93196b64..d5af7bea54388 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-semantics.rs @@ -4,7 +4,6 @@ // via `.contains(...)` and make sure the dynamic semantics match. #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] #![allow(unreachable_patterns)] macro_rules! yes { diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs index 4b14a314e7aea..158da6509662f 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs @@ -1,5 +1,4 @@ #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] macro_rules! m { ($s:expr, $($t:tt)+) => { diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr index e9702bb380fb3..169e776fc20fd 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr @@ -1,77 +1,77 @@ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:10:11 | LL | m!(0, ..u8::MIN); | ^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:13:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11 | LL | m!(0, ..u16::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11 | LL | m!(0, ..u32::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:16:11 | LL | m!(0, ..u64::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:19:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11 | LL | m!(0, ..u128::MIN); | ^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:22:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11 | LL | m!(0, ..i8::MIN); | ^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11 | LL | m!(0, ..i16::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:26:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:25:11 | LL | m!(0, ..i32::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11 | LL | m!(0, ..i64::MIN); | ^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:29:11 | LL | m!(0, ..i128::MIN); | ^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:14 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:32:14 | LL | m!(0f32, ..f32::NEG_INFINITY); | ^^^^^^^^^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:35:14 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:34:14 | LL | m!(0f64, ..f64::NEG_INFINITY); | ^^^^^^^^^^^^^^^^^^^ error[E0579]: lower range bound must be less than upper - --> $DIR/half-open-range-pats-thir-lower-empty.rs:38:13 + --> $DIR/half-open-range-pats-thir-lower-empty.rs:37:13 | LL | m!('a', ..'\u{0}'); | ^^^^^^^^^ diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs index acb7feac132f4..e6d5e64a15b7a 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions0.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions0.rs @@ -1,5 +1,4 @@ // run-pass -#![allow(incomplete_features)] #![feature(exclusive_range_pattern)] #![feature(inline_const_pat)] diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs index c37af75b8fb29..cd38154437266 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs @@ -5,4 +5,5 @@ fn main() { //~^ `X..` patterns in slices are experimental //~| exclusive range pattern syntax is experimental //~| exclusive range pattern syntax is experimental + //~| ERROR: refutable pattern } diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr index be8f3aa5051e3..fc549eb65c0ed 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr @@ -30,6 +30,21 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: use an inclusive range pattern, like N..=M -error: aborting due to 3 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/slice_pattern_syntax_problem1.rs:4:9 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `[i32; 8]` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0005, E0658. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs index bd4533e0433ff..dc865605ed3c0 100644 --- a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs +++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs @@ -12,10 +12,12 @@ fn hr_subtype<'c>(f: for<'a, 'b> fn(Inv<'a>, Inv<'a>)) { fn simple1<'c>(x: (&'c i32,)) { let _x: (&'static i32,) = x; + //~^ ERROR: lifetime may not live long enough } fn simple2<'c>(x: (&'c i32,)) { let _: (&'static i32,) = x; + //~^ ERROR: lifetime may not live long enough } fn main() { diff --git a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr index c6d6f50832829..39d43181ed7d6 100644 --- a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr +++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr @@ -9,6 +9,22 @@ LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub; = note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)` found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/placeholder-pattern-fail.rs:14:13 + | +LL | fn simple1<'c>(x: (&'c i32,)) { + | -- lifetime `'c` defined here +LL | let _x: (&'static i32,) = x; + | ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/placeholder-pattern-fail.rs:19:12 + | +LL | fn simple2<'c>(x: (&'c i32,)) { + | -- lifetime `'c` defined here +LL | let _: (&'static i32,) = x; + | ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr index 77aa37cefe363..b322ea41c436d 100644 --- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr +++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.classic.stderr @@ -2,7 +2,7 @@ error[E0277]: expected a `Fn(&'w ())` closure, found `fn(&'w ())` --> $DIR/fn-ptr.rs:12:5 | LL | ice(); - | ^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())` + | ^^^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())` | = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())` note: required by a bound in `ice` diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs index 48ebe5017aa62..33e0ec4635b66 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs @@ -18,7 +18,7 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) want_foo_for_any_tcx(f); //~ ERROR not satisfied } -fn want_foo_for_any_tcx(f: &F) +fn want_foo_for_any_tcx(f: &F) //~ WARN cannot return without recursing where F : for<'tcx> Foo<'tcx> { want_foo_for_some_tcx(f); @@ -35,7 +35,7 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_bar_for_any_ccx(b); //~ ERROR not satisfied } -fn want_bar_for_any_ccx(b: &B) +fn want_bar_for_any_ccx(b: &B) //~ WARN cannot return without recursing where B : for<'ccx> Bar<'ccx> { want_foo_for_some_tcx(b); diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr index 7f96909b6e76e..f220ba6f33893 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr @@ -38,6 +38,31 @@ help: consider further restricting this bound LL | where B : Bar<'x> + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ -error: aborting due to 2 previous errors +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + | +LL | / fn want_foo_for_any_tcx(f: &F) +LL | | where F : for<'tcx> Foo<'tcx> + | |_________________________________^ cannot return without recursing +... +LL | want_foo_for_any_tcx(f); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 + | +LL | / fn want_bar_for_any_ccx(b: &B) +LL | | where B : for<'ccx> Bar<'ccx> + | |_________________________________^ cannot return without recursing +... +LL | want_bar_for_any_ccx(b); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to 2 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr index 73870703cfbac..699a4ecc42bb9 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr @@ -15,6 +15,12 @@ note: the following trait bounds were not satisfied: | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `filterx`, perhaps you need to implement it + --> $DIR/issue-30786.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ error[E0599]: the method `countx` exists for struct `Filter &u64 {identity::}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:132:24 @@ -33,6 +39,12 @@ note: the following trait bounds were not satisfied: | LL | impl StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `countx`, perhaps you need to implement it + --> $DIR/issue-30786.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr index 3240518fbbe08..e60531a876be1 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-85455.stderr @@ -13,7 +13,7 @@ error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied --> $DIR/issue-85455.rs:8:5 | LL | callee:: >::Associated>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr index 7fe803550bddf..761fd9045a13a 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied --> $DIR/issue-89118.rs:19:8 | LL | C: StackContext, - | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-89118.rs:1:1 @@ -29,7 +29,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied --> $DIR/issue-89118.rs:29:9 | LL | impl EthernetWorker {} - | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-89118.rs:1:1 @@ -56,7 +56,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied --> $DIR/issue-89118.rs:22:20 | LL | type Handler = Ctx; - | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()` + | ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`, which is required by `for<'a> Ctx<()>: BufferUdpStateContext<&'a ()>` | help: this trait has no implementations, consider adding one --> $DIR/issue-89118.rs:1:1 diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs index ab9d9a7ce6f08..7072f41066b3a 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs @@ -1,5 +1,4 @@ -// check-fail -// known-bug: #90950 +// check-pass trait Yokeable<'a>: 'static { type Output: 'a; diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr deleted file mode 100644 index 075e422e29c0b..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0277]: the trait bound `for<'a> <_ as Yokeable<'a>>::Output: IsCovariant<'a>` is not satisfied - --> $DIR/issue-90950.rs:50:12 - | -LL | upcast(y) - | ------ ^ the trait `for<'a> IsCovariant<'a>` is not implemented for `<_ as Yokeable<'a>>::Output` - | | - | required by a bound introduced by this call - | - = help: the trait `IsCovariant<'a>` is implemented for `std::borrow::Cow<'a, T>` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/issue-90950.rs:50:12 - | -LL | upcast(y) - | -------^- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant -note: required by a bound in `upcast` - --> $DIR/issue-90950.rs:27:42 - | -LL | fn upcast(x: Yoke) -> Yoke + 'static>> where - | ------ required by a bound in this function -LL | Y: for<'a> Yokeable<'a>, -LL | for<'a> >::Output: IsCovariant<'a> - | ^^^^^^^^^^^^^^^ required by this bound in `upcast` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs index 7693b11824762..58ca5b0c1874a 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs @@ -1,5 +1,4 @@ -// check-fail -// known-bug: #89196 +// check-pass // Should pass, but we normalize and check bounds before we resolve the generics // of the function (which we know because of the return type). diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr deleted file mode 100644 index a2ec96f1a2d0f..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0277]: the trait bound `for<'a> <_ as Trait<'a>>::Out: Copy` is not satisfied - --> $DIR/norm-before-method-resolution.rs:22:17 - | -LL | let _: () = weird_bound(); - | ^^^^^^^^^^^ the trait `for<'a> Copy` is not implemented for `<_ as Trait<'a>>::Out` - | -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/norm-before-method-resolution.rs:22:17 - | -LL | let _: () = weird_bound(); - | ^^^^^^^^^^^ try adding turbofish arguments to this expression to specify the types manually, even if it's redundant -note: required by a bound in `weird_bound` - --> $DIR/norm-before-method-resolution.rs:18:40 - | -LL | fn weird_bound() -> X - | ----------- required by a bound in this function -... -LL | for<'a> >::Out: Copy - | ^^^^ required by this bound in `weird_bound` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5824ef31211be..5c552411da7f3 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:570:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/impl-trait/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leak2.stderr index 52fa28145d664..1fcde0372fc96 100644 --- a/tests/ui/impl-trait/auto-trait-leak2.stderr +++ b/tests/ui/impl-trait/auto-trait-leak2.stderr @@ -9,7 +9,7 @@ LL | send(before()); | | | required by a bound introduced by this call | - = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>`, which is required by `impl Fn(i32): Send` note: required because it's used within this closure --> $DIR/auto-trait-leak2.rs:10:5 | @@ -37,7 +37,7 @@ LL | send(after()); LL | fn after() -> impl Fn(i32) { | ------------ within this `impl Fn(i32)` | - = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` + = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>`, which is required by `impl Fn(i32): Send` note: required because it's used within this closure --> $DIR/auto-trait-leak2.rs:38:5 | diff --git a/tests/ui/impl-trait/cross-return-site-inference.stderr b/tests/ui/impl-trait/cross-return-site-inference.stderr index 8ee3e9abf9ccb..5512c234af985 100644 --- a/tests/ui/impl-trait/cross-return-site-inference.stderr +++ b/tests/ui/impl-trait/cross-return-site-inference.stderr @@ -13,7 +13,7 @@ error[E0790]: cannot call associated function on trait without specifying the co --> $DIR/cross-return-site-inference.rs:38:16 | LL | return Err(From::from("foo")); - | ^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | @@ -24,7 +24,7 @@ error[E0790]: cannot call associated function on trait without specifying the co --> $DIR/cross-return-site-inference.rs:44:9 | LL | Err(From::from("foo")) - | ^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 9cc199d1e0ec6..f25269ca03207 100644 --- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -16,7 +16,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) } | | | doesn't have a size known at compile-time | - = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized` = note: required because it appears within the type `(usize, (dyn Trait + 'static))` = note: the return type of a function must have a statically known size @@ -38,7 +38,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } | | | doesn't have a size known at compile-time | - = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`, which is required by `(usize, (dyn Trait + 'static)): Sized` = note: required because it appears within the type `(usize, (dyn Trait + 'static))` = note: the return type of a function must have a statically known size diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr index 1011fc4163bca..0e3cd2ff06099 100644 --- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr +++ b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr @@ -1,4 +1,4 @@ -note: no errors encountered even though `span_delayed_bug` issued +note: no errors encountered even though delayed bugs were created note: those delayed bugs will now be shown as internal compiler errors diff --git a/tests/ui/impl-trait/example-st.rs b/tests/ui/impl-trait/example-st.rs index 4e1aa3a085921..1e6ebc52365dc 100644 --- a/tests/ui/impl-trait/example-st.rs +++ b/tests/ui/impl-trait/example-st.rs @@ -3,7 +3,7 @@ struct State; type Error = (); -trait Bind { +trait Bind { //~ WARN trait `Bind` is never used type Output; fn bind(self, f: F) -> Self::Output; } diff --git a/tests/ui/impl-trait/example-st.stderr b/tests/ui/impl-trait/example-st.stderr new file mode 100644 index 0000000000000..f722d7f658215 --- /dev/null +++ b/tests/ui/impl-trait/example-st.stderr @@ -0,0 +1,10 @@ +warning: trait `Bind` is never used + --> $DIR/example-st.rs:6:7 + | +LL | trait Bind { + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs index 57d688492515b..e1aba8eda1bff 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs @@ -4,10 +4,6 @@ fn ice() -> impl AsRef { //~^ WARN trait objects without an explicit `dyn` are deprecated - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! Foo } diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr index ab6d8355e07bb..3cb3af89bfc25 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr @@ -12,33 +12,5 @@ help: if this is an object-safe trait, use `dyn` LL | fn ice() -> impl AsRef { | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn ice() -> impl AsRef { - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 - | -LL | fn ice() -> impl AsRef { - | ^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | fn ice() -> impl AsRef { - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/impl-trait/impl_trait_projections.stderr b/tests/ui/impl-trait/impl_trait_projections.stderr index 700aff36aa509..421afc96eed07 100644 --- a/tests/ui/impl-trait/impl_trait_projections.stderr +++ b/tests/ui/impl-trait/impl_trait_projections.stderr @@ -32,7 +32,7 @@ error[E0277]: the trait bound `impl Debug: Step` is not satisfied --> $DIR/impl_trait_projections.rs:26:8 | LL | -> <::std::ops::Range as Iterator>::Item - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Step` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range: Iterator` | = help: the following other types implement trait `Step`: char @@ -53,7 +53,7 @@ LL | / { LL | | LL | | (1i32..100).next().unwrap() LL | | } - | |_^ the trait `Step` is not implemented for `impl Debug` + | |_^ the trait `Step` is not implemented for `impl Debug`, which is required by `std::ops::Range: Iterator` | = help: the following other types implement trait `Step`: char diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs index 650cb3870d581..daf29a0005dec 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs @@ -20,7 +20,6 @@ impl dyn MyTrait { MyTrait::foo(&self) //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied - //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied //~| ERROR the trait `MyTrait` cannot be made into an object } } diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr index 01de3e531952c..90285d512ef03 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr @@ -32,14 +32,6 @@ LL | MyTrait::foo(&self) | = help: the trait `MyTrait` is implemented for `Outer` -error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 - | -LL | MyTrait::foo(&self) - | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` - | - = help: the trait `MyTrait` is implemented for `Outer` - error[E0038]: the trait `MyTrait` cannot be made into an object --> $DIR/cycle-effective-visibilities-during-object-safety.rs:16:6 | @@ -72,7 +64,7 @@ LL | fn foo(&self) -> impl Marker; = help: consider moving `foo` to another trait = help: only type `Outer` implements the trait, consider using it directly instead -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0038, E0277. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/impl-trait/in-trait/issue-102140.rs b/tests/ui/impl-trait/in-trait/issue-102140.rs index 7960018482fce..9d703cf0df1bc 100644 --- a/tests/ui/impl-trait/in-trait/issue-102140.rs +++ b/tests/ui/impl-trait/in-trait/issue-102140.rs @@ -20,7 +20,6 @@ impl dyn MyTrait { MyTrait::foo(&self) //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied - //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied } } diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr index 9cd2cdfd1a53e..dc3dcc114aed5 100644 --- a/tests/ui/impl-trait/in-trait/issue-102140.stderr +++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr @@ -20,14 +20,6 @@ LL | MyTrait::foo(&self) | = help: the trait `MyTrait` is implemented for `Outer` -error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/issue-102140.rs:20:9 - | -LL | MyTrait::foo(&self) - | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` - | - = help: the trait `MyTrait` is implemented for `Outer` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed index 8dc8e045d4738..ecc8488a15299 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed @@ -1,6 +1,7 @@ // edition:2021 // run-rustfix +#![allow(dead_code)] trait Trait { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs index 30b04d87b9a3e..860fea07df964 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs @@ -1,6 +1,7 @@ // edition:2021 // run-rustfix +#![allow(dead_code)] trait Trait { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr index cf68ed87030a9..45fd79badb30f 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`, `baz` - --> $DIR/suggest-missing-item.rs:19:1 + --> $DIR/suggest-missing-item.rs:20:1 | LL | async fn foo(); | --------------- `foo` from trait diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr index c20df9b40edfb..7d42659d81edb 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -5,7 +5,7 @@ LL | fn nya() -> impl Wf>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `[u8]` cannot be known at compilation time @@ -15,11 +15,11 @@ LL | fn nya2() -> impl Wf<[u8]>; | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Wf` +note: required by an implicit `Sized` bound in `Wf` --> $DIR/wf-bounds.rs:7:10 | LL | trait Wf { - | ^ required by this bound in `Wf` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wf` help: consider relaxing the implicit `Sized` restriction | LL | trait Wf { @@ -32,7 +32,7 @@ LL | fn nya3() -> impl Wf<(), Output = impl Wf>>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: `T` doesn't implement `std::fmt::Display` diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr index 8912cce1b4b5b..0c86824e62217 100644 --- a/tests/ui/impl-trait/issue-55872-1.stderr +++ b/tests/ui/impl-trait/issue-55872-1.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)` --> $DIR/issue-55872-1.rs:12:29 | LL | fn foo() -> Self::E { - | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` + | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`, which is required by `(S, T): Copy` | = note: required because it appears within the type `(S, T)` help: consider further restricting this bound @@ -23,7 +23,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)` --> $DIR/issue-55872-1.rs:12:29 | LL | fn foo() -> Self::E { - | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` + | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`, which is required by `(S, T): Copy` | = note: required because it appears within the type `(S, T)` help: consider further restricting this bound diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs index 18404f9860317..9762ac982721f 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -16,12 +16,16 @@ fn foo<'a>(x: &i32) -> impl Copy + 'a { x } //~^ ERROR explicit lifetime required in the type of `x` fn elided3(x: &i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn elided4(x: &i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } //~^ ERROR lifetime may not live long enough diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr index c60fe08c5d7c5..273f51ddbe35c 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -67,7 +67,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:26:55 + --> $DIR/must_outlive_least_region_or_bound.rs:30:55 | LL | fn elided5(x: &i32) -> (Box, impl Debug) { (Box::new(x), x) } | - ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` @@ -84,7 +84,7 @@ LL | fn elided5(x: &i32) -> (Box, impl Debug + '_) { (Box::new(x), x) | ++++ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:32:69 + --> $DIR/must_outlive_least_region_or_bound.rs:36:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -99,12 +99,12 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ~~~~~~~~~~~~ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:38:5 + --> $DIR/must_outlive_least_region_or_bound.rs:42:5 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- ---------------- opaque type defined here | | - | hidden type `{closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13}` captures the lifetime `'b` as defined here + | hidden type `{closure@$DIR/must_outlive_least_region_or_bound.rs:42:5: 42:13}` captures the lifetime `'b` as defined here LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -114,7 +114,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | ++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:43:5 + --> $DIR/must_outlive_least_region_or_bound.rs:47:5 | LL | x | ^ @@ -127,7 +127,63 @@ help: consider adding an explicit lifetime bound LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | +++++++++ -error: aborting due to 9 previous errors +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:18:41 + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | - ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided3(x: &i32) -> Box { Box::new(x) } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:21:50 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | -- lifetime `'a` defined here ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound + | +LL | fn explicit3<'a>(x: &'a i32) -> Box { Box::new(x) } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:24:51 + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | - ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn elided4(x: &i32) -> Box { Box::new(x) } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn elided4(x: &'static i32) -> Box { Box::new(x) } + | ~~~~~~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | -- lifetime `'a` defined here ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn explicit4<'a>(x: &'a i32) -> Box { Box::new(x) } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn explicit4<'a>(x: &'static i32) -> Box { Box::new(x) } + | ~~~~~~~~~~~~ + +error: aborting due to 13 previous errors Some errors have detailed explanations: E0310, E0621, E0700. For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index 31c3e0c901365..83d1347aff431 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -46,7 +46,7 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug`, which is required by `impl Into: Into` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` @@ -55,7 +55,7 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug`, which is required by `impl Into: Into` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 7fd2ec57b1455..f77b4bd517f43 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -4,5 +4,29 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/normalize-tait-in-const.rs:26:5 + | +LL | fun(filter_positive()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) { + | ++++++++++++++++++++++++++++++++++++ + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/normalize-tait-in-const.rs:25:79 + | +LL | const fn with_positive Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^ the destructor for this type cannot be evaluated in constant functions +LL | fun(filter_positive()); +LL | } + | - value is dropped here + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/impl-trait/type-alias-generic-param.rs b/tests/ui/impl-trait/type-alias-generic-param.rs index 1211625dac9cc..e4b2e4124202f 100644 --- a/tests/ui/impl-trait/type-alias-generic-param.rs +++ b/tests/ui/impl-trait/type-alias-generic-param.rs @@ -5,7 +5,7 @@ // run-pass #![feature(impl_trait_in_assoc_type)] -trait Meow { +trait Meow { //~ WARN trait `Meow` is never used type MeowType; fn meow(self) -> Self::MeowType; } diff --git a/tests/ui/impl-trait/type-alias-generic-param.stderr b/tests/ui/impl-trait/type-alias-generic-param.stderr new file mode 100644 index 0000000000000..e4115dc1319d1 --- /dev/null +++ b/tests/ui/impl-trait/type-alias-generic-param.stderr @@ -0,0 +1,10 @@ +warning: trait `Meow` is never used + --> $DIR/type-alias-generic-param.rs:8:7 + | +LL | trait Meow { + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr index 2731ed2ba86d3..6c7d79174daf6 100644 --- a/tests/ui/imports/ambiguous-9.stderr +++ b/tests/ui/imports/ambiguous-9.stderr @@ -60,7 +60,6 @@ note: `date_range` could also refer to the function imported here LL | use prelude::*; | ^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` warning: 4 warnings emitted diff --git a/tests/ui/imports/empty-import-prefix-pass-2015.rs b/tests/ui/imports/empty-import-prefix-pass-2015.rs new file mode 100644 index 0000000000000..a3278007c119a --- /dev/null +++ b/tests/ui/imports/empty-import-prefix-pass-2015.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2015 + +use {}; +use {{}}; + +use ::{}; +use {::{}}; + +fn main() {} diff --git a/tests/ui/imports/empty-import-prefix-pass.rs b/tests/ui/imports/empty-import-prefix-pass.rs new file mode 100644 index 0000000000000..d76c0da4bd8eb --- /dev/null +++ b/tests/ui/imports/empty-import-prefix-pass.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2018 + +use {}; +use {{}}; + +use ::{}; +use {::{}}; + +fn main() {} diff --git a/tests/ui/imports/issue-28134.rs b/tests/ui/imports/issue-28134.rs index ef2a5d634a678..0cecdf7a0ec73 100644 --- a/tests/ui/imports/issue-28134.rs +++ b/tests/ui/imports/issue-28134.rs @@ -1,5 +1,5 @@ // compile-flags: --test #![allow(soft_unstable)] -#![test] //~ ERROR cannot determine resolution for the attribute macro `test` +#![test] //~^ ERROR 4:1: 4:9: `test` attribute cannot be used at crate level diff --git a/tests/ui/imports/issue-28134.stderr b/tests/ui/imports/issue-28134.stderr index 5315c2e9fee9c..e47aa15e87a94 100644 --- a/tests/ui/imports/issue-28134.stderr +++ b/tests/ui/imports/issue-28134.stderr @@ -1,11 +1,3 @@ -error: cannot determine resolution for the attribute macro `test` - --> $DIR/issue-28134.rs:4:4 - | -LL | #![test] - | ^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `test` attribute cannot be used at crate level --> $DIR/issue-28134.rs:4:1 | @@ -18,5 +10,5 @@ LL - #![test] LL + #[test] | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-55457.rs b/tests/ui/imports/issue-55457.rs index c1f048897d9ea..fd08294025587 100644 --- a/tests/ui/imports/issue-55457.rs +++ b/tests/ui/imports/issue-55457.rs @@ -1,10 +1,9 @@ use NonExistent; //~ ERROR unresolved import `NonExistent` use non_existent::non_existent; //~ ERROR unresolved import `non_existent` -#[non_existent] //~ ERROR cannot determine resolution for the attribute macro `non_existent` -#[derive(NonExistent)] //~ ERROR cannot determine resolution for the derive macro `NonExistent` - //~| ERROR cannot determine resolution for the derive macro `NonExistent` - //~| ERROR cannot determine resolution for the derive macro `NonExistent` +#[non_existent] +#[derive(NonExistent)] + struct S; fn main() {} diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr index 30d2373652b4c..09bb13a060478 100644 --- a/tests/ui/imports/issue-55457.stderr +++ b/tests/ui/imports/issue-55457.stderr @@ -15,40 +15,6 @@ LL | use non_existent::non_existent; | = help: consider adding `extern crate non_existent` to use the `non_existent` crate -error: cannot determine resolution for the derive macro `NonExistent` - --> $DIR/issue-55457.rs:5:10 - | -LL | #[derive(NonExistent)] - | ^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the attribute macro `non_existent` - --> $DIR/issue-55457.rs:4:3 - | -LL | #[non_existent] - | ^^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: cannot determine resolution for the derive macro `NonExistent` - --> $DIR/issue-55457.rs:5:10 - | -LL | #[derive(NonExistent)] - | ^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: cannot determine resolution for the derive macro `NonExistent` - --> $DIR/issue-55457.rs:5:10 - | -LL | #[derive(NonExistent)] - | ^^^^^^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/issue-59764.rs b/tests/ui/imports/issue-59764.rs index 09dee8c273268..91b3ddcd84d57 100644 --- a/tests/ui/imports/issue-59764.rs +++ b/tests/ui/imports/issue-59764.rs @@ -128,7 +128,6 @@ use issue_59764::foo::makro; //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432] makro!(bar); -//~^ ERROR cannot determine resolution for the macro `makro` fn main() { bar(); diff --git a/tests/ui/imports/issue-59764.stderr b/tests/ui/imports/issue-59764.stderr index b969515e2f0e6..fe58eb97b8dbf 100644 --- a/tests/ui/imports/issue-59764.stderr +++ b/tests/ui/imports/issue-59764.stderr @@ -226,21 +226,13 @@ help: a macro with this name exists at the root of the crate LL | use issue_59764::makro; | ~~~~~~~~~~~~~~~~~~ -error: cannot determine resolution for the macro `makro` - --> $DIR/issue-59764.rs:130:1 - | -LL | makro!(bar); - | ^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error[E0425]: cannot find function `bar` in this scope - --> $DIR/issue-59764.rs:134:5 + --> $DIR/issue-59764.rs:133:5 | LL | bar(); | ^^^ not found in this scope -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors Some errors have detailed explanations: E0425, E0432. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index 4ec28ddf87171..1291bf2a4611e 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `i32` LL | x[0i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`, which is required by `Vec<{integer}>: Index<_>` = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec<{integer}>` to implement `Index` diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 3041c2c99a108..38e7881dcc675 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `u8` LL | [0][0u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`, which is required by `[{integer}; 1]: Index<_>` = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[{integer}]` to implement `Index` diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr index 4cced22789f74..df4d7cc0683d5 100644 --- a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied --> $DIR/point-at-index-for-obligation-failure.rs:5:9 | LL | &s - | ^^ the trait `Borrow<&str>` is not implemented for `String` + | ^^ the trait `Borrow<&str>` is not implemented for `String`, which is required by `HashMap: Index<&_>` | = help: the trait `Borrow` is implemented for `String` = help: for that trait implementation, expected `str`, found `&str` diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr index 9be1828648011..546e679f2d0bc 100644 --- a/tests/ui/inference/erase-type-params-in-label.stderr +++ b/tests/ui/inference/erase-type-params-in-label.stderr @@ -2,7 +2,7 @@ error[E0283]: type annotations needed for `Foo` --> $DIR/erase-type-params-in-label.rs:2:9 | LL | let foo = foo(1, ""); - | ^^^ --- type must be known at this point + | ^^^ ---------- type must be known at this point | = note: cannot satisfy `_: Default` note: required by a bound in `foo` @@ -19,7 +19,7 @@ error[E0283]: type annotations needed for `Bar` --> $DIR/erase-type-params-in-label.rs:5:9 | LL | let bar = bar(1, ""); - | ^^^ --- type must be known at this point + | ^^^ ---------- type must be known at this point | = note: cannot satisfy `_: Default` note: required by a bound in `bar` diff --git a/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr b/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr index aeebf68e67576..5576e17546873 100644 --- a/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr +++ b/tests/ui/inference/need_type_info/infer-var-for-self-param.stderr @@ -2,7 +2,7 @@ error[E0790]: cannot call associated function on trait without specifying the co --> $DIR/infer-var-for-self-param.rs:5:14 | LL | let _ = (Default::default(),); - | ^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use a fully-qualified path to a specific available implementation | diff --git a/tests/ui/inference/need_type_info/type-alias.rs b/tests/ui/inference/need_type_info/type-alias.rs index f921b046b6cac..b24af2d484954 100644 --- a/tests/ui/inference/need_type_info/type-alias.rs +++ b/tests/ui/inference/need_type_info/type-alias.rs @@ -15,7 +15,7 @@ fn direct_alias() { type IndirectAlias = Ty>; fn indirect_alias() { - IndirectAlias::new(); + IndirectAlias::new(); //~ ERROR: type annotations needed // FIXME: This should also emit an error. // // Added it separately as `type-alias-indirect.rs` diff --git a/tests/ui/inference/need_type_info/type-alias.stderr b/tests/ui/inference/need_type_info/type-alias.stderr index a33f49baf549f..2c39a3f56466f 100644 --- a/tests/ui/inference/need_type_info/type-alias.stderr +++ b/tests/ui/inference/need_type_info/type-alias.stderr @@ -2,14 +2,20 @@ error[E0282]: type annotations needed --> $DIR/type-alias.rs:12:5 | LL | DirectAlias::new() - | ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + +error[E0282]: type annotations needed + --> $DIR/type-alias.rs:18:5 + | +LL | IndirectAlias::new(); + | ^^^^^^^^^^^^^ cannot infer type for type parameter `T` declared on the type alias `IndirectAlias` error[E0282]: type annotations needed --> $DIR/type-alias.rs:32:5 | LL | DirectButWithDefaultAlias::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/infinite/infinite-tag-type-recursion.rs b/tests/ui/infinite/infinite-tag-type-recursion.rs index 87a9e08dd381a..1b5cb55b4e4d1 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.rs +++ b/tests/ui/infinite/infinite-tag-type-recursion.rs @@ -1,4 +1,5 @@ enum MList { Cons(isize, MList), Nil } //~^ ERROR recursive type `MList` has infinite size +//~| ERROR cycle fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } diff --git a/tests/ui/infinite/infinite-tag-type-recursion.stderr b/tests/ui/infinite/infinite-tag-type-recursion.stderr index 4ca408260b84a..8745224a45e13 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.stderr +++ b/tests/ui/infinite/infinite-tag-type-recursion.stderr @@ -9,6 +9,17 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum MList { Cons(isize, Box), Nil } | ++++ + -error: aborting due to 1 previous error +error[E0391]: cycle detected when computing when `MList` needs drop + --> $DIR/infinite-tag-type-recursion.rs:1:1 + | +LL | enum MList { Cons(isize, MList), Nil } + | ^^^^^^^^^^ + | + = note: ...which immediately requires computing when `MList` needs drop again + = note: cycle used when computing whether `MList` needs drop + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs index 46e501abf6c2e..9d76fc2ad65bc 100644 --- a/tests/ui/inline-const/const-match-pat-generic.rs +++ b/tests/ui/inline-const/const-match-pat-generic.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(inline_const_pat)] // rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr index 4ffbde4101d72..15c3a876afcf7 100644 --- a/tests/ui/inline-const/const-match-pat-generic.stderr +++ b/tests/ui/inline-const/const-match-pat-generic.stderr @@ -1,11 +1,11 @@ error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:8:9 + --> $DIR/const-match-pat-generic.rs:7:9 | LL | const { V } => {}, | ^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/const-match-pat-generic.rs:20:9 + --> $DIR/const-match-pat-generic.rs:19:9 | LL | const { f(V) } => {}, | ^^^^^^^^^^^^^^ diff --git a/tests/ui/inline-const/const-match-pat-inference.rs b/tests/ui/inline-const/const-match-pat-inference.rs index d83ae6e983486..c595824833f5f 100644 --- a/tests/ui/inline-const/const-match-pat-inference.rs +++ b/tests/ui/inline-const/const-match-pat-inference.rs @@ -1,7 +1,6 @@ // check-pass #![feature(inline_const_pat)] -#![allow(incomplete_features)] fn main() { match 1u64 { diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.rs b/tests/ui/inline-const/const-match-pat-lifetime-err.rs index ce91e5233bccd..ff0a9dbf110c4 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(const_mut_refs)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr index c5760f1027ef2..98ce6cfae7b38 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr @@ -1,5 +1,5 @@ error[E0597]: `y` does not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:29:29 + --> $DIR/const-match-pat-lifetime-err.rs:28:29 | LL | fn match_invariant_ref<'a>() { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | } | - `y` dropped here while still borrowed error: lifetime may not live long enough - --> $DIR/const-match-pat-lifetime-err.rs:39:12 + --> $DIR/const-match-pat-lifetime-err.rs:38:12 | LL | fn match_covariant_ref<'a>() { | -- lifetime `'a` defined here diff --git a/tests/ui/inline-const/const-match-pat-lifetime.rs b/tests/ui/inline-const/const-match-pat-lifetime.rs index 6d943bbcc0160..595741b101e93 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime.rs +++ b/tests/ui/inline-const/const-match-pat-lifetime.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(const_mut_refs)] #![feature(inline_const)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/const-match-pat-range.rs b/tests/ui/inline-const/const-match-pat-range.rs index 73d6334c36f8e..0f9372c537f89 100644 --- a/tests/ui/inline-const/const-match-pat-range.rs +++ b/tests/ui/inline-const/const-match-pat-range.rs @@ -1,6 +1,5 @@ // build-pass -#![allow(incomplete_features)] #![feature(inline_const_pat, exclusive_range_pattern)] fn main() { diff --git a/tests/ui/inline-const/const-match-pat.rs b/tests/ui/inline-const/const-match-pat.rs index 2f55e16b35cd9..fc4d37714585e 100644 --- a/tests/ui/inline-const/const-match-pat.rs +++ b/tests/ui/inline-const/const-match-pat.rs @@ -1,6 +1,5 @@ // run-pass -#![allow(incomplete_features)] #![feature(inline_const_pat)] const MMIO_BIT1: u8 = 4; const MMIO_BIT2: u8 = 5; diff --git a/tests/ui/inline-const/pat-match-fndef.rs b/tests/ui/inline-const/pat-match-fndef.rs index fbd4dc66c3a05..013a4a6756102 100644 --- a/tests/ui/inline-const/pat-match-fndef.rs +++ b/tests/ui/inline-const/pat-match-fndef.rs @@ -1,5 +1,4 @@ #![feature(inline_const_pat)] -//~^ WARN the feature `inline_const_pat` is incomplete fn uwu() {} diff --git a/tests/ui/inline-const/pat-match-fndef.stderr b/tests/ui/inline-const/pat-match-fndef.stderr index 02c4a60b68f20..b189ec51ade38 100644 --- a/tests/ui/inline-const/pat-match-fndef.stderr +++ b/tests/ui/inline-const/pat-match-fndef.stderr @@ -1,17 +1,8 @@ -warning: the feature `inline_const_pat` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/pat-match-fndef.rs:1:12 - | -LL | #![feature(inline_const_pat)] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #76001 for more information - = note: `#[warn(incomplete_features)]` on by default - error: `fn() {uwu}` cannot be used in patterns - --> $DIR/pat-match-fndef.rs:9:9 + --> $DIR/pat-match-fndef.rs:8:9 | LL | const { uwu } => {} | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error diff --git a/tests/ui/inline-const/pat-unsafe-err.rs b/tests/ui/inline-const/pat-unsafe-err.rs index 7680c82efb5c5..b906def702950 100644 --- a/tests/ui/inline-const/pat-unsafe-err.rs +++ b/tests/ui/inline-const/pat-unsafe-err.rs @@ -1,4 +1,3 @@ -#![allow(incomplete_features)] #![feature(inline_const_pat)] const unsafe fn require_unsafe() -> usize { diff --git a/tests/ui/inline-const/pat-unsafe-err.stderr b/tests/ui/inline-const/pat-unsafe-err.stderr index 9b995d6ccf27e..786c7f31ccce1 100644 --- a/tests/ui/inline-const/pat-unsafe-err.stderr +++ b/tests/ui/inline-const/pat-unsafe-err.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block - --> $DIR/pat-unsafe-err.rs:11:13 + --> $DIR/pat-unsafe-err.rs:10:13 | LL | require_unsafe(); | ^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | require_unsafe(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block - --> $DIR/pat-unsafe-err.rs:18:13 + --> $DIR/pat-unsafe-err.rs:17:13 | LL | require_unsafe() | ^^^^^^^^^^^^^^^^ call to unsafe function diff --git a/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs index f7073ef40eb09..5a90920ef3cff 100644 --- a/tests/ui/inline-const/pat-unsafe.rs +++ b/tests/ui/inline-const/pat-unsafe.rs @@ -1,6 +1,5 @@ // check-pass -#![allow(incomplete_features)] #![warn(unused_unsafe)] #![feature(inline_const_pat)] diff --git a/tests/ui/inline-const/pat-unsafe.stderr b/tests/ui/inline-const/pat-unsafe.stderr index 84dc10c490258..59460271ac010 100644 --- a/tests/ui/inline-const/pat-unsafe.stderr +++ b/tests/ui/inline-const/pat-unsafe.stderr @@ -1,17 +1,17 @@ warning: unnecessary `unsafe` block - --> $DIR/pat-unsafe.rs:16:17 + --> $DIR/pat-unsafe.rs:15:17 | LL | unsafe {} | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/pat-unsafe.rs:4:9 + --> $DIR/pat-unsafe.rs:3:9 | LL | #![warn(unused_unsafe)] | ^^^^^^^^^^^^^ warning: unnecessary `unsafe` block - --> $DIR/pat-unsafe.rs:23:17 + --> $DIR/pat-unsafe.rs:22:17 | LL | unsafe {} | ^^^^^^ unnecessary `unsafe` block diff --git a/tests/ui/inner-static-type-parameter.stderr b/tests/ui/inner-static-type-parameter.stderr index ff6558e494b11..88d33b44c5931 100644 --- a/tests/ui/inner-static-type-parameter.stderr +++ b/tests/ui/inner-static-type-parameter.stderr @@ -5,15 +5,17 @@ LL | fn foo() { | - type parameter from outer item LL | static a: Bar = Bar::What; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/inner-static-type-parameter.rs:3:10 | LL | enum Bar { What } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr index 97e658617cf03..ad2c3af424be8 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/integral-indexing.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `u8` LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` + = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `Vec` to implement `Index` @@ -15,7 +15,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `i8` LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` + = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` = note: required for `Vec` to implement `Index` @@ -26,7 +26,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `u32` LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` + = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` = note: required for `Vec` to implement `Index` @@ -37,7 +37,7 @@ error[E0277]: the type `[isize]` cannot be indexed by `i32` LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` + = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`, which is required by `Vec: Index<_>` = help: the trait `SliceIndex<[isize]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec` to implement `Index` @@ -48,7 +48,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `u8` LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` + = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[u8]` to implement `Index` @@ -59,7 +59,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `i8` LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` + = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` = note: required for `[u8]` to implement `Index` @@ -70,7 +70,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `u32` LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` + = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` = note: required for `[u8]` to implement `Index` @@ -81,7 +81,7 @@ error[E0277]: the type `[u8]` cannot be indexed by `i32` LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` + = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`, which is required by `[u8]: Index<_>` = help: the trait `SliceIndex<[u8]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[u8]` to implement `Index` diff --git a/tests/ui/interior-mutability/interior-mutability.stderr b/tests/ui/interior-mutability/interior-mutability.stderr index 36686565e2e3a..7b08a6454052d 100644 --- a/tests/ui/interior-mutability/interior-mutability.stderr +++ b/tests/ui/interior-mutability/interior-mutability.stderr @@ -6,7 +6,7 @@ LL | catch_unwind(|| { x.set(23); }); | | | required by a bound introduced by this call | - = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `{closure@$DIR/interior-mutability.rs:5:18: 5:20}: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `&Cell` to implement `UnwindSafe` diff --git a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs index 06cf8c0f0f6d5..8ea4eac1a6173 100644 --- a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs +++ b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs @@ -26,5 +26,7 @@ fn main() { let _ = A(0); let _ = B(0); let _ = C(0); - let _ = E::X; + unsafe { + let _ = E::X; + } } diff --git a/tests/ui/issues/issue-10412.stderr b/tests/ui/issues/issue-10412.stderr index 26666782d2abc..02a26034f9aa7 100644 --- a/tests/ui/issues/issue-10412.stderr +++ b/tests/ui/issues/issue-10412.stderr @@ -58,11 +58,11 @@ LL | impl<'self> Serializable for &'self str { | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` -note: required by a bound in `Serializable` +note: required by an implicit `Sized` bound in `Serializable` --> $DIR/issue-10412.rs:1:27 | LL | trait Serializable<'self, T> { - | ^ required by this bound in `Serializable` + | ^ required by the implicit `Sized` requirement on this type parameter in `Serializable` help: consider relaxing the implicit `Sized` restriction | LL | trait Serializable<'self, T: ?Sized> { diff --git a/tests/ui/issues/issue-11374.rs b/tests/ui/issues/issue-11374.rs index 7519ba2826e7a..60ee256c65a90 100644 --- a/tests/ui/issues/issue-11374.rs +++ b/tests/ui/issues/issue-11374.rs @@ -18,6 +18,7 @@ impl<'a> Container<'a> { pub fn for_stdin<'a>() -> Container<'a> { let mut r = io::stdin(); Container::wrap(&mut r as &mut dyn io::Read) + //~^ ERROR cannot return value referencing local variable } fn main() { diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr index 275a0e6b5d775..3ae5cfc79f874 100644 --- a/tests/ui/issues/issue-11374.stderr +++ b/tests/ui/issues/issue-11374.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-11374.rs:26:15 + --> $DIR/issue-11374.rs:27:15 | LL | c.read_to(v); | ------- ^ expected `&mut [u8]`, found `Vec<_>` @@ -18,6 +18,16 @@ help: consider mutably borrowing here LL | c.read_to(&mut v); | ++++ -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing local variable `r` + --> $DIR/issue-11374.rs:20:5 + | +LL | Container::wrap(&mut r as &mut dyn io::Read) + | ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `r` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0515. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13497.rs b/tests/ui/issues/issue-13497.rs index 4b2795aa841e8..7f786a54b9f71 100644 --- a/tests/ui/issues/issue-13497.rs +++ b/tests/ui/issues/issue-13497.rs @@ -3,6 +3,7 @@ fn read_lines_borrowed1() -> Vec< > { let rawLines: Vec = vec!["foo ".to_string(), " bar".to_string()]; rawLines.iter().map(|l| l.trim()).collect() + //~^ ERROR: cannot return value referencing } fn main() {} diff --git a/tests/ui/issues/issue-13497.stderr b/tests/ui/issues/issue-13497.stderr index fb3de637a7985..7630848f6a512 100644 --- a/tests/ui/issues/issue-13497.stderr +++ b/tests/ui/issues/issue-13497.stderr @@ -14,6 +14,16 @@ help: instead, you are more likely to want to return an owned value LL | String | ~~~~~~ -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing local variable `rawLines` + --> $DIR/issue-13497.rs:5:5 + | +LL | rawLines.iter().map(|l| l.trim()).collect() + | --------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `rawLines` is borrowed here + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0515. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-14399.rs b/tests/ui/issues/issue-14399.rs index 7b32bf8e4cbb7..0c6c4d8dc6bd3 100644 --- a/tests/ui/issues/issue-14399.rs +++ b/tests/ui/issues/issue-14399.rs @@ -9,7 +9,7 @@ #[derive(Clone)] struct B1; -trait A { fn foo(&self) {} } +trait A { fn foo(&self) {} } //~ WARN method `foo` is never used impl A for B1 {} fn main() { diff --git a/tests/ui/issues/issue-14399.stderr b/tests/ui/issues/issue-14399.stderr new file mode 100644 index 0000000000000..d226ece6fb0b6 --- /dev/null +++ b/tests/ui/issues/issue-14399.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/issue-14399.rs:12:14 + | +LL | trait A { fn foo(&self) {} } + | - ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/issues/issue-15858.rs index 77941c07671d6..e3e3c293d7a74 100644 --- a/tests/ui/issues/issue-15858.rs +++ b/tests/ui/issues/issue-15858.rs @@ -2,7 +2,7 @@ static mut DROP_RAN: bool = false; trait Bar { - fn do_something(&mut self); + fn do_something(&mut self); //~ WARN method `do_something` is never used } struct BarImpl; diff --git a/tests/ui/issues/issue-15858.stderr b/tests/ui/issues/issue-15858.stderr new file mode 100644 index 0000000000000..f36bcc21bd7fb --- /dev/null +++ b/tests/ui/issues/issue-15858.stderr @@ -0,0 +1,12 @@ +warning: method `do_something` is never used + --> $DIR/issue-15858.rs:5:8 + | +LL | trait Bar { + | --- method in this trait +LL | fn do_something(&mut self); + | ^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-17351.rs b/tests/ui/issues/issue-17351.rs index 62f6bcf15e3e7..12bb8a73b7bd4 100644 --- a/tests/ui/issues/issue-17351.rs +++ b/tests/ui/issues/issue-17351.rs @@ -1,7 +1,7 @@ // run-pass // pretty-expanded FIXME #23616 -trait Str { fn foo(&self) {} } +trait Str { fn foo(&self) {} } //~ WARN method `foo` is never used impl Str for str {} impl<'a, S: ?Sized> Str for &'a S where S: Str {} diff --git a/tests/ui/issues/issue-17351.stderr b/tests/ui/issues/issue-17351.stderr new file mode 100644 index 0000000000000..3242d578dabce --- /dev/null +++ b/tests/ui/issues/issue-17351.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/issue-17351.rs:4:16 + | +LL | trait Str { fn foo(&self) {} } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-17904-2.stderr b/tests/ui/issues/issue-17904-2.stderr index 102c8537f8e04..9965106d1401a 100644 --- a/tests/ui/issues/issue-17904-2.stderr +++ b/tests/ui/issues/issue-17904-2.stderr @@ -1,8 +1,8 @@ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-17904-2.rs:4:12 | LL | struct Foo where T: Copy; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/issues/issue-17994.rs b/tests/ui/issues/issue-17994.rs index 39b0a7ebe74d8..ab37a172eaa74 100644 --- a/tests/ui/issues/issue-17994.rs +++ b/tests/ui/issues/issue-17994.rs @@ -1,3 +1,3 @@ trait Tr {} -type Huh where T: Tr = isize; //~ ERROR type parameter `T` is unused +type Huh where T: Tr = isize; //~ ERROR type parameter `T` is never used fn main() {} diff --git a/tests/ui/issues/issue-17994.stderr b/tests/ui/issues/issue-17994.stderr index ba3def64dfb5d..f149e5d08faac 100644 --- a/tests/ui/issues/issue-17994.stderr +++ b/tests/ui/issues/issue-17994.stderr @@ -1,8 +1,10 @@ -error[E0091]: type parameter `T` is unused +error[E0091]: type parameter `T` is never used --> $DIR/issue-17994.rs:2:10 | LL | type Huh where T: Tr = isize; | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-18173.rs b/tests/ui/issues/issue-18173.rs index 11468040ee530..010efee9f8ab6 100644 --- a/tests/ui/issues/issue-18173.rs +++ b/tests/ui/issues/issue-18173.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass trait Foo { type T; } diff --git a/tests/ui/issues/issue-18919.stderr b/tests/ui/issues/issue-18919.stderr index 6dcd891cedac9..714b6d7d86be3 100644 --- a/tests/ui/issues/issue-18919.stderr +++ b/tests/ui/issues/issue-18919.stderr @@ -5,11 +5,11 @@ LL | fn ho_func(f: Option) { | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn for<'a> Fn(&'a isize) -> isize` -note: required by a bound in `Option` +note: required by an implicit `Sized` bound in `Option` --> $DIR/issue-18919.rs:7:13 | LL | enum Option { - | ^ required by this bound in `Option` + | ^ required by the implicit `Sized` requirement on this type parameter in `Option` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-18919.rs:7:13 | diff --git a/tests/ui/issues/issue-20055-box-trait.rs b/tests/ui/issues/issue-20055-box-trait.rs index 772cd9d7eda82..36f597450adb8 100644 --- a/tests/ui/issues/issue-20055-box-trait.rs +++ b/tests/ui/issues/issue-20055-box-trait.rs @@ -8,7 +8,7 @@ // statement surrounding the `match`. trait Boo { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } impl Boo for [i8; 1] { } diff --git a/tests/ui/issues/issue-20055-box-trait.stderr b/tests/ui/issues/issue-20055-box-trait.stderr new file mode 100644 index 0000000000000..db9d359e2252c --- /dev/null +++ b/tests/ui/issues/issue-20055-box-trait.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-20055-box-trait.rs:11:8 + | +LL | trait Boo { + | --- method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-20413.stderr b/tests/ui/issues/issue-20413.stderr index 8793029dd224a..5d442eb989851 100644 --- a/tests/ui/issues/issue-20413.stderr +++ b/tests/ui/issues/issue-20413.stderr @@ -1,11 +1,11 @@ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-20413.rs:6:15 | LL | struct NoData; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error[E0275]: overflow evaluating the requirement `NoData>>>>>>: Foo` --> $DIR/issue-20413.rs:9:36 diff --git a/tests/ui/issues/issue-20433.stderr b/tests/ui/issues/issue-20433.stderr index 2dd0b3c2f8439..3730a67cc7959 100644 --- a/tests/ui/issues/issue-20433.stderr +++ b/tests/ui/issues/issue-20433.stderr @@ -5,7 +5,7 @@ LL | fn iceman(c: Vec<[i32]>) {} | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-21763.stderr b/tests/ui/issues/issue-21763.stderr index 135b705eeeff2..aa4938a0c0b3a 100644 --- a/tests/ui/issues/issue-21763.stderr +++ b/tests/ui/issues/issue-21763.stderr @@ -4,7 +4,7 @@ error[E0277]: `Rc<()>` cannot be sent between threads safely LL | foo::, Rc<()>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely | - = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>` + = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>`, which is required by `HashMap, Rc<()>>: Send` = 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<()>, RandomState>` diff --git a/tests/ui/issues/issue-21909.rs b/tests/ui/issues/issue-21909.rs index 7cb558d9a4fa6..6a6cdcfee159d 100644 --- a/tests/ui/issues/issue-21909.rs +++ b/tests/ui/issues/issue-21909.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait A { diff --git a/tests/ui/issues/issue-22872.stderr b/tests/ui/issues/issue-22872.stderr index 6ff710b113325..03e5393da4882 100644 --- a/tests/ui/issues/issue-22872.stderr +++ b/tests/ui/issues/issue-22872.stderr @@ -4,7 +4,7 @@ error[E0277]: `

>::Item` is not an iterator LL | let _: Box Wrap<'b>> = Box::new(Wrapper(process)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `

>::Item` is not an iterator | - = help: the trait `Iterator` is not implemented for `

>::Item` + = help: the trait `Iterator` is not implemented for `

>::Item`, which is required by `for<'b> Wrapper

: Wrap<'b>` note: required for `Wrapper

` (where P is one of the previous types except `Self`) + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0038, E0307, E0378, E0412, E0658. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs index ac8bda9c01042..75483a810949d 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.rs +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -8,11 +8,9 @@ use core::marker::PhantomData; fn main() { test::>>(make()); //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) test::>>(make()); //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - //~| ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) } #[rustc_evaluate_where_clauses] diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr index 9590ea12c05e4..d2b00a45a4f15 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr @@ -1,12 +1,3 @@ -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 - | -LL | test::>>(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn test(_: T) {} - | - predicate - error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 | @@ -17,16 +8,7 @@ LL | fn test(_: T) {} | ----- predicate error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 - | -LL | test::>>(make()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | fn test(_: T) {} - | - predicate - -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - --> $DIR/issue-85360-eval-obligation-ice.rs:13:5 + --> $DIR/issue-85360-eval-obligation-ice.rs:12:5 | LL | test::>>(make()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,5 +16,5 @@ LL | test::>>(make()); LL | fn test(_: T) {} | ----- predicate -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-91594.stderr b/tests/ui/traits/issue-91594.stderr index 13568179e81f4..726ee5b61461b 100644 --- a/tests/ui/traits/issue-91594.stderr +++ b/tests/ui/traits/issue-91594.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied --> $DIR/issue-91594.rs:10:19 | LL | impl HasComponent<>::Interface> for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`, which is required by `Foo: Component` | = help: the trait `HasComponent<>::Interface>` is implemented for `Foo` note: required for `Foo` to implement `Component` diff --git a/tests/ui/traits/issue-97576.stderr b/tests/ui/traits/issue-97576.stderr index 2c6cfd83b9571..bee254461f1bd 100644 --- a/tests/ui/traits/issue-97576.stderr +++ b/tests/ui/traits/issue-97576.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `String: From` is not satisfied --> $DIR/issue-97576.rs:8:22 | LL | bar: bar.into(), - | ^^^^ the trait `From` is not implemented for `String` + | ^^^^ the trait `From` is not implemented for `String`, which is required by `impl ToString: Into<_>` | = note: required for `impl ToString` to implement `Into` diff --git a/tests/ui/traits/method-on-unbounded-type-param.rs b/tests/ui/traits/method-on-unbounded-type-param.rs new file mode 100644 index 0000000000000..8505eb41e98bb --- /dev/null +++ b/tests/ui/traits/method-on-unbounded-type-param.rs @@ -0,0 +1,15 @@ +fn f(a: T, b: T) -> std::cmp::Ordering { + a.cmp(&b) //~ ERROR E0599 +} +fn g(a: T, b: T) -> std::cmp::Ordering { + (&a).cmp(&b) //~ ERROR E0599 +} +fn h(a: &T, b: T) -> std::cmp::Ordering { + a.cmp(&b) //~ ERROR E0599 +} +trait T {} +impl T for X {} +fn main() { + let x: Box = Box::new(0); + x.cmp(&x); //~ ERROR E0599 +} diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr new file mode 100644 index 0000000000000..0d8bd8ee964e7 --- /dev/null +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -0,0 +1,84 @@ +error[E0599]: no method named `cmp` found for type parameter `T` in the current scope + --> $DIR/method-on-unbounded-type-param.rs:2:7 + | +LL | fn f(a: T, b: T) -> std::cmp::Ordering { + | - method `cmp` not found for this type parameter +LL | a.cmp(&b) + | ^^^ method cannot be called on `T` due to unsatisfied trait bounds + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: + | +LL | fn f(a: T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn f(a: T, b: T) -> std::cmp::Ordering { + | ++++++++++ + +error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:5:10 + | +LL | (&a).cmp(&b) + | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Ord` + which is required by `&T: Ord` + `&T: Iterator` + which is required by `&mut &T: Iterator` + `T: Iterator` + which is required by `&mut T: Iterator` + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: + | +LL | fn g(a: T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn g(a: T, b: T) -> std::cmp::Ordering { + | ++++++++++ + +error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:8:7 + | +LL | a.cmp(&b) + | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Ord` + which is required by `&T: Ord` + `&T: Iterator` + which is required by `&mut &T: Iterator` + `T: Iterator` + which is required by `&mut T: Iterator` + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: + | +LL | fn h(a: &T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn h(a: &T, b: T) -> std::cmp::Ordering { + | ++++++++++ + +error[E0599]: the method `cmp` exists for struct `Box`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:14:7 + | +LL | trait T {} + | ------- doesn't satisfy `dyn T: Iterator` or `dyn T: Ord` +... +LL | x.cmp(&x); + | ^^^ method cannot be called on `Box` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `dyn T: Iterator` + which is required by `Box: Iterator` + `dyn T: Ord` + which is required by `Box: Ord` + `Box: Iterator` + which is required by `&mut Box: Iterator` + `dyn T: Iterator` + which is required by `&mut dyn T: Iterator` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `cmp`, perhaps you need to implement one of them: + candidate #1: `Ord` + candidate #2: `Iterator` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs index f845e198aa574..e9ae8ab012a09 100644 --- a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs @@ -6,7 +6,7 @@ use std::cell::RefCell; -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn foo(&self) {} } diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr b/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr new file mode 100644 index 0000000000000..25313a477f7af --- /dev/null +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/multidispatch-conditional-impl-not-considered.rs:9:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/multidispatch-infer-convert-target.rs b/tests/ui/traits/multidispatch-infer-convert-target.rs index 626e1ae71bc2f..a3653dea2cbdf 100644 --- a/tests/ui/traits/multidispatch-infer-convert-target.rs +++ b/tests/ui/traits/multidispatch-infer-convert-target.rs @@ -5,7 +5,7 @@ use std::mem; trait Convert { - fn convert(&self) -> Target; + fn convert(&self) -> Target; //~ WARN method `convert` is never used } impl Convert for i16 { diff --git a/tests/ui/traits/multidispatch-infer-convert-target.stderr b/tests/ui/traits/multidispatch-infer-convert-target.stderr new file mode 100644 index 0000000000000..c8c1b64271950 --- /dev/null +++ b/tests/ui/traits/multidispatch-infer-convert-target.stderr @@ -0,0 +1,12 @@ +warning: method `convert` is never used + --> $DIR/multidispatch-infer-convert-target.rs:8:8 + | +LL | trait Convert { + | ------- method in this trait +LL | fn convert(&self) -> Target; + | ^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/mutual-recursion-issue-75860.stderr b/tests/ui/traits/mutual-recursion-issue-75860.stderr index 420ed2dcd2f09..8f83bab003db3 100644 --- a/tests/ui/traits/mutual-recursion-issue-75860.stderr +++ b/tests/ui/traits/mutual-recursion-issue-75860.stderr @@ -5,7 +5,7 @@ LL | iso(left, right) | ^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mutual_recursion_issue_75860`) -note: required by a bound in `Option` +note: required by an implicit `Sized` bound in `Option` --> $SRC_DIR/core/src/option.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr index 8f5b937e586ae..2a3833beb26b3 100644 --- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -49,7 +49,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` + = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`, which is required by `({integer}, dummy1c::TestType): Send` = note: required because it appears within the type `({integer}, dummy1c::TestType)` note: required by a bound in `is_send` --> $DIR/negated-auto-traits-error.rs:16:15 @@ -87,7 +87,7 @@ LL | is_send(Box::new(Outer2(TestType))); | | | required by a bound introduced by this call | - = help: within `Outer2`, the trait `Send` is not implemented for `dummy3::TestType` + = help: within `Outer2`, the trait `Send` is not implemented for `dummy3::TestType`, which is required by `Box>: Send` note: required because it appears within the type `Outer2` --> $DIR/negated-auto-traits-error.rs:12:8 | @@ -110,7 +110,7 @@ LL | is_sync(Outer2(TestType)); | | | required by a bound introduced by this call | - = help: the trait `Send` is not implemented for `main::TestType` + = help: the trait `Send` is not implemented for `main::TestType`, which is required by `Outer2: Sync` note: required for `Outer2` to implement `Sync` --> $DIR/negated-auto-traits-error.rs:14:22 | diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs index 35297ab124ed0..01829e4130115 100644 --- a/tests/ui/traits/negative-impls/negative-specializes-negative.rs +++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs @@ -3,7 +3,7 @@ // Test a negative impl that "specializes" another negative impl. // -// run-pass +// check-pass trait MyTrait {} diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs index 633f0e75572c7..a520bf6c25b04 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs @@ -22,8 +22,7 @@ impl Foo for () { fn main() { let x = String::from("hello, world"); drop(<() as Foo>::copy_me(&x)); - //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized` - //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` + //~^ ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr index d5f7e975b1371..2408e05728a84 100644 --- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr @@ -29,15 +29,6 @@ LL | drop(<() as Foo>::copy_me(&x)); | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item: Sized` - --> $DIR/alias-bound-unsound.rs:24:10 - | -LL | drop(<() as Foo>::copy_me(&x)); - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) - = note: the return type of a function must have a statically known size - error[E0275]: overflow evaluating the requirement `&<() as Foo>::Item well-formed` --> $DIR/alias-bound-unsound.rs:24:31 | @@ -63,6 +54,6 @@ LL | drop(<() as Foo>::copy_me(&x)); = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs index af471b5e19345..d7a2c8e7a928e 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs @@ -8,6 +8,7 @@ trait Overflow { } impl Overflow for T { type Assoc = ::Assoc; + //~^ ERROR: overflow } diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index e3c0dabf549e8..583945723d5f0 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `::Assoc` - --> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1 + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1 | LL | impl Trait for T {} | ------------------------- first implementation here @@ -7,6 +7,24 @@ LL | struct LocalTy; LL | impl Trait for ::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `::Assoc` -error: aborting due to 1 previous error +error[E0275]: overflow evaluating the requirement `::Assoc: Sized` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18 + | +LL | type Assoc = ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) +note: required by a bound in `Overflow::Assoc` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:7:5 + | +LL | type Assoc; + | ^^^^^^^^^^^ required by this bound in `Overflow::Assoc` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assoc: ?Sized; + | ++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0275. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs index c7e2e2d5e040b..f6c75317a34e4 100644 --- a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs +++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs @@ -24,6 +24,18 @@ where { } +// HACK: This impls is necessary so that the impl above is well-formed. +// +// When checking that the impl above is well-formed we check `B: Trait<'a, 'b>` +// with the where clauses `A: Trait<'a, 'b>` and `A NotImplemented`. Trying to +// use the impl itself to prove that adds region constraints as we uniquified the +// regions in the `A: Trait<'a, 'b>` where-bound. As both the impl above +// and the impl below now apply with some constraints, we failed with ambiguity. +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for B +where + A: NotImplemented, +{} + // This impl directly requires 'b to be equal to 'static. // // Because of the coinductive cycle through `C` it also requires diff --git a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr index 7b3075f4ff35a..0cbd96540448c 100644 --- a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr +++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/fixpoint-rerun-all-cycle-heads.rs:47:5 + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:59:5 | LL | fn check<'a, T: ?Sized>() { | -- lifetime `'a` defined here diff --git a/tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs b/tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs new file mode 100644 index 0000000000000..37730d38c7a64 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs @@ -0,0 +1,40 @@ +// compile-flags: -Znext-solver +// check-pass + +// If a trait goal is proven using the environment, we discard +// impl candidates when normalizing. However, in this example +// the env candidates start as ambiguous and end up not applying, +// so normalization should succeed later on. + +trait Trait: Sized { + type Assoc: From; +} + +impl Trait for T { + type Assoc = T; +} + +fn mk_assoc, U>(t: T, _: U) -> >::Assoc { + t.into() +} + +fn generic(t: T) -> T +where + T: Trait, + T: Trait, +{ + let u = Default::default(); + + // at this point we have 2 ambig env candidates + let ret: T = mk_assoc(t, u); + + // now both env candidates don't apply, so we're now able to + // normalize using this impl candidates. For this to work + // the normalizes-to must have remained ambiguous above. + let _: u8 = u; + ret +} + +fn main() { + assert_eq!(generic(1), 1); +} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-1.rs b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-1.rs new file mode 100644 index 0000000000000..63742d0d1a1e8 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-1.rs @@ -0,0 +1,30 @@ +// compile-flags: -Znext-solver +// check-pass + +// Normalizing `::TraitAssoc` in the elaborated environment +// `[T: Trait, T: Super, ::SuperAssoc = ::TraitAssoc]` +// has a single impl candidate, which uses the environment to +// normalize `::TraitAssoc` to itself. We avoid this overflow +// by discarding impl candidates the trait bound is proven by a where-clause. + +// https://github.com/rust-lang/trait-system-refactor-initiative/issues/76 +trait Super { + type SuperAssoc; +} + +trait Trait: Super { + type TraitAssoc; +} + +impl Trait for T +where + T: Super, +{ + type TraitAssoc = U; +} + +fn overflow() { + let x: ::TraitAssoc; +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs new file mode 100644 index 0000000000000..b0ef0d44baf80 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs @@ -0,0 +1,29 @@ +// revisions: next current +//[next] compile-flags: -Znext-solver +// check-pass + +#![allow(warnings)] +trait Trait { + type Assoc; +} + +impl Trait for T { + type Assoc = T; +} + +fn lazy_init, U>() -> (T, >::Assoc) { + todo!() +} + +fn foo>(x: T) { + // When considering impl candidates to be equally valid as env candidates + // this ends up being ambiguous as `U` can be both `u32´ and `u64` here. + // + // This is acceptable breakage but we should still note that it's + // theoretically breaking. + let (delayed, mut proj) = lazy_init::<_, _>(); + proj = x; + let _: T = delayed; +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-3.rs b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-3.rs new file mode 100644 index 0000000000000..807e19a4a5869 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-3.rs @@ -0,0 +1,18 @@ +// compile-flags: -Znext-solver +// check-pass + +// If we normalize using the impl here the constraints from normalization and +// trait goals can differ. This is especially bad if normalization results +// in stronger constraints. +trait Trait<'a> { + type Assoc; +} + +impl Trait<'static> for T { + type Assoc = (); +} + +// normalizing requires `'a == 'static`, the trait bound does not. +fn foo<'a, T: Trait<'a>>(_: T::Assoc) {} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.rs b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.rs new file mode 100644 index 0000000000000..af2c44ea23398 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.rs @@ -0,0 +1,29 @@ +// compile-flags: -Znext-solver + +// Checks whether the new solver is smart enough to infer `?0 = U` when solving: +// `normalizes-to( as Trait>::Assoc, u8)` +// with `normalizes-to( as Trait>::Assoc, u8)` in the paramenv even when +// there is a separate `Vec: Trait` bound in the paramenv. +// +// We currently intentionally do not guide inference this way. + +trait Trait { + type Assoc; +} + +fn foo>(x: T) {} + +fn unconstrained() -> Vec { + todo!() +} + +fn bar() +where + Vec: Trait, + Vec: Trait, +{ + foo(unconstrained()) + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.stderr similarity index 70% rename from tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr rename to tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.stderr index c1a8b74df0824..36d281e11dd7a 100644 --- a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr +++ b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.stderr @@ -1,21 +1,21 @@ error[E0283]: type annotations needed - --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:36:5 + --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:25:5 | LL | foo(unconstrained()) | ^^^ --------------- type must be known at this point | | | cannot infer type of the type parameter `T` declared on the function `foo` | - = note: cannot satisfy `_: Trait` + = note: cannot satisfy `Vec<_>: Trait` note: required by a bound in `foo` - --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:19:11 + --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:14:11 | LL | fn foo>(x: T) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` help: consider specifying the generic argument | -LL | foo::(unconstrained()) - | +++++ +LL | foo::>(unconstrained()) + | ++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs new file mode 100644 index 0000000000000..5989e605bd9aa --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs @@ -0,0 +1,31 @@ +// compile-flags: -Znext-solver + +trait Foo { + type Assoc; +} + +trait Bar {} + +impl Foo for T { + type Assoc = i32; +} + +impl Bar for T where T: Foo {} + +fn require_bar() {} + +fn foo() { + // Unlike the classic solver, the new solver previously projected + // `::Assoc = _` down to `i32` even though there's a param-env + // candidate here, since we don't assemble any param-env projection + // candidates for `T: Foo` alone. + // + // However, allowing impl candidates shadowed by env candidates results + // in multiple issues, so we explicitly hide them, e.g. + // + // https://github.com/rust-lang/trait-system-refactor-initiative/issues/76 + require_bar::(); + //~^ ERROR the trait bound `T: Bar` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr new file mode 100644 index 0000000000000..2785357e792de --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/param-candidate-shadows-project.rs:27:19 + | +LL | require_bar::(); + | ^ the trait `Bar` is not implemented for `T` + | +note: required by a bound in `require_bar` + --> $DIR/param-candidate-shadows-project.rs:15:19 + | +LL | fn require_bar() {} + | ^^^ required by this bound in `require_bar` +help: consider further restricting this bound + | +LL | fn foo() { + | +++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr index ad8b24a39c701..aaadf604a80ac 100644 --- a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr +++ b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr @@ -1,11 +1,9 @@ -error[E0275]: overflow evaluating the requirement `<>::Id as Unnormalizable>::Assoc == _` +error[E0284]: type annotations needed: cannot satisfy `<>::Id as Unnormalizable>::Assoc == _` --> $DIR/occurs-check-nested-alias.rs:36:9 | LL | x = y; - | ^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`occurs_check_nested_alias`) + | ^ cannot satisfy `<>::Id as Unnormalizable>::Assoc == _` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index 10fb7d525b7a1..c50276c78b4f8 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -12,6 +12,7 @@ trait ToUnit<'a> { trait Overlap {} type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; +//~^ ERROR: not well-formed impl Overlap for T {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index c16a48d5f154c..f4638348358fc 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Missing` in this scope - --> $DIR/issue-118950-root-region.rs:18:55 + --> $DIR/issue-118950-root-region.rs:19:55 | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^^^^^^^ not found in this scope @@ -22,7 +22,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) error[E0119]: conflicting implementations of trait `Overlap` for type `fn(_)` - --> $DIR/issue-118950-root-region.rs:18:1 + --> $DIR/issue-118950-root-region.rs:19:1 | LL | impl Overlap for T {} | ------------------------ first implementation here @@ -30,7 +30,13 @@ LL | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` -error: aborting due to 2 previous errors; 1 warning emitted +error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed + --> $DIR/issue-118950-root-region.rs:14:21 + | +LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted Some errors have detailed explanations: E0119, E0412. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index e3be2931e1232..1b776d7198ea4 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `dyn Trait: Trait` is not satisfied --> $DIR/more-object-bound.rs:12:5 | LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Trait` | note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.rs b/tests/ui/traits/next-solver/normalize-param-env-2.rs index ce084651bfb6e..9da1f8dbec1de 100644 --- a/tests/ui/traits/next-solver/normalize-param-env-2.rs +++ b/tests/ui/traits/next-solver/normalize-param-env-2.rs @@ -1,24 +1,29 @@ -// check-pass // compile-flags: -Znext-solver -// Issue 92505 +// known-bug: #92505 +// When checking that the impl method where-bounds are implied by the trait, +// we prove `<() as A>::Assoc: A` in the environment `<() as A>::Assoc: A`. +// +// Normalizing `<() as A>::Assoc` is ambiguous in that environment. The +// where-bound `<() as A>::Assoc: A` may apply, resulting in overflow. trait A { - type I; + type Assoc; fn f() where - Self::I: A, + Self::Assoc: A, { } } impl A for () { - type I = (); + type Assoc = (); fn f() where - Self::I: A, + Self::Assoc: A, { + <() as A>::f(); } } diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize-param-env-2.stderr new file mode 100644 index 0000000000000..a52022e539eb7 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-param-env-2.stderr @@ -0,0 +1,35 @@ +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A, + | ^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_2`) +note: the requirement `<() as A>::Assoc: A` appears on the `impl`'s method `f` but not on the corresponding trait's method + --> $DIR/normalize-param-env-2.rs:12:8 + | +LL | trait A { + | - in this trait +... +LL | fn f() + | ^ this trait's method doesn't have the requirement `<() as A>::Assoc: A` + +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A, + | ^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_2`) + +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc well-formed` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A, + | ^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_2`) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr new file mode 100644 index 0000000000000..dec820c61b06d --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr @@ -0,0 +1,19 @@ +error[E0275]: overflow evaluating the requirement `::Assoc: Trait` + --> $DIR/normalize-param-env-4.rs:18:26 + | +LL | ::Assoc: Trait, + | ^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_4`) + +error[E0275]: overflow evaluating the requirement `::Assoc well-formed` + --> $DIR/normalize-param-env-4.rs:18:26 + | +LL | ::Assoc: Trait, + | ^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_4`) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.rs b/tests/ui/traits/next-solver/normalize-param-env-4.rs new file mode 100644 index 0000000000000..d49f74922971f --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-param-env-4.rs @@ -0,0 +1,34 @@ +// revisions: current next +//[next] compile-flags: -Znext-solver +//[next] known-bug: #92505 +//[current] check-pass + +trait Trait { + type Assoc; +} + +impl Trait for T { + type Assoc = T; +} + +fn impls_trait() {} + +fn foo() +where + ::Assoc: Trait, +{ + // Trying to use `::Assoc: Trait` to prove `T: Trait` + // requires normalizing `::Assoc`. We do not normalize + // using impl candidates if there's a where-bound for that trait. + // + // We therefore check whether `T: Trait` is proven by the environment. + // For that we try to apply the `::Assoc: Trait` candidate, + // trying to normalize its self type results in overflow. + // + // In the old solver we eagerly normalize the environment, ignoring the + // unnormalized `::Assoc: Trait` where-bound when normalizing + // `::Asosc` + impls_trait::(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize-region-obligations.rs new file mode 100644 index 0000000000000..d189e4893a320 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-region-obligations.rs @@ -0,0 +1,29 @@ +// revisions: normalize_param_env normalize_obligation hrtb +// check-pass +// compile-flags: -Znext-solver + +trait Foo { + #[cfg(normalize_param_env)] + type Gat<'a> where ::Assoc: 'a; + #[cfg(normalize_obligation)] + type Gat<'a> where Self: 'a; + #[cfg(hrtb)] + type Gat<'b> where for<'a> >::Assoc: 'b; +} + +trait Mirror { type Assoc: ?Sized; } +impl Mirror for T { type Assoc = T; } + +trait MirrorRegion<'a> { type Assoc: ?Sized; } +impl<'a, T> MirrorRegion<'a> for T { type Assoc = T; } + +impl Foo for T { + #[cfg(normalize_param_env)] + type Gat<'a> = i32 where T: 'a; + #[cfg(normalize_obligation)] + type Gat<'a> = i32 where ::Assoc: 'a; + #[cfg(hrtb)] + type Gat<'b> = i32 where Self: 'b; +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs b/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs new file mode 100644 index 0000000000000..7477c56cd5487 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs @@ -0,0 +1,18 @@ +// check-pass +// compile-flags: -Znext-solver + +trait Mirror { + type Assoc; +} + +impl Mirror for T { + type Assoc = T; +} + +fn is_static() {} + +fn test() where ::Assoc: 'static { + is_static::(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-type-outlives.rs b/tests/ui/traits/next-solver/normalize-type-outlives.rs new file mode 100644 index 0000000000000..f50eb6326e239 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-type-outlives.rs @@ -0,0 +1,13 @@ +// check-pass + +trait Tr<'a> { + type Assoc; +} + +fn outlives<'o, T: 'o>() {} + +fn foo<'a, 'b, T: Tr<'a, Assoc = ()>>() { + outlives::<'b, T::Assoc>(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs b/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs deleted file mode 100644 index 7dc87daccd98b..0000000000000 --- a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs +++ /dev/null @@ -1,40 +0,0 @@ -// [no_self_infer] check-pass -// compile-flags: -Znext-solver -// revisions: self_infer no_self_infer - -// checks that the new solver is smart enough to infer `?0 = U` when solving: -// `normalizes-to( as Trait>::Assoc, u8)` -// with `normalizes-to( as Trait>::Assoc, u8)` in the paramenv even when -// there is a separate `Vec: Trait` bound in the paramenv. -// -// FIXME(-Znext-solver) -// This could also compile for `normalizes-to(::Assoc, u8)` but -// we currently immediately consider a goal ambiguous if the self type is an -// inference variable. - -trait Trait { - type Assoc; -} - -fn foo>(x: T) {} - -#[cfg(self_infer)] -fn unconstrained() -> T { - todo!() -} - -#[cfg(no_self_infer)] -fn unconstrained() -> Vec { - todo!() -} - -fn bar() -where - Vec: Trait, - Vec: Trait, -{ - foo(unconstrained()) - //[self_infer]~^ ERROR type annotations needed -} - -fn main() {} diff --git a/tests/ui/traits/next-solver/object-unsafety.stderr b/tests/ui/traits/next-solver/object-unsafety.stderr index ee38c256e5f64..eedca879b0c8a 100644 --- a/tests/ui/traits/next-solver/object-unsafety.stderr +++ b/tests/ui/traits/next-solver/object-unsafety.stderr @@ -46,10 +46,7 @@ error[E0277]: the size for values of type ` as Setup>::From` --> $DIR/object-unsafety.rs:12:5 | LL | copy::>(t) - | ^^^^^^^^^^^^^^^^^^^^^^^^^--- - | | - | doesn't have a size known at compile-time - | this returned value is of type ` as Setup>::From` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for ` as Setup>::From` = note: the return type of a function must have a statically known size diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index ed87404d57395..09622bb9b6c28 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -26,11 +26,11 @@ LL | needs_bar::(); | ^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`) -note: required by a bound in `needs_bar` +note: required by an implicit `Sized` bound in `needs_bar` --> $DIR/recursive-self-normalization-2.rs:12:14 | LL | fn needs_bar() {} - | ^ required by this bound in `needs_bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar` help: consider relaxing the implicit `Sized` restriction | LL | fn needs_bar() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr index e4ef2f60740f4..7c058909df7c5 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr @@ -26,11 +26,11 @@ LL | needs_bar::(); | ^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`) -note: required by a bound in `needs_bar` +note: required by an implicit `Sized` bound in `needs_bar` --> $DIR/recursive-self-normalization.rs:8:14 | LL | fn needs_bar() {} - | ^ required by this bound in `needs_bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar` help: consider relaxing the implicit `Sized` restriction | LL | fn needs_bar() {} diff --git a/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs b/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs deleted file mode 100644 index f67b073c53c5c..0000000000000 --- a/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs +++ /dev/null @@ -1,25 +0,0 @@ -// compile-flags: -Znext-solver -// check-pass - -trait Foo { - type Assoc; -} - -trait Bar {} - -impl Foo for T { - type Assoc = i32; -} - -impl Bar for T where T: Foo {} - -fn require_bar() {} - -fn foo() { - // Unlike the classic solver, `::Assoc = _` will still project - // down to `i32` even though there's a param-env candidate here, since we - // don't assemble any param-env projection candidates for `T: Foo` alone. - require_bar::(); -} - -fn main() {} diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index ff25656a7ff59..d96936f60f7a9 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -1,4 +1,5 @@ // compile-flags: -Znext-solver +//~^ ERROR cannot normalize `::Id: '_` #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete @@ -13,6 +14,7 @@ impl Default for T { default type Id = T; //~ ERROR type annotations needed // This will be fixed by #111994 fn intu(&self) -> &Self::Id { + //~^ ERROR type annotations needed self } } diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index a5459165587ca..ea1ae387f56a6 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -1,5 +1,5 @@ warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-transmute.rs:3:12 + --> $DIR/specialization-transmute.rs:4:12 | LL | #![feature(specialization)] | ^^^^^^^^^^^^^^ @@ -8,12 +8,21 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default +error: cannot normalize `::Id: '_` + +error[E0284]: type annotations needed: cannot satisfy `::Id == _` + --> $DIR/specialization-transmute.rs:16:23 + | +LL | fn intu(&self) -> &Self::Id { + | ^^^^^^^^^ cannot satisfy `::Id == _` + error[E0282]: type annotations needed - --> $DIR/specialization-transmute.rs:13:23 + --> $DIR/specialization-transmute.rs:14:23 | LL | default type Id = T; | ^ cannot infer type for associated type `::Id` -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 3 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0282`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/next-solver/specialization-unconstrained.stderr b/tests/ui/traits/next-solver/specialization-unconstrained.stderr index ed4dafa1484c2..68232aacc0c5f 100644 --- a/tests/ui/traits/next-solver/specialization-unconstrained.stderr +++ b/tests/ui/traits/next-solver/specialization-unconstrained.stderr @@ -12,7 +12,7 @@ error[E0284]: type annotations needed: cannot satisfy `::Id == ( --> $DIR/specialization-unconstrained.rs:20:5 | LL | test::(); - | ^^^^^^^^^^^^^^^ cannot satisfy `::Id == ()` + | ^^^^^^^^^^^^^^^^^ cannot satisfy `::Id == ()` | note: required by a bound in `test` --> $DIR/specialization-unconstrained.rs:17:20 diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.rs b/tests/ui/traits/next-solver/unsound-region-obligation.rs new file mode 100644 index 0000000000000..b8bfa03538887 --- /dev/null +++ b/tests/ui/traits/next-solver/unsound-region-obligation.rs @@ -0,0 +1,13 @@ +//~ ERROR the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime +// compile-flags: -Znext-solver +// Regression test for rust-lang/trait-system-refactor-initiative#59 + +trait StaticTy { + type Item<'a>: 'static; +} + +impl StaticTy for () { + type Item<'a> = &'a (); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/unsound-region-obligation.stderr b/tests/ui/traits/next-solver/unsound-region-obligation.stderr new file mode 100644 index 0000000000000..518de7ea3e025 --- /dev/null +++ b/tests/ui/traits/next-solver/unsound-region-obligation.stderr @@ -0,0 +1,7 @@ +error[E0477]: the type `<() as StaticTy>::Item<'a>` does not fulfill the required lifetime + | + = note: type must satisfy the static lifetime + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0477`. diff --git a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr index d5f2bfef19260..4694e7da500f3 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-copy-cond.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/bad-copy-cond.rs:7:5 | LL | foo(); - | ^^^ the trait `Copy` is not implemented for `T` + | ^^^^^ the trait `Copy` is not implemented for `T` | note: required by a bound in `foo` --> $DIR/bad-copy-cond.rs:4:26 diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr index d8db07277c500..f7d5d6fcee4db 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr @@ -11,7 +11,7 @@ error[E0277]: the size for values of type `V` cannot be known at compilation tim --> $DIR/bad-sized-cond.rs:17:5 | LL | foo(); - | ^^^ doesn't have a size known at compile-time + | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `V` note: required by a bound in `foo` @@ -27,9 +27,9 @@ error[E0277]: `V` is not an iterator --> $DIR/bad-sized-cond.rs:20:5 | LL | bar(); - | ^^^ `V` is not an iterator + | ^^^^^ `V` is not an iterator | - = help: the trait `Iterator` is not implemented for `V` + = help: the trait `Iterator` is not implemented for `V`, which is required by `V: IntoIterator` = note: required for `V` to implement `IntoIterator` note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:12:15 @@ -44,9 +44,9 @@ error[E0277]: the size for values of type `V` cannot be known at compilation tim --> $DIR/bad-sized-cond.rs:20:5 | LL | bar(); - | ^^^ doesn't have a size known at compile-time + | ^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `V` + = help: the trait `Sized` is not implemented for `V`, which is required by `V: IntoIterator` = note: required for `V` to implement `IntoIterator` note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:12:15 diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr index 240bcef7df504..9a324c952931e 100644 --- a/tests/ui/traits/non_lifetime_binders/fail.stderr +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -11,7 +11,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/fail.rs:19:5 | LL | fail(); - | ^^^^ the trait `Trait` is not implemented for `T` + | ^^^^^^ the trait `Trait` is not implemented for `T` | help: this trait has no implementations, consider adding one --> $DIR/fail.rs:6:1 @@ -31,7 +31,7 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/fail.rs:21:5 | LL | auto_trait(); - | ^^^^^^^^^^ `T` cannot be sent between threads safely + | ^^^^^^^^^^^^ `T` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `T` note: required by a bound in `auto_trait` diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr index 8cf32c89416a7..abbdecf2fe1db 100644 --- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr @@ -11,7 +11,7 @@ error[E0277]: can't compare `T` with `T` --> $DIR/foreach-partial-eq.rs:10:5 | LL | auto_trait(); - | ^^^^^^^^^^ no implementation for `T < T` and `T > T` + | ^^^^^^^^^^^^ no implementation for `T < T` and `T > T` | = help: the trait `PartialOrd` is not implemented for `T` note: required by a bound in `auto_trait` diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs new file mode 100644 index 0000000000000..8958871ed5d72 --- /dev/null +++ b/tests/ui/traits/object/pretty.rs @@ -0,0 +1,37 @@ +// Test for pretty-printing trait object types. + +trait Super { + type Assoc; +} +trait Any: Super {} +trait Fixed: Super {} +trait FixedSub: Fixed {} +trait FixedStatic: Super {} + +trait SuperGeneric<'a> { + type Assoc2; +} +trait AnyGeneric<'a>: SuperGeneric<'a> {} +trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {} +trait FixedGeneric2<'a>: Super {} +trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {} +trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} +trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} + +fn dyn_super(x: &dyn Super) { x } //~ERROR mismatched types +fn dyn_any(x: &dyn Any) { x } //~ERROR mismatched types +fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types +fn dyn_fixed_multi(x: &dyn Fixed) { x } //~ERROR mismatched types +fn dyn_fixed_sub(x: &dyn FixedSub) { x } //~ERROR mismatched types +fn dyn_fixed_static(x: &dyn FixedStatic) { x } //~ERROR mismatched types + +fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types +fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types +fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } //~ERROR mismatched types +fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } //~ERROR mismatched types +fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } //~ERROR mismatched types +fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types +fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } //~ERROR mismatched types +fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } //~ERROR mismatched types + +fn main() {} diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr new file mode 100644 index 0000000000000..bc645e5f9677d --- /dev/null +++ b/tests/ui/traits/object/pretty.stderr @@ -0,0 +1,157 @@ +error[E0308]: mismatched types + --> $DIR/pretty.rs:21:43 + | +LL | fn dyn_super(x: &dyn Super) { x } + | - ^ expected `()`, found `&dyn Super` + | | + | help: try adding a return type: `-> &dyn Super` + | + = note: expected unit type `()` + found reference `&dyn Super` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:22:39 + | +LL | fn dyn_any(x: &dyn Any) { x } + | - ^ expected `()`, found `&dyn Any` + | | + | help: try adding a return type: `-> &dyn Any` + | + = note: expected unit type `()` + found reference `&dyn Any` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:23:31 + | +LL | fn dyn_fixed(x: &dyn Fixed) { x } + | - ^ expected `()`, found `&dyn Fixed` + | | + | help: try adding a return type: `-> &dyn Fixed` + | + = note: expected unit type `()` + found reference `&dyn Fixed` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:24:50 + | +LL | fn dyn_fixed_multi(x: &dyn Fixed) { x } + | - ^ expected `()`, found `&dyn Fixed` + | | + | help: try adding a return type: `-> &dyn Fixed` + | + = note: expected unit type `()` + found reference `&dyn Fixed` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:25:38 + | +LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } + | - ^ expected `()`, found `&dyn FixedSub` + | | + | help: try adding a return type: `-> &dyn FixedSub` + | + = note: expected unit type `()` + found reference `&dyn FixedSub` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:26:44 + | +LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } + | - ^ expected `()`, found `&dyn FixedStatic` + | | + | help: try adding a return type: `-> &dyn FixedStatic` + | + = note: expected unit type `()` + found reference `&dyn FixedStatic` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:28:75 + | +LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } + | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc2 = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:29:71 + | +LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } + | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc2 = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:30:60 + | +LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric1<'a>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:31:60 + | +LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric2<'a>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric2<'a>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:32:79 + | +LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:33:40 + | +LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } + | - ^ expected `()`, found `&dyn FixedHrtb` + | | + | help: try adding a return type: `-> &dyn FixedHrtb` + | + = note: expected unit type `()` + found reference `&dyn FixedHrtb` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:34:73 + | +LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders) { x } + | - ^ expected `()`, found `&dyn AnyDifferentBinders` + | | + | help: try adding a return type: `-> &dyn AnyDifferentBinders` + | + = note: expected unit type `()` + found reference `&dyn AnyDifferentBinders` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:35:65 + | +LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } + | - ^ expected `()`, found `&dyn FixedDifferentBinders` + | | + | help: try adding a return type: `-> &dyn FixedDifferentBinders` + | + = note: expected unit type `()` + found reference `&dyn FixedDifferentBinders` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/pointee-normalize-equate.rs b/tests/ui/traits/pointee-normalize-equate.rs new file mode 100644 index 0000000000000..2e75933aca0cf --- /dev/null +++ b/tests/ui/traits/pointee-normalize-equate.rs @@ -0,0 +1,56 @@ +// check-pass +// revisions: old next +//[next] compile-flags: -Znext-solver + +#![feature(ptr_metadata)] + +use std::ptr::{self, Pointee}; + +fn cast_same_meta(ptr: *const T) -> *const U +where + T: Pointee::Metadata>, +{ + let (thin, meta) = ptr.to_raw_parts(); + ptr::from_raw_parts(thin, meta) +} + +struct Wrapper(T); + +// normalize `Wrapper::Metadata` -> `T::Metadata` +fn wrapper_to_tail(ptr: *const T) -> *const Wrapper { + cast_same_meta(ptr) +} + +// normalize `Wrapper::Metadata` -> `T::Metadata` -> `()` +fn wrapper_to_unit(ptr: *const ()) -> *const Wrapper { + cast_same_meta(ptr) +} + +trait Project { + type Assoc: ?Sized; +} + +struct WrapperProject(T::Assoc); + +// normalize `WrapperProject::Metadata` -> `T::Assoc::Metadata` +fn wrapper_project_tail(ptr: *const T::Assoc) -> *const WrapperProject { + cast_same_meta(ptr) +} + +// normalize `WrapperProject::Metadata` -> `T::Assoc::Metadata` -> `()` +fn wrapper_project_unit(ptr: *const ()) -> *const WrapperProject +where + T::Assoc: Sized, +{ + cast_same_meta(ptr) +} + +// normalize `<[T] as Pointee>::Metadata` -> `usize`, even if `[T]: Sized` +fn sized_slice(ptr: *const [T]) -> *const str +where + [T]: Sized, +{ + cast_same_meta(ptr) +} + +fn main() {} diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr index 3059e0beca3e4..79f270fd1bbd6 100644 --- a/tests/ui/traits/question-mark-result-err-mismatch.stderr +++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr @@ -11,7 +11,7 @@ LL | | e; LL | | }) | |__________- this can't be annotated with `?` because it has type `Result<_, ()>` LL | .map(|()| "")?; - | ^ the trait `From<()>` is not implemented for `String` + | ^ the trait `From<()>` is not implemented for `String`, which is required by `Result: FromResidual>` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required for `Result` to implement `FromResidual>` @@ -25,7 +25,7 @@ LL | let x = foo(); | ----- this has type `Result<_, String>` ... LL | .map_err(|_| ())?; - | ---------------^ the trait `From<()>` is not implemented for `String` + | ---------------^ the trait `From<()>` is not implemented for `String`, which is required by `Result<(), String>: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, ()>` | @@ -50,7 +50,7 @@ LL | .ok_or_else(|| { LL | | "Couldn't split the test string"; | | - help: remove this semicolon LL | | })?; - | | -^ the trait `From<()>` is not implemented for `String` + | | -^ the trait `From<()>` is not implemented for `String`, which is required by `Result: FromResidual>` | |__________| | this can't be annotated with `?` because it has type `Result<_, ()>` | diff --git a/tests/ui/traits/self-without-lifetime-constraint.rs b/tests/ui/traits/self-without-lifetime-constraint.rs index 99013d32ab8d0..50901173b763d 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.rs +++ b/tests/ui/traits/self-without-lifetime-constraint.rs @@ -15,6 +15,7 @@ impl<'a> ValueRef<'a> { match *self { ValueRef::Text(t) => { std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + //~^ ERROR: cannot return value referencing function parameter `x` } _ => Err(FromSqlError::InvalidType), } diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr index 0a5ae8a027e48..8997d2a98b323 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.stderr +++ b/tests/ui/traits/self-without-lifetime-constraint.stderr @@ -1,5 +1,5 @@ error: `impl` item signature doesn't match `trait` item signature - --> $DIR/self-without-lifetime-constraint.rs:45:5 + --> $DIR/self-without-lifetime-constraint.rs:46:5 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` @@ -10,10 +10,20 @@ LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - --> $DIR/self-without-lifetime-constraint.rs:41:60 + --> $DIR/self-without-lifetime-constraint.rs:42:60 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | ^^^^ consider borrowing this type parameter in the trait -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing function parameter `x` + --> $DIR/self-without-lifetime-constraint.rs:17:87 + | +LL | std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + | ^^^^--^ + | | | + | | `x` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/traits/static-method-generic-inference.stderr b/tests/ui/traits/static-method-generic-inference.stderr index 44c7c099832b5..80bdbbf350dfd 100644 --- a/tests/ui/traits/static-method-generic-inference.stderr +++ b/tests/ui/traits/static-method-generic-inference.stderr @@ -5,7 +5,7 @@ LL | fn new() -> T; | -------------- `HasNew::new` defined here ... LL | let _f: base::Foo = base::HasNew::new(); - | ^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr index 8024ad28d5ae6..28a0646a86bfc 100644 --- a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr +++ b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr @@ -6,7 +6,7 @@ LL | use_iterator(i); | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `&dyn IntoIterator` + = help: the trait `Iterator` is not implemented for `&dyn IntoIterator`, which is required by `&dyn IntoIterator: IntoIterator` = note: required for `&dyn IntoIterator` to implement `IntoIterator` note: required by a bound in `use_iterator` --> $DIR/dont-suggest-unsize-deref.rs:3:8 diff --git a/tests/ui/traits/suggest-dereferences/issue-39029.stderr b/tests/ui/traits/suggest-dereferences/issue-39029.stderr index fd45fa3cf74d0..0eea6cbcc5a62 100644 --- a/tests/ui/traits/suggest-dereferences/issue-39029.stderr +++ b/tests/ui/traits/suggest-dereferences/issue-39029.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied --> $DIR/issue-39029.rs:16:38 | LL | let _errors = TcpListener::bind(&bad); - | ----------------- ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs` + | ----------------- ^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`, which is required by `&NoToSocketAddrs: ToSocketAddrs` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/suggest-dereferences/root-obligation.stderr b/tests/ui/traits/suggest-dereferences/root-obligation.stderr index 62500866c49b9..a41330373be1a 100644 --- a/tests/ui/traits/suggest-dereferences/root-obligation.stderr +++ b/tests/ui/traits/suggest-dereferences/root-obligation.stderr @@ -6,7 +6,7 @@ LL | .filter(|c| "aeiou".contains(c)) | | | required by a bound introduced by this call | - = help: the trait `Fn<(char,)>` is not implemented for `char` + = help: the trait `Fn<(char,)>` is not implemented for `char`, which is required by `&char: Pattern<'_>` = note: required for `&char` to implement `FnOnce<(char,)>` = note: required for `&char` to implement `Pattern<'_>` note: required by a bound in `core::str::::contains` diff --git a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr index d6033bc6baa0f..d1d75625abaaa 100644 --- a/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr +++ b/tests/ui/traits/suggest-dereferences/suggest-dereferencing-receiver-argument.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `TargetStruct: From<&{integer}>` is not satisfied --> $DIR/suggest-dereferencing-receiver-argument.rs:13:30 | LL | let _b: TargetStruct = a.into(); - | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct` + | ^^^^ the trait `From<&{integer}>` is not implemented for `TargetStruct`, which is required by `&{integer}: Into<_>` | = note: required for `&{integer}` to implement `Into` help: consider dereferencing here diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr index e3bbf768c6e73..08f3a8dc23dd1 100644 --- a/tests/ui/traits/suggest-where-clause.stderr +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -7,7 +7,7 @@ LL | // suggest a where-clause, if needed LL | mem::size_of::(); | ^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider removing the `?Sized` bound to make the type parameter `Sized` | @@ -29,7 +29,7 @@ note: required because it appears within the type `Misc` | LL | struct Misc(T); | ^^^^ -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider removing the `?Sized` bound to make the type parameter `Sized` | @@ -72,7 +72,7 @@ LL | mem::size_of::<[T]>(); | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[T]` -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error[E0277]: the size for values of type `[&U]` cannot be known at compilation time @@ -82,7 +82,7 @@ LL | mem::size_of::<[&U]>(); | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[&U]` -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: aborting due to 7 previous errors diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs index 9825158c2dd38..6486ec3891c68 100644 --- a/tests/ui/traits/trait-upcasting/lifetime.rs +++ b/tests/ui/traits/trait-upcasting/lifetime.rs @@ -7,7 +7,7 @@ trait Foo: PartialEq + std::fmt::Debug + Send + Sync { 10 } - fn z(&self) -> i32 { + fn z(&self) -> i32 { //~ WARN methods `z` and `y` are never used 11 } @@ -21,7 +21,7 @@ trait Bar: Foo { 20 } - fn w(&self) -> i32 { + fn w(&self) -> i32 { //~ WARN method `w` is never used 21 } } diff --git a/tests/ui/traits/trait-upcasting/lifetime.stderr b/tests/ui/traits/trait-upcasting/lifetime.stderr new file mode 100644 index 0000000000000..ca8f9cf63f3e7 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/lifetime.stderr @@ -0,0 +1,25 @@ +warning: methods `z` and `y` are never used + --> $DIR/lifetime.rs:10:8 + | +LL | trait Foo: PartialEq + std::fmt::Debug + Send + Sync { + | --- methods in this trait +... +LL | fn z(&self) -> i32 { + | ^ +... +LL | fn y(&self) -> i32 { + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: method `w` is never used + --> $DIR/lifetime.rs:24:8 + | +LL | trait Bar: Foo { + | --- method in this trait +... +LL | fn w(&self) -> i32 { + | ^ + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs index 9ccfc9306ac0c..5ef65786bb705 100644 --- a/tests/ui/traits/trait-upcasting/replace-vptr.rs +++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs @@ -3,7 +3,7 @@ #![feature(trait_upcasting)] trait A { - fn foo_a(&self); + fn foo_a(&self); //~ WARN method `foo_a` is never used } trait B { @@ -11,7 +11,7 @@ trait B { } trait C: A + B { - fn foo_c(&self); + fn foo_c(&self); //~ WARN method `foo_c` is never used } struct S(i32); diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.stderr b/tests/ui/traits/trait-upcasting/replace-vptr.stderr new file mode 100644 index 0000000000000..823094761b385 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/replace-vptr.stderr @@ -0,0 +1,20 @@ +warning: method `foo_a` is never used + --> $DIR/replace-vptr.rs:6:8 + | +LL | trait A { + | - method in this trait +LL | fn foo_a(&self); + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: method `foo_c` is never used + --> $DIR/replace-vptr.rs:14:8 + | +LL | trait C: A + B { + | - method in this trait +LL | fn foo_c(&self); + | ^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/unsend-future.stderr b/tests/ui/traits/unsend-future.stderr index 25df34197947b..4462208cb4956 100644 --- a/tests/ui/traits/unsend-future.stderr +++ b/tests/ui/traits/unsend-future.stderr @@ -4,7 +4,7 @@ error: future cannot be sent between threads safely LL | require_handler(handler) | ^^^^^^^ future returned by `handler` is not `Send` | - = help: within `impl Future`, the trait `Send` is not implemented for `*const i32` + = help: within `impl Future`, the trait `Send` is not implemented for `*const i32`, which is required by `fn() -> impl Future {handler}: Handler` note: future is not `Send` as this value is used across an await --> $DIR/unsend-future.rs:15:14 | diff --git a/tests/ui/traits/use-before-def.rs b/tests/ui/traits/use-before-def.rs index 1ee2b941909f4..e52dc53fbab79 100644 --- a/tests/ui/traits/use-before-def.rs +++ b/tests/ui/traits/use-before-def.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(non_camel_case_types)] // Issue #1761 diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs index 74b2ef48533d2..e90c8763d651f 100644 --- a/tests/ui/traits/wf-object/reverse-order.rs +++ b/tests/ui/traits/wf-object/reverse-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. diff --git a/tests/ui/transmutability/region-infer.stderr b/tests/ui/transmutability/region-infer.stderr index 50d060cd47431..805862d6c4afc 100644 --- a/tests/ui/transmutability/region-infer.stderr +++ b/tests/ui/transmutability/region-infer.stderr @@ -2,7 +2,7 @@ error[E0277]: `()` cannot be safely transmuted into `W<'_>` in the defining scop --> $DIR/region-infer.rs:20:5 | LL | test(); - | ^^^^ The size of `()` is smaller than the size of `W<'_>` + | ^^^^^^ The size of `()` is smaller than the size of `W<'_>` | note: required by a bound in `test` --> $DIR/region-infer.rs:11:12 diff --git a/tests/ui/treat-err-as-bug/eagerly-emit.rs b/tests/ui/treat-err-as-bug/eagerly-emit.rs index 5f32f5a1d94b7..ede190575d529 100644 --- a/tests/ui/treat-err-as-bug/eagerly-emit.rs +++ b/tests/ui/treat-err-as-bug/eagerly-emit.rs @@ -6,6 +6,5 @@ fn main() {} fn f() -> impl Foo { //~^ ERROR the trait bound `i32: Foo` is not satisfied - //~| ERROR `report_selection_error` did not emit an error 1i32 } diff --git a/tests/ui/treat-err-as-bug/eagerly-emit.stderr b/tests/ui/treat-err-as-bug/eagerly-emit.stderr index 3d25741d52de8..4ae596435aa7f 100644 --- a/tests/ui/treat-err-as-bug/eagerly-emit.stderr +++ b/tests/ui/treat-err-as-bug/eagerly-emit.stderr @@ -1,9 +1,3 @@ -error: `report_selection_error` did not emit an error - --> $DIR/eagerly-emit.rs:7:11 - | -LL | fn f() -> impl Foo { - | ^^^^^^^^ - error: trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging error[E0277]: the trait bound `i32: Foo` is not satisfied @@ -11,7 +5,7 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied | LL | fn f() -> impl Foo { | ^^^^^^^^ the trait `Foo` is not implemented for `i32` -... +LL | LL | 1i32 | ---- return type was inferred to be `i32` here | @@ -21,8 +15,6 @@ help: this trait has no implementations, consider adding one LL | trait Foo {} | ^^^^^^^^^ -error: expected fulfillment errors - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/trivial_casts-rpass.rs b/tests/ui/trivial_casts-rpass.rs index 8e49468bf0c45..4653a8df802da 100644 --- a/tests/ui/trivial_casts-rpass.rs +++ b/tests/ui/trivial_casts-rpass.rs @@ -4,7 +4,7 @@ #![allow(trivial_casts, trivial_numeric_casts)] trait Foo { - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } pub struct Bar; diff --git a/tests/ui/trivial_casts-rpass.stderr b/tests/ui/trivial_casts-rpass.stderr new file mode 100644 index 0000000000000..74698b61ab4a4 --- /dev/null +++ b/tests/ui/trivial_casts-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/trivial_casts-rpass.rs:7:8 + | +LL | trait Foo { + | --- method in this trait +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index d58a011ff5501..6c41b42dc643f 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -2,7 +2,7 @@ error[E0277]: `?` couldn't convert the error to `TryFromSliceError` --> $DIR/try-block-bad-type.rs:7:16 | LL | Err("")?; - | -------^ the trait `From<&str>` is not implemented for `TryFromSliceError` + | -------^ the trait `From<&str>` is not implemented for `TryFromSliceError`, which is required by `Result: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, &str>` | diff --git a/tests/ui/try-block/try-block-in-match-arm.rs b/tests/ui/try-block/try-block-in-match-arm.rs new file mode 100644 index 0000000000000..ea004ebe29f9e --- /dev/null +++ b/tests/ui/try-block/try-block-in-match-arm.rs @@ -0,0 +1,11 @@ +// check-pass +// compile-flags: --edition 2018 + +#![feature(try_blocks)] + +fn main() { + let _ = match 1 { + 1 => try {} + _ => Ok::<(), ()>(()), + }; +} diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index 7e5b68353fb2d..80471c0ab1a40 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -4,7 +4,7 @@ error[E0277]: `?` couldn't convert the error to `u8` LL | fn result_to_result() -> Result { | --------------- expected `u8` because of this LL | Ok(Err(123_i32)?) - | ------------^ the trait `From` is not implemented for `u8` + | ------------^ the trait `From` is not implemented for `u8`, which is required by `Result: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, i32>` | diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr index b155b3ff66313..34618de78cd0f 100644 --- a/tests/ui/try-trait/issue-32709.stderr +++ b/tests/ui/try-trait/issue-32709.stderr @@ -4,7 +4,7 @@ error[E0277]: `?` couldn't convert the error to `()` LL | fn a() -> Result { | --------------- expected `()` because of this LL | Err(5)?; - | ------^ the trait `From<{integer}>` is not implemented for `()` + | ------^ the trait `From<{integer}>` is not implemented for `()`, which is required by `Result: FromResidual>` | | | this can't be annotated with `?` because it has type `Result<_, {integer}>` | diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs index acbf15dcb6c6a..5f3b711b31aa9 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs @@ -31,10 +31,7 @@ impl Tr for E { type V = u8; fn f() -> Self::V { 0 } //~^ ERROR ambiguous associated item - //~| ERROR ambiguous associated item //~| WARN this was previously accepted - //~| WARN this was previously accepted - //~| HELP use fully-qualified syntax //~| HELP use fully-qualified syntax } diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr index 359bd09ecd02b..0f42fcbe04d0a 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -18,25 +18,5 @@ LL | type V; | ^^^^^^ = note: `#[deny(ambiguous_associated_items)]` on by default -error: ambiguous associated item - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 - | -LL | fn f() -> Self::V { 0 } - | ^^^^^^^ help: use fully-qualified syntax: `::V` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57644 -note: `V` could refer to the variant defined here - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5 - | -LL | V - | ^ -note: `V` could also refer to the associated type defined here - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 - | -LL | type V; - | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr index 2ed918eca1714..5c5506fb8532d 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -9,7 +9,7 @@ LL | is_send(m::foo()); | | | required by a bound introduced by this call | - = help: within `Foo`, the trait `Send` is not implemented for `Rc` + = help: within `Foo`, the trait `Send` is not implemented for `Rc`, which is required by `Foo: Send` note: required because it appears within the type `Foo` --> $DIR/auto-trait-leakage2.rs:7:16 | diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs index ac32dbde04b1c..1a5daa13458c6 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -6,6 +6,7 @@ mod test_type_param_static { fn defining(s: A) -> Ty { s } fn assert_static() {} fn test() where Ty: 'static { assert_static::() } + //~^ ERROR: the parameter type `A` may not live long enough } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index ff11aee40261b..d1c06330c15e0 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -12,6 +12,20 @@ help: consider adding an explicit lifetime bound LL | type Ty = impl Sized + 'static; | +++++++++ -error: aborting due to 1 previous error +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check4_static.rs:8:41 + | +LL | fn test() where Ty: 'static { assert_static::() } + | ^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn test() where Ty: 'static { assert_static::() } + | +++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/issue-58887.rs b/tests/ui/type-alias-impl-trait/issue-58887.rs index 9675867656a96..68d85ed6b0f9b 100644 --- a/tests/ui/type-alias-impl-trait/issue-58887.rs +++ b/tests/ui/type-alias-impl-trait/issue-58887.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 3d6c826d6ac5a..2d9345a3e5e8e 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -7,6 +7,7 @@ type Pointer = impl std::ops::Deref; fn test() -> Pointer<_> { //~^ ERROR: the placeholder `_` is not allowed within types Box::new(1) + //~^ ERROR: expected generic type parameter, found `i32` } fn main() { diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index c5cacfd3cd351..ebd78e5b7a54f 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -8,7 +8,7 @@ LL | fn test() -> Pointer<_> { | help: replace with the correct return type: `Pointer` error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/issue-77179.rs:17:25 + --> $DIR/issue-77179.rs:18:25 | LL | fn bar() -> Pointer<_>; | ^ @@ -16,6 +16,16 @@ LL | fn bar() -> Pointer<_>; | not allowed in type signatures | help: use type parameters instead: `T` -error: aborting due to 2 previous errors +error[E0792]: expected generic type parameter, found `i32` + --> $DIR/issue-77179.rs:9:5 + | +LL | type Pointer = impl std::ops::Deref; + | - this generic parameter must be used with a generic type parameter +... +LL | Box::new(1) + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0792. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index 37abb3fe021bb..5e978e97d6b50 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `B: Bar` is not satisfied --> $DIR/issue-90400-2.rs:25:9 | LL | MyBaz(bar) - | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` + | ^^^^^^^^^^ the trait `Bar` is not implemented for `B`, which is required by `MyBaz: Baz` | note: required for `MyBaz` to implement `Baz` --> $DIR/issue-90400-2.rs:30:14 diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr index b5f38074632ee..a7840e0a5bf24 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied --> $DIR/multiple-def-uses-in-one-fn.rs:9:45 | LL | fn f(a: &'static A, b: B) -> (X, X) { - | ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` + | ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`, which is required by `&A: Into<&'static B>` | = note: required for `&A` to implement `Into<&'static B>` help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs index 0f0a02e97d82d..6431cf37df7ab 100644 --- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -14,5 +14,7 @@ mod foo { } fn main() { - let _: foo::Foo = std::mem::transmute(0u8); + unsafe { + let _: foo::Foo = std::mem::transmute(0u8); + } } diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr index d92bafce142c2..fd76526644bdd 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -1,4 +1,4 @@ -note: no errors encountered even though `span_delayed_bug` issued +note: no errors encountered even though delayed bugs were created note: those delayed bugs will now be shown as internal compiler errors diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr index e4de9245951cf..913a35eb9fb0e 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied --> $DIR/underconstrained_generic.rs:22:5 | LL | () - | ^^ the trait `Trait` is not implemented for `T` + | ^^ the trait `Trait` is not implemented for `T`, which is required by `(): ProofForConversion` | note: required for `()` to implement `ProofForConversion` --> $DIR/underconstrained_generic.rs:13:16 diff --git a/tests/ui/type/issue-101866.stderr b/tests/ui/type/issue-101866.stderr index 6f4b380b4e746..4d02153ebe20e 100644 --- a/tests/ui/type/issue-101866.stderr +++ b/tests/ui/type/issue-101866.stderr @@ -5,7 +5,7 @@ LL | fn func(); | ---------- `TraitA::func` defined here ... LL | TraitA::::func(); - | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait + | ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/type/issue-58355.stderr b/tests/ui/type/issue-58355.stderr index b6056f0fd65ad..cd8e353880241 100644 --- a/tests/ui/type/issue-58355.stderr +++ b/tests/ui/type/issue-58355.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `dyn ToString` cannot be known at comp LL | x = Some(Box::new(callback)); | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString` + = help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString`, which is required by `fn() -> dyn ToString: Fn()` = note: required because it appears within the type `fn() -> dyn ToString` = note: required for the cast from `Box dyn ToString>` to `Box (dyn ToString + 'static)>` diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr index bd7fd0392c378..137c7b0639667 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `K: Hash` is not satisfied --> $DIR/bad-index-due-to-nested.rs:20:5 | LL | map[k] - | ^^^ the trait `Hash` is not implemented for `K` + | ^^^ the trait `Hash` is not implemented for `K`, which is required by `HashMap<_, _>: Index<&_>` | note: required for `HashMap` to implement `Index<&K>` --> $DIR/bad-index-due-to-nested.rs:7:12 @@ -21,7 +21,7 @@ error[E0277]: the trait bound `V: Copy` is not satisfied --> $DIR/bad-index-due-to-nested.rs:20:5 | LL | map[k] - | ^^^ the trait `Copy` is not implemented for `V` + | ^^^ the trait `Copy` is not implemented for `V`, which is required by `HashMap<_, _>: Index<&_>` | note: required for `HashMap` to implement `Index<&K>` --> $DIR/bad-index-due-to-nested.rs:7:12 diff --git a/tests/ui/typeck/issue-104510-ice.rs b/tests/ui/typeck/issue-104510-ice.rs index 157bdf07e3826..635cc8fad66f1 100644 --- a/tests/ui/typeck/issue-104510-ice.rs +++ b/tests/ui/typeck/issue-104510-ice.rs @@ -6,7 +6,7 @@ struct W(Oops); unsafe fn test() { let j = W(()); - let pointer = &j as *const _; + let pointer = &j as *const _; //~ ERROR type annotations needed core::arch::asm!( "nop", in("eax") pointer, diff --git a/tests/ui/typeck/issue-104510-ice.stderr b/tests/ui/typeck/issue-104510-ice.stderr index 143139b2c089c..774e52681849f 100644 --- a/tests/ui/typeck/issue-104510-ice.stderr +++ b/tests/ui/typeck/issue-104510-ice.stderr @@ -4,6 +4,18 @@ error[E0412]: cannot find type `Oops` in this scope LL | struct W(Oops); | ^^^^ not found in this scope -error: aborting due to 1 previous error +error[E0282]: type annotations needed for `*const W` + --> $DIR/issue-104510-ice.rs:9:9 + | +LL | let pointer = &j as *const _; + | ^^^^^^^ + | +help: consider giving `pointer` an explicit type, where the type for type parameter `T` is specified + | +LL | let pointer: *const W = &j as *const _; + | +++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0282, E0412. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/issues/issue-16338.rs b/tests/ui/typeck/issue-16338.rs similarity index 100% rename from tests/ui/issues/issue-16338.rs rename to tests/ui/typeck/issue-16338.rs diff --git a/tests/ui/issues/issue-16338.stderr b/tests/ui/typeck/issue-16338.stderr similarity index 100% rename from tests/ui/issues/issue-16338.stderr rename to tests/ui/typeck/issue-16338.stderr diff --git a/tests/ui/typeck/issue-90101.stderr b/tests/ui/typeck/issue-90101.stderr index a24f9cb540fc8..d5ba157974d93 100644 --- a/tests/ui/typeck/issue-90101.stderr +++ b/tests/ui/typeck/issue-90101.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `PathBuf: From>` is not satisfied --> $DIR/issue-90101.rs:6:10 | LL | func(Path::new("hello").to_path_buf().to_string_lossy(), "world") - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `PathBuf` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `PathBuf`, which is required by `Cow<'_, str>: Into` | | | required by a bound introduced by this call | diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr index b9fca1a1b54b8..f5311b6e8ed7f 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -17,7 +17,7 @@ error[E0277]: `UnsafeCell` cannot be shared between threads safely LL | is_sync::(); | ^^^^^^^^^^^^^ `UnsafeCell` cannot be shared between threads safely | - = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell` + = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell`, which is required by `MyTypeWUnsafe: Sync` note: required because it appears within the type `MyTypeWUnsafe` --> $DIR/typeck-default-trait-impl-negation-sync.rs:21:8 | @@ -35,7 +35,7 @@ error[E0277]: `Managed` cannot be shared between threads safely LL | is_sync::(); | ^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely | - = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed` + = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed`, which is required by `MyTypeManaged: Sync` note: required because it appears within the type `MyTypeManaged` --> $DIR/typeck-default-trait-impl-negation-sync.rs:25:8 | diff --git a/tests/ui/typeck/typeck-unsafe-always-share.stderr b/tests/ui/typeck/typeck-unsafe-always-share.stderr index 154e504996bc4..3eb792b82e0f4 100644 --- a/tests/ui/typeck/typeck-unsafe-always-share.stderr +++ b/tests/ui/typeck/typeck-unsafe-always-share.stderr @@ -36,7 +36,7 @@ LL | test(ms); | | | required by a bound introduced by this call | - = help: within `MySync`, the trait `Sync` is not implemented for `UnsafeCell` + = help: within `MySync`, the trait `Sync` is not implemented for `UnsafeCell`, which is required by `MySync: Sync` note: required because it appears within the type `MySync` --> $DIR/typeck-unsafe-always-share.rs:8:8 | diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index 4eba14f5a93fb..591a7278ddcf6 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -198,6 +198,7 @@ trait Qux { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types } impl Qux for Struct { + //~^ ERROR not all trait items implemented, missing: `F` type A = _; //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types type B = _; diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index a4325b01f02c4..bfcc76c1dae7d 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -29,7 +29,7 @@ LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:205:5 + --> $DIR/typeck_type_placeholder_item.rs:206:5 | LL | const C: _; | ^^^^^^^^^^- @@ -411,7 +411,7 @@ LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/typeck_type_placeholder_item.rs:216:31 + --> $DIR/typeck_type_placeholder_item.rs:217:31 | LL | fn value() -> Option<&'static _> { | ----------------^- @@ -420,7 +420,7 @@ LL | fn value() -> Option<&'static _> { | help: replace with the correct return type: `Option<&'static u8>` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:221:10 + --> $DIR/typeck_type_placeholder_item.rs:222:10 | LL | const _: Option<_> = map(value); | ^^^^^^^^^ @@ -429,7 +429,7 @@ LL | const _: Option<_> = map(value); | help: replace with the correct type: `Option` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/typeck_type_placeholder_item.rs:224:31 + --> $DIR/typeck_type_placeholder_item.rs:225:31 | LL | fn evens_squared(n: usize) -> _ { | ^ @@ -438,13 +438,13 @@ LL | fn evens_squared(n: usize) -> _ { | help: replace with an appropriate return type: `impl Iterator` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:229:10 + --> $DIR/typeck_type_placeholder_item.rs:230: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, {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 +note: however, the inferred type `Map, {closure@typeck_type_placeholder_item.rs:230:29}>, {closure@typeck_type_placeholder_item.rs:230:49}>` cannot be named + --> $DIR/typeck_type_placeholder_item.rs:230:14 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -631,25 +631,25 @@ LL | fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; } | ~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:201:14 + --> $DIR/typeck_type_placeholder_item.rs:202:14 | LL | type A = _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:203:14 + --> $DIR/typeck_type_placeholder_item.rs:204:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:205:14 + --> $DIR/typeck_type_placeholder_item.rs:206:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:208:14 + --> $DIR/typeck_type_placeholder_item.rs:209:14 | LL | const D: _ = 42; | ^ @@ -657,7 +657,16 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error: aborting due to 71 previous errors +error[E0046]: not all trait items implemented, missing: `F` + --> $DIR/typeck_type_placeholder_item.rs:200:1 + | +LL | type F: std::ops::Fn(_); + | ----------------------- `F` from trait +... +LL | impl Qux for Struct { + | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation + +error: aborting due to 72 previous errors -Some errors have detailed explanations: E0121, E0282, E0403. -For more information about an error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0046, E0121, E0282, E0403. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/typeof/issue-100183.stderr b/tests/ui/typeof/issue-100183.stderr index 7be923d938357..57317d449cf3a 100644 --- a/tests/ui/typeof/issue-100183.stderr +++ b/tests/ui/typeof/issue-100183.stderr @@ -6,8 +6,8 @@ LL | y: (typeof("hey"),), | help: consider replacing `typeof(...)` with an actual type | -LL | y: (&'static str,), - | ~~~~~~~~~~~~ +LL | y: (&str,), + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index ae0a06e6328df..c1281ce6a422f 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -11,6 +11,19 @@ LL | >::add(1, 2); <&'a i32 as Add> <&i32 as Add<&i32>> +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 + | +LL | >::add(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | + = help: the trait `Add` is not implemented for `i32` + = help: the following other types implement trait `Add`: + + > + <&'a i32 as Add> + <&i32 as Add<&i32>> + error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 | @@ -55,19 +68,6 @@ help: change the type of the numeric literal from `u32` to `i32` LL | >::add(1, 2i32); | ~~~ -error[E0277]: cannot add `u32` to `i32` - --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 - | -LL | >::add(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` - | - = help: the trait `Add` is not implemented for `i32` - = help: the following other types implement trait `Add`: - - > - <&'a i32 as Add> - <&i32 as Add<&i32>> - error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs index ea73b8b3c4a28..8537eb7177484 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs @@ -33,6 +33,7 @@ fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { //~^ ERROR trait takes 1 lifetime argument but 0 lifetime arguments were supplied // Here, the omitted lifetimes are expanded to distinct things. same_type(x, y) + //~^ ERROR borrowed data escapes outside of function } fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr index d73aef851fd76..6e6c649ca3d57 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr @@ -34,6 +34,22 @@ note: trait defined here, with 1 lifetime parameter: `'a` LL | trait Foo<'a,T> { | ^^^ -- -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/unboxed-closure-sugar-region.rs:35:5 + | +LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { + | - - `y` declared here, outside of the function body + | | + | `x` is a reference that is only valid in the function body + | has type `&dyn Foo<'1, (isize,), Output = ()>` +... +LL | same_type(x, y) + | ^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0521. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs index 3d049cc5639c0..ebc3879854434 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs @@ -14,6 +14,7 @@ fn meh() -> Box Meh<'_>> //~ ERROR cannot be used here } fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime specifier +//~^ ERROR lifetime may not live long enough fn main() { let x = 5; diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr index cd74d27dcb55f..5d2954d1d71e0 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -45,7 +45,15 @@ help: consider introducing a named lifetime parameter LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } | ++++ ~~ ~~ ~~ -error: aborting due to 5 previous errors +error: lifetime may not live long enough + --> $DIR/underscore-lifetime-binders.rs:16:43 + | +LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } + | - ^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0106, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed index 5be6ff8e7e14e..700e4f2542384 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs index d7072aa118161..66ba9b24dac2f 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr index 54e62f34fbaa3..f012120e550d7 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:13:17 + --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:14:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed index 0f1be586589e2..56682db3b0b43 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed @@ -1,5 +1,6 @@ // edition:2018 // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs index 59f7e472e2d34..5302b2f1576b6 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs @@ -1,5 +1,6 @@ // edition:2018 // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr index 36f3e9ef14527..7d675dd41e904 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:14:17 + --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:15:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed index 55c7470960eb2..f3adc7e7fad32 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs index 42a35b0216119..1e084e9ad41bb 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr index 92b7a9c2af893..8aa0e52c688db 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-trait-impl-region-2015.rs:10:17 + --> $DIR/where-clause-trait-impl-region-2015.rs:11:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed index 09b96fe5ea42a..dd8074abed728 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed @@ -1,6 +1,8 @@ // run-rustfix // edition:2018 +#![allow(dead_code)] + trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs index 445f38cbee187..4fc9c71b17943 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs @@ -1,6 +1,8 @@ // run-rustfix // edition:2018 +#![allow(dead_code)] + trait WithType {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr index 63d8b99ed18fb..22940d0b0b18d 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-trait-impl-region-2018.rs:11:17 + --> $DIR/where-clause-trait-impl-region-2018.rs:13:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr similarity index 91% rename from tests/ui/uninhabited/uninhabited-irrefutable.stderr rename to tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr index 304e738ed2561..c9131a8372ab1 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0005]: refutable pattern in local binding - --> $DIR/uninhabited-irrefutable.rs:29:9 + --> $DIR/uninhabited-irrefutable.rs:32:9 | LL | let Foo::D(_y, _z) = x; | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered @@ -7,7 +7,7 @@ LL | let Foo::D(_y, _z) = x; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `Foo` defined here - --> $DIR/uninhabited-irrefutable.rs:18:6 + --> $DIR/uninhabited-irrefutable.rs:21:6 | LL | enum Foo { | ^^^ diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..c9131a8372ab1 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr @@ -0,0 +1,26 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/uninhabited-irrefutable.rs:32:9 + | +LL | let Foo::D(_y, _z) = x; + | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Foo` defined here + --> $DIR/uninhabited-irrefutable.rs:21:6 + | +LL | enum Foo { + | ^^^ +LL | +LL | A(foo::SecretlyEmpty), + | - not covered + = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future + = note: the matched value is of type `Foo` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Foo::D(_y, _z) = x else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs index cfd60a8d903fa..2ef3b668cb089 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.rs +++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs @@ -1,5 +1,8 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, allow(incomplete_features))] #![feature(never_type)] -#![feature(exhaustive_patterns)] mod foo { pub struct SecretlyEmpty { diff --git a/tests/ui/union/projection-as-union-type-error-2.stderr b/tests/ui/union/projection-as-union-type-error-2.stderr index 3b073ca1fb4e0..39cdf30d8605a 100644 --- a/tests/ui/union/projection-as-union-type-error-2.stderr +++ b/tests/ui/union/projection-as-union-type-error-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u8: NotImplemented` is not satisfied --> $DIR/projection-as-union-type-error-2.rs:18:8 | LL | a: ::Identity, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotImplemented` is not implemented for `u8`, which is required by `u8: Identity` | help: this trait has no implementations, consider adding one --> $DIR/projection-as-union-type-error-2.rs:9:1 diff --git a/tests/ui/union/union-pat-refutability.rs b/tests/ui/union/union-pat-refutability.rs index 17ac6c6dfa9bf..edcc1add38fde 100644 --- a/tests/ui/union/union-pat-refutability.rs +++ b/tests/ui/union/union-pat-refutability.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] -#![allow(illegal_floating_point_literal_pattern)] #[repr(u32)] enum Tag { diff --git a/tests/ui/unsafe/const_pat_in_layout_restricted.rs b/tests/ui/unsafe/const_pat_in_layout_restricted.rs index 5bc7a7113e4f6..9a085958c1080 100644 --- a/tests/ui/unsafe/const_pat_in_layout_restricted.rs +++ b/tests/ui/unsafe/const_pat_in_layout_restricted.rs @@ -2,7 +2,6 @@ // unsafe because they're within a pattern for a layout constrained stuct. // check-pass -#![allow(incomplete_features)] #![feature(rustc_attrs)] #![feature(inline_const_pat)] diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr index b39eb2e70bbae..4c06566709ede 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -13,7 +13,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t LL | A as fn(str) -> A; | ^ doesn't have a size known at compile-time | - = help: within `A`, the trait `Sized` is not implemented for `str` + = help: within `A`, the trait `Sized` is not implemented for `str`, which is required by `A: Sized` note: required because it appears within the type `A` --> $DIR/issue-50940-with-feature.rs:5:12 | diff --git a/tests/ui/unsized-locals/rust-call.stderr b/tests/ui/unsized-locals/rust-call.stderr index 9eb0f3dabcca1..b2e13b553e921 100644 --- a/tests/ui/unsized-locals/rust-call.stderr +++ b/tests/ui/unsized-locals/rust-call.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | f(*slice); | ^^^^^^ doesn't have a size known at compile-time | - = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]` + = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]`, which is required by `([u8],): Sized` = note: required because it appears within the type `([u8],)` = note: argument required to be sized due to `extern "rust-call"` ABI diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr index a7f57e3fd1566..6da37749facbb 100644 --- a/tests/ui/unsized-locals/unsized-exprs.stderr +++ b/tests/ui/unsized-locals/unsized-exprs.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | udrop::<(i32, [u8])>((42, *foo())); | ^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]` + = help: within `({integer}, [u8])`, the trait `Sized` is not implemented for `[u8]`, which is required by `({integer}, [u8]): Sized` = note: required because it appears within the type `({integer}, [u8])` = note: tuples must have a statically known size to be initialized @@ -14,7 +14,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | udrop::>(A { 0: *foo() }); | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` + = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `A<[u8]>: Sized` note: required because it appears within the type `A<[u8]>` --> $DIR/unsized-exprs.rs:3:8 | @@ -26,9 +26,9 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation --> $DIR/unsized-exprs.rs:26:22 | LL | udrop::>(A(*foo())); - | ^ doesn't have a size known at compile-time + | ^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` + = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`, which is required by `A<[u8]>: Sized` note: required because it appears within the type `A<[u8]>` --> $DIR/unsized-exprs.rs:3:8 | diff --git a/tests/ui/unsized/unsized-bare-typaram.stderr b/tests/ui/unsized/unsized-bare-typaram.stderr index aa3f8fae72a17..4202e76b6a2ae 100644 --- a/tests/ui/unsized/unsized-bare-typaram.stderr +++ b/tests/ui/unsized/unsized-bare-typaram.stderr @@ -7,10 +7,10 @@ LL | fn foo() { bar::() } | this type parameter needs to be `Sized` | note: required by a bound in `bar` - --> $DIR/unsized-bare-typaram.rs:1:8 + --> $DIR/unsized-bare-typaram.rs:1:11 | LL | fn bar() { } - | ^ required by this bound in `bar` + | ^^^^^ required by this bound in `bar` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn foo() { bar::() } diff --git a/tests/ui/unsized/unsized-enum.stderr b/tests/ui/unsized/unsized-enum.stderr index 8c56a83a5122e..5a30d7fab65a7 100644 --- a/tests/ui/unsized/unsized-enum.stderr +++ b/tests/ui/unsized/unsized-enum.stderr @@ -6,11 +6,11 @@ LL | fn foo2() { not_sized::>() } | | | this type parameter needs to be `Sized` | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/unsized-enum.rs:4:10 | LL | enum Foo { FooSome(U), FooNone } - | ^ required by this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: you could relax the implicit `Sized` bound on `U` if it were used through indirection like `&U` or `Box` --> $DIR/unsized-enum.rs:4:10 | diff --git a/tests/ui/unsized/unsized-enum2.stderr b/tests/ui/unsized/unsized-enum2.stderr index 71cf782120e57..48cca6eb4bd06 100644 --- a/tests/ui/unsized/unsized-enum2.stderr +++ b/tests/ui/unsized/unsized-enum2.stderr @@ -320,7 +320,7 @@ error[E0277]: the size for values of type `(dyn PathHelper1 + 'static)` cannot b LL | VI(Path1), | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)` + = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)`, which is required by `Path1: Sized` note: required because it appears within the type `Path1` --> $DIR/unsized-enum2.rs:16:8 | @@ -343,7 +343,7 @@ error[E0277]: the size for values of type `(dyn PathHelper2 + 'static)` cannot b LL | VJ{x: Path2}, | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)` + = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)`, which is required by `Path2: Sized` note: required because it appears within the type `Path2` --> $DIR/unsized-enum2.rs:17:8 | @@ -366,7 +366,7 @@ error[E0277]: the size for values of type `(dyn PathHelper3 + 'static)` cannot b LL | VK(isize, Path3), | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)` + = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)`, which is required by `Path3: Sized` note: required because it appears within the type `Path3` --> $DIR/unsized-enum2.rs:18:8 | @@ -389,7 +389,7 @@ error[E0277]: the size for values of type `(dyn PathHelper4 + 'static)` cannot b LL | VL{u: isize, x: Path4}, | ^^^^^ doesn't have a size known at compile-time | - = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)` + = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)`, which is required by `Path4: Sized` note: required because it appears within the type `Path4` --> $DIR/unsized-enum2.rs:19:8 | diff --git a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr index 3e16a20d726dc..5a379f4065aa7 100644 --- a/tests/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/tests/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -6,11 +6,11 @@ LL | impl S5 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `S5` +note: required by an implicit `Sized` bound in `S5` --> $DIR/unsized-inherent-impl-self-type.rs:5:11 | LL | struct S5(Y); - | ^ required by this bound in `S5` + | ^ required by the implicit `Sized` requirement on this type parameter in `S5` help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` --> $DIR/unsized-inherent-impl-self-type.rs:5:11 | diff --git a/tests/ui/unsized/unsized-struct.stderr b/tests/ui/unsized/unsized-struct.stderr index 4e7cb09f0ccaf..06c4ffb7773c6 100644 --- a/tests/ui/unsized/unsized-struct.stderr +++ b/tests/ui/unsized/unsized-struct.stderr @@ -6,11 +6,11 @@ LL | fn foo2() { not_sized::>() } | | | this type parameter needs to be `Sized` | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/unsized-struct.rs:4:12 | LL | struct Foo { data: T } - | ^ required by this bound in `Foo` + | ^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/unsized-struct.rs:4:12 | @@ -38,10 +38,10 @@ note: required because it appears within the type `Bar` LL | struct Bar { data: T } | ^^^ note: required by a bound in `is_sized` - --> $DIR/unsized-struct.rs:1:13 + --> $DIR/unsized-struct.rs:1:15 | LL | fn is_sized() { } - | ^ required by this bound in `is_sized` + | ^^^^^ required by this bound in `is_sized` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn bar2() { is_sized::>() } diff --git a/tests/ui/unsized/unsized-trait-impl-self-type.stderr b/tests/ui/unsized/unsized-trait-impl-self-type.stderr index 5bc8dc590cacb..3b684193b4aca 100644 --- a/tests/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/tests/ui/unsized/unsized-trait-impl-self-type.stderr @@ -6,11 +6,11 @@ LL | impl T3 for S5 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `S5` +note: required by an implicit `Sized` bound in `S5` --> $DIR/unsized-trait-impl-self-type.rs:8:11 | LL | struct S5(Y); - | ^ required by this bound in `S5` + | ^ required by the implicit `Sized` requirement on this type parameter in `S5` help: you could relax the implicit `Sized` bound on `Y` if it were used through indirection like `&Y` or `Box` --> $DIR/unsized-trait-impl-self-type.rs:8:11 | diff --git a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr index e9353d2bbd94a..79fc9567dae6f 100644 --- a/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/tests/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -6,11 +6,11 @@ LL | impl T2 for S4 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `T2` +note: required by an implicit `Sized` bound in `T2` --> $DIR/unsized-trait-impl-trait-arg.rs:4:10 | LL | trait T2 { - | ^ required by this bound in `T2` + | ^ required by the implicit `Sized` requirement on this type parameter in `T2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl T2 for S4 { diff --git a/tests/ui/unsized/unsized3.stderr b/tests/ui/unsized/unsized3.stderr index a11243980d1a3..c7a145b1c5171 100644 --- a/tests/ui/unsized/unsized3.stderr +++ b/tests/ui/unsized/unsized3.stderr @@ -6,11 +6,11 @@ LL | fn f1(x: &X) { LL | f2::(x); | ^ doesn't have a size known at compile-time | -note: required by a bound in `f2` +note: required by an implicit `Sized` bound in `f2` --> $DIR/unsized3.rs:10:7 | LL | fn f2(x: &X) { - | ^ required by this bound in `f2` + | ^ required by the implicit `Sized` requirement on this type parameter in `f2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f1(x: &X) { @@ -29,11 +29,11 @@ LL | fn f3(x: &X) { LL | f4::(x); | ^ doesn't have a size known at compile-time | -note: required by a bound in `f4` +note: required by an implicit `Sized` bound in `f4` --> $DIR/unsized3.rs:21:7 | LL | fn f4(x: &X) { - | ^ required by this bound in `f4` + | ^ required by the implicit `Sized` requirement on this type parameter in `f4` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f3(x: &X) { @@ -59,11 +59,11 @@ note: required because it appears within the type `S` | LL | struct S { | ^ -note: required by a bound in `f5` +note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | LL | fn f5(x: &Y) {} - | ^ required by this bound in `f5` + | ^ required by the implicit `Sized` requirement on this type parameter in `f5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f8(x1: &S, x2: &S) { @@ -131,11 +131,11 @@ note: required because it appears within the type `S` LL | struct S { | ^ = note: required because it appears within the type `({integer}, S)` -note: required by a bound in `f5` +note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | LL | fn f5(x: &Y) {} - | ^ required by this bound in `f5` + | ^ required by the implicit `Sized` requirement on this type parameter in `f5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f10(x1: Box>) { diff --git a/tests/ui/unsized/unsized7.stderr b/tests/ui/unsized/unsized7.stderr index 2edde15965343..6e9c052a07022 100644 --- a/tests/ui/unsized/unsized7.stderr +++ b/tests/ui/unsized/unsized7.stderr @@ -6,11 +6,11 @@ LL | impl T1 for S3 { | | | this type parameter needs to be `Sized` | -note: required by a bound in `T1` +note: required by an implicit `Sized` bound in `T1` --> $DIR/unsized7.rs:7:10 | LL | trait T1 { - | ^ required by this bound in `T1` + | ^ required by the implicit `Sized` requirement on this type parameter in `T1` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl T1 for S3 { diff --git a/tests/ui/variance/variance-regions-unused-direct.stderr b/tests/ui/variance/variance-regions-unused-direct.stderr index 1a600f5b0580f..4dc2af6ce2cc8 100644 --- a/tests/ui/variance/variance-regions-unused-direct.stderr +++ b/tests/ui/variance/variance-regions-unused-direct.stderr @@ -1,16 +1,16 @@ -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-regions-unused-direct.rs:5:18 | LL | struct Bivariant<'a>; - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'d` is never used +error[E0392]: lifetime parameter `'d` is never used --> $DIR/variance-regions-unused-direct.rs:7:19 | LL | struct Struct<'a, 'd> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'d`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/variance/variance-regions-unused-indirect.stderr b/tests/ui/variance/variance-regions-unused-indirect.stderr index 14fdd849294b1..ec4d480baab78 100644 --- a/tests/ui/variance/variance-regions-unused-indirect.stderr +++ b/tests/ui/variance/variance-regions-unused-indirect.stderr @@ -21,19 +21,19 @@ LL | enum Bar<'a> { LL ~ Bar1(Box>) | -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-regions-unused-indirect.rs:3:10 | LL | enum Foo<'a> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-regions-unused-indirect.rs:8:10 | LL | enum Bar<'a> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/variance/variance-unused-region-param.stderr b/tests/ui/variance/variance-unused-region-param.stderr index 7c7ec40ba35c3..b9c08bd43c454 100644 --- a/tests/ui/variance/variance-unused-region-param.stderr +++ b/tests/ui/variance/variance-unused-region-param.stderr @@ -1,16 +1,16 @@ -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-unused-region-param.rs:3:19 | LL | struct SomeStruct<'a> { x: u32 } - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/variance-unused-region-param.rs:4:15 | LL | enum SomeEnum<'a> { Nothing } - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr index e612da118f058..3011b7bd18fa7 100644 --- a/tests/ui/variance/variance-unused-type-param.stderr +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -1,51 +1,51 @@ -error[E0392]: parameter `A` is never used +error[E0392]: type parameter `A` is never used --> $DIR/variance-unused-type-param.rs:6:19 | LL | struct SomeStruct { x: u32 } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `A` to be a const parameter, use `const A: usize` instead + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead -error[E0392]: parameter `A` is never used +error[E0392]: type parameter `A` is never used --> $DIR/variance-unused-type-param.rs:9:15 | LL | enum SomeEnum { Nothing } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `A` to be a const parameter, use `const A: usize` instead + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:13:15 | LL | enum ListCell { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:19:19 | LL | struct WithBounds {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:22:24 | LL | struct WithWhereBounds where T: Sized {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/variance-unused-type-param.rs:25:27 | LL | struct WithOutlivesBounds {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/wf/hir-wf-canonicalized.rs b/tests/ui/wf/hir-wf-canonicalized.rs index bdb84409d009d..eac238f0fcab1 100644 --- a/tests/ui/wf/hir-wf-canonicalized.rs +++ b/tests/ui/wf/hir-wf-canonicalized.rs @@ -9,8 +9,8 @@ trait Callback: Fn(&Bar<'_, T>, &T::V) {} struct Bar<'a, T> { callback: Box>>>, //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied - //~| ERROR the trait bound `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied - //~| ERROR the size for values of type `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time + //~| ERROR the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied + //~| ERROR the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time } impl Bar<'_, Bar<'_, T>> {} diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr index 21122e37da53d..8938801ce3d97 100644 --- a/tests/ui/wf/hir-wf-canonicalized.stderr +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -10,11 +10,11 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the trait bound `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied +error[E0277]: the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box>>>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, Output = ()> + 'static)` | help: this trait has no implementations, consider adding one --> $DIR/hir-wf-canonicalized.rs:3:1 @@ -22,18 +22,18 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the size for values of type `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time +error[E0277]: the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` -note: required by a bound in `Bar` + = help: the trait `Sized` is not implemented for `(dyn Callback, Output = ()> + 'static)` +note: required by an implicit `Sized` bound in `Bar` --> $DIR/hir-wf-canonicalized.rs:9:16 | LL | struct Bar<'a, T> { - | ^ required by this bound in `Bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `Bar` help: consider relaxing the implicit `Sized` restriction | LL | struct Bar<'a, T: ?Sized> { diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.stderr index 4b696dc1d1dfe..93449d60e9d0d 100644 --- a/tests/ui/wf/hir-wf-check-erase-regions.stderr +++ b/tests/ui/wf/hir-wf-check-erase-regions.stderr @@ -4,7 +4,7 @@ error[E0277]: `&'a T` is not an iterator LL | type IntoIter = std::iter::Flatten>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator | - = help: the trait `Iterator` is not implemented for `&'a T` + = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `Flatten>: Iterator` = help: the trait `Iterator` is implemented for `&mut I` = note: required for `Flatten>` to implement `Iterator` note: required by a bound in `std::iter::IntoIterator::IntoIter` @@ -16,7 +16,7 @@ error[E0277]: `&'a T` is not an iterator LL | type IntoIter = std::iter::Flatten>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator | - = help: the trait `Iterator` is not implemented for `&'a T` + = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `&'a T: IntoIterator` = help: the trait `Iterator` is implemented for `&mut I` = note: required for `&'a T` to implement `IntoIterator` note: required by a bound in `Flatten` @@ -28,7 +28,7 @@ error[E0277]: `&'a T` is not an iterator LL | fn into_iter(self) -> Self::IntoIter { | ^^^^^^^^^^^^^^ `&'a T` is not an iterator | - = help: the trait `Iterator` is not implemented for `&'a T` + = help: the trait `Iterator` is not implemented for `&'a T`, which is required by `&'a T: IntoIterator` = help: the trait `Iterator` is implemented for `&mut I` = note: required for `&'a T` to implement `IntoIterator` note: required by a bound in `Flatten` diff --git a/tests/ui/wf/wf-const-type.stderr b/tests/ui/wf/wf-const-type.stderr index 039e907705ee6..d5e0f7672a6f3 100644 --- a/tests/ui/wf/wf-const-type.stderr +++ b/tests/ui/wf/wf-const-type.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-const-type.rs:10:12 | LL | const FOO: IsCopy> = IsCopy { t: None }; - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` @@ -20,7 +20,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-const-type.rs:10:50 | LL | const FOO: IsCopy> = IsCopy { t: None }; - | ^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr index cd6c051feedf5..40f2f45263930 100644 --- a/tests/ui/wf/wf-fn-where-clause.stderr +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -30,11 +30,11 @@ LL | fn bar() where Vec:, {} | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Copy + 'static)` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $DIR/wf-fn-where-clause.rs:16:12 | LL | struct Vec { - | ^ required by this bound in `Vec` + | ^ required by the implicit `Sized` requirement on this type parameter in `Vec` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/wf-fn-where-clause.rs:16:12 | diff --git a/tests/ui/wf/wf-impl-self-type.stderr b/tests/ui/wf/wf-impl-self-type.stderr index 86fe6df32bf21..6c3abd9f2816e 100644 --- a/tests/ui/wf/wf-impl-self-type.stderr +++ b/tests/ui/wf/wf-impl-self-type.stderr @@ -5,7 +5,7 @@ LL | impl Foo for Option<[u8]> {} | ^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `Option` +note: required by an implicit `Sized` bound in `Option` --> $SRC_DIR/core/src/option.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr index 65dae26014375..481173b8a269c 100644 --- a/tests/ui/wf/wf-static-type.stderr +++ b/tests/ui/wf/wf-static-type.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-static-type.rs:10:13 | LL | static FOO: IsCopy> = IsCopy { t: None }; - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` @@ -20,7 +20,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied --> $DIR/wf-static-type.rs:10:51 | LL | static FOO: IsCopy> = IsCopy { t: None }; - | ^^^^ the trait `Copy` is not implemented for `NotCopy` + | ^^^^ the trait `Copy` is not implemented for `NotCopy`, which is required by `Option: Copy` | = note: required for `Option` to implement `Copy` note: required by a bound in `IsCopy` diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr index 4c15497d5308e..6de4caa76ee0e 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied --> $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())` + | ^^^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())` | help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index 3318c70f1bb38..4cb3cdd69ad00 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for Foo` is not implemented for `fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` + | ^^^^^^^^ the trait `for Foo` is not implemented for `fn(&ReBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), 'b) }) ())` | help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 diff --git a/tests/ui/where-clauses/issue-50825-1.rs b/tests/ui/where-clauses/issue-50825-1.rs index ee4316029a829..2ee34ad714ede 100644 --- a/tests/ui/where-clauses/issue-50825-1.rs +++ b/tests/ui/where-clauses/issue-50825-1.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // regression test for issue #50825 // Make sure that the `impl` bound (): X is preferred over // the (): X bound in the where clause. diff --git a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs index ea60fa708764f..65fd2f3096c93 100644 --- a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs +++ b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Bound { diff --git a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs index 6fc570b9b5b9b..a7ce0590fcd46 100644 --- a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs +++ b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs @@ -3,7 +3,7 @@ // pretty-expanded FIXME #23616 -trait TheTrait { fn dummy(&self) { } } +trait TheTrait { fn dummy(&self) { } } //~ WARN method `dummy` is never used impl TheTrait for &'static isize { } diff --git a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr new file mode 100644 index 0000000000000..a9fe11ea6b316 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/where-clause-early-bound-lifetimes.rs:6:21 + | +LL | trait TheTrait { fn dummy(&self) { } } + | -------- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs index daa3c8dd8e367..8f9c6fbff3d8f 100644 --- a/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs +++ b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] // pretty-expanded FIXME #23616 -trait Foo { fn dummy(&self, arg: T) { } } +trait Foo { fn dummy(&self, arg: T) { } } //~ WARN method `dummy` is never used trait Bar { fn method(&self) where A: Foo; diff --git a/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr b/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr new file mode 100644 index 0000000000000..0d09cb9de3f6b --- /dev/null +++ b/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/where-clause-method-substituion-rpass.rs:5:19 + | +LL | trait Foo { fn dummy(&self, arg: T) { } } + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed index 2f47c0d91fa96..4e1aa59aac0f0 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed @@ -1,6 +1,8 @@ // check-pass // run-rustfix +#![allow(dead_code)] + trait Trait { // Fine. type Assoc where u32: Copy; diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs index b20aa9398b58f..05b2f8c82a456 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs @@ -1,6 +1,8 @@ // check-pass // run-rustfix +#![allow(dead_code)] + trait Trait { // Fine. type Assoc where u32: Copy; diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr index b4de051845fa6..6ff9d2dd73b5b 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr @@ -1,5 +1,5 @@ warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:13:16 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:15:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:16:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:18:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL + type Assoc2 = () where i32: Copy, u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:24:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:26:17 | LL | type Assoc2 where u32: Copy, i32: Copy = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed index d171eba50b788..940e2cc8e9750 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![allow(dead_code)] #![feature(associated_type_defaults)] trait Trait { diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs index 59afee65794c4..7001a9245a5f3 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![allow(dead_code)] #![feature(associated_type_defaults)] trait Trait { diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr index a81cb8c8cd62e..9e9967ef7391a 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr @@ -1,5 +1,5 @@ warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-trait.rs:8:16 + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:9:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-trait.rs:11:17 + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:12:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ diff --git a/triagebot.toml b/triagebot.toml index bf898819cfc16..ef3f3693e6174 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -652,12 +652,12 @@ compiler-team = [ "@davidtwco", "@estebank", "@oli-obk", + "@pnkfelix", "@wesleywiser", "@michaelwoerister", ] compiler-team-contributors = [ "@TaKO8Ki", - "@b-naber", "@nnethercote", "@fmease", ] @@ -669,7 +669,6 @@ libs = [ "@cuviper", "@joshtriplett", "@Mark-Simulacrum", - "@m-ou-se", ] bootstrap = [ "@Mark-Simulacrum",

` to implement `for<'b> Wrap<'b>` --> $DIR/issue-22872.rs:7:13 | diff --git a/tests/ui/issues/issue-23281.stderr b/tests/ui/issues/issue-23281.stderr index e1f4e8a96c825..ee079f2deeca3 100644 --- a/tests/ui/issues/issue-23281.stderr +++ b/tests/ui/issues/issue-23281.stderr @@ -5,11 +5,11 @@ LL | pub fn function(funs: Vec ()>) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Fn() + 'static)` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $DIR/issue-23281.rs:8:12 | LL | struct Vec { - | ^ required by this bound in `Vec` + | ^ required by the implicit `Sized` requirement on this type parameter in `Vec` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-23281.rs:8:12 | diff --git a/tests/ui/issues/issue-23485.rs b/tests/ui/issues/issue-23485.rs index 1dd3d9293bcc6..07ed0f1b00df8 100644 --- a/tests/ui/issues/issue-23485.rs +++ b/tests/ui/issues/issue-23485.rs @@ -17,7 +17,7 @@ trait Iterator { fn next(&mut self) -> Option; - fn clone_first(mut self) -> Option<::Target> where + fn clone_first(mut self) -> Option<::Target> where //~ WARN method `clone_first` is never used Self: Sized, Self::Item: Deref, ::Target: Clone, diff --git a/tests/ui/issues/issue-23485.stderr b/tests/ui/issues/issue-23485.stderr new file mode 100644 index 0000000000000..ed2d2400d0d93 --- /dev/null +++ b/tests/ui/issues/issue-23485.stderr @@ -0,0 +1,13 @@ +warning: method `clone_first` is never used + --> $DIR/issue-23485.rs:20:8 + | +LL | trait Iterator { + | -------- method in this trait +... +LL | fn clone_first(mut self) -> Option<::Target> where + | ^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-2848.rs b/tests/ui/issues/issue-2848.rs index e0049bf8fbb00..34181acdd0556 100644 --- a/tests/ui/issues/issue-2848.rs +++ b/tests/ui/issues/issue-2848.rs @@ -12,6 +12,7 @@ fn main() { use bar::foo::{alpha, charlie}; match alpha { alpha | beta => {} //~ ERROR variable `beta` is not bound in all patterns + //~^ ERROR: `beta` is named the same as one of the variants charlie => {} } } diff --git a/tests/ui/issues/issue-2848.stderr b/tests/ui/issues/issue-2848.stderr index 873f7efcd73f3..1cef27c34635e 100644 --- a/tests/ui/issues/issue-2848.stderr +++ b/tests/ui/issues/issue-2848.stderr @@ -6,6 +6,15 @@ LL | alpha | beta => {} | | | pattern doesn't bind `beta` -error: aborting due to 1 previous error +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `bar::foo` + --> $DIR/issue-2848.rs:14:15 + | +LL | alpha | beta => {} + | ^^^^ help: to match on the variant, qualify the path: `bar::foo::beta` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0170, E0408. +For more information about an error, try `rustc --explain E0170`. diff --git a/tests/ui/issues/issue-28971.rs b/tests/ui/issues/issue-28971.rs index f0a1e2d006179..8e7a2fe0ef209 100644 --- a/tests/ui/issues/issue-28971.rs +++ b/tests/ui/issues/issue-28971.rs @@ -13,4 +13,5 @@ fn main(){ fn foo(f: F) where F: FnMut() { f(); + //~^ ERROR: cannot borrow } diff --git a/tests/ui/issues/issue-28971.stderr b/tests/ui/issues/issue-28971.stderr index 8fd3c7ffc3035..26057cbc2d1d8 100644 --- a/tests/ui/issues/issue-28971.stderr +++ b/tests/ui/issues/issue-28971.stderr @@ -10,6 +10,18 @@ LL | Foo::Baz(..) => (), | variant or associated item not found in `Foo` | help: there is a variant with a similar name: `Bar` -error: aborting due to 1 previous error +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/issue-28971.rs:15:5 + | +LL | f(); + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo(mut f: F) where F: FnMut() { + | +++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. +Some errors have detailed explanations: E0596, E0599. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-2989.rs b/tests/ui/issues/issue-2989.rs index c0b67374370e7..a95867514073c 100644 --- a/tests/ui/issues/issue-2989.rs +++ b/tests/ui/issues/issue-2989.rs @@ -1,8 +1,8 @@ // run-pass #![allow(non_camel_case_types)] -trait methods { - fn to_bytes(&self) -> Vec ; +trait methods { //~ WARN trait `methods` is never used + fn to_bytes(&self) -> Vec; } impl methods for () { diff --git a/tests/ui/issues/issue-2989.stderr b/tests/ui/issues/issue-2989.stderr new file mode 100644 index 0000000000000..57181607cecd3 --- /dev/null +++ b/tests/ui/issues/issue-2989.stderr @@ -0,0 +1,10 @@ +warning: trait `methods` is never used + --> $DIR/issue-2989.rs:4:7 + | +LL | trait methods { + | ^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-30236.rs b/tests/ui/issues/issue-30236.rs index 9c2d855076d79..08d08a544021e 100644 --- a/tests/ui/issues/issue-30236.rs +++ b/tests/ui/issues/issue-30236.rs @@ -1,5 +1,5 @@ type Foo< - Unused //~ ERROR type parameter `Unused` is unused + Unused //~ ERROR type parameter `Unused` is never used > = u8; fn main() { diff --git a/tests/ui/issues/issue-30236.stderr b/tests/ui/issues/issue-30236.stderr index 0f69f49f505a0..bfe374a653f5f 100644 --- a/tests/ui/issues/issue-30236.stderr +++ b/tests/ui/issues/issue-30236.stderr @@ -1,8 +1,11 @@ -error[E0091]: type parameter `Unused` is unused +error[E0091]: type parameter `Unused` is never used --> $DIR/issue-30236.rs:2:5 | LL | Unused | ^^^^^^ unused type parameter + | + = help: consider removing `Unused` or referring to it in the body of the type alias + = help: if you intended `Unused` to be a const parameter, use `const Unused: /* Type */` instead error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-31910.stderr b/tests/ui/issues/issue-31910.stderr index 89a6d5574a1e5..ca2d2f619e62e 100644 --- a/tests/ui/issues/issue-31910.stderr +++ b/tests/ui/issues/issue-31910.stderr @@ -4,11 +4,11 @@ error[E0308]: mismatched types LL | X = Trait::Number, | ^^^^^^^^^^^^^ expected `isize`, found `i32` -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-31910.rs:1:11 | LL | enum Enum { - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/issues/issue-34074.rs b/tests/ui/issues/issue-34074.rs index 0600d3937c16e..ca7d7b49a042f 100644 --- a/tests/ui/issues/issue-34074.rs +++ b/tests/ui/issues/issue-34074.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Make sure several unnamed function parameters don't conflict with each other trait Tr { diff --git a/tests/ui/issues/issue-34373.stderr b/tests/ui/issues/issue-34373.stderr index 1a1cfc925b779..13667cd920e9b 100644 --- a/tests/ui/issues/issue-34373.stderr +++ b/tests/ui/issues/issue-34373.stderr @@ -45,14 +45,14 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo(_: T) where Self: Sized {} | +++++++++++++++++ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-34373.rs:7:16 | LL | pub struct Foo>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unused parameter + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-34503.rs b/tests/ui/issues/issue-34503.rs index 26e7358408f48..d2c95d990ecde 100644 --- a/tests/ui/issues/issue-34503.rs +++ b/tests/ui/issues/issue-34503.rs @@ -2,7 +2,7 @@ fn main() { struct X; trait Foo { - fn foo(&self) where (T, Option): Ord {} + fn foo(&self) where (T, Option): Ord {} //~ WARN methods `foo` and `bar` are never used fn bar(&self, x: &Option) -> bool where Option: Ord { *x < *x } } diff --git a/tests/ui/issues/issue-34503.stderr b/tests/ui/issues/issue-34503.stderr new file mode 100644 index 0000000000000..60d8d76a61965 --- /dev/null +++ b/tests/ui/issues/issue-34503.stderr @@ -0,0 +1,14 @@ +warning: methods `foo` and `bar` are never used + --> $DIR/issue-34503.rs:5:12 + | +LL | trait Foo { + | --- methods in this trait +LL | fn foo(&self) where (T, Option): Ord {} + | ^^^ +LL | fn bar(&self, x: &Option) -> bool + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-3563-3.rs b/tests/ui/issues/issue-3563-3.rs index bedfdab97d58b..6346b82167cb8 100644 --- a/tests/ui/issues/issue-3563-3.rs +++ b/tests/ui/issues/issue-3563-3.rs @@ -112,7 +112,7 @@ trait Canvas { // Unlike interfaces traits support default implementations. // Got an ICE as soon as I added this method. - fn add_points(&mut self, shapes: &[Point]) { + fn add_points(&mut self, shapes: &[Point]) { //~ WARN method `add_points` is never used for pt in shapes {self.add_point(*pt)}; } } diff --git a/tests/ui/issues/issue-3563-3.stderr b/tests/ui/issues/issue-3563-3.stderr new file mode 100644 index 0000000000000..bd65c1e3fd5b4 --- /dev/null +++ b/tests/ui/issues/issue-3563-3.stderr @@ -0,0 +1,13 @@ +warning: method `add_points` is never used + --> $DIR/issue-3563-3.rs:115:8 + | +LL | trait Canvas { + | ------ method in this trait +... +LL | fn add_points(&mut self, shapes: &[Point]) { + | ^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-36299.stderr b/tests/ui/issues/issue-36299.stderr index dc24fb353f408..29e8d7ca59a24 100644 --- a/tests/ui/issues/issue-36299.stderr +++ b/tests/ui/issues/issue-36299.stderr @@ -1,19 +1,19 @@ -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-36299.rs:1:12 | LL | struct Foo<'a, A> {} - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `A` is never used +error[E0392]: type parameter `A` is never used --> $DIR/issue-36299.rs:1:16 | LL | struct Foo<'a, A> {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `A` to be a const parameter, use `const A: usize` instead + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr index 03fea2c16486d..a687e733d3dae 100644 --- a/tests/ui/issues/issue-37534.stderr +++ b/tests/ui/issues/issue-37534.stderr @@ -15,11 +15,11 @@ warning: relaxing a default bound only does something for `?Sized`; all other tr LL | struct Foo {} | ^^^^^ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/issue-37534.rs:1:12 | LL | struct Foo {} - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/issues/issue-3878.rs b/tests/ui/issues/issue-3878.rs deleted file mode 100644 index 6de3405af0d95..0000000000000 --- a/tests/ui/issues/issue-3878.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![allow(path_statements)] - -pub fn main() { - let y: Box<_> = Box::new(1); - y; -} diff --git a/tests/ui/issues/issue-40827.stderr b/tests/ui/issues/issue-40827.stderr index 7f5c578ae4fff..44ae90cbc0ff8 100644 --- a/tests/ui/issues/issue-40827.stderr +++ b/tests/ui/issues/issue-40827.stderr @@ -6,7 +6,7 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | | | required by a bound introduced by this call | - = help: within `Bar`, the trait `Sync` is not implemented for `Rc` + = help: within `Bar`, the trait `Sync` is not implemented for `Rc`, which is required by `Foo: Send` note: required because it appears within the type `Bar` --> $DIR/issue-40827.rs:6:6 | @@ -32,7 +32,7 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | | | required by a bound introduced by this call | - = help: within `Bar`, the trait `Send` is not implemented for `Rc` + = help: within `Bar`, the trait `Send` is not implemented for `Rc`, which is required by `Foo: Send` note: required because it appears within the type `Bar` --> $DIR/issue-40827.rs:6:6 | diff --git a/tests/ui/issues/issue-50571.fixed b/tests/ui/issues/issue-50571.fixed index 2f8c925b85328..13c830cd0d4b1 100644 --- a/tests/ui/issues/issue-50571.fixed +++ b/tests/ui/issues/issue-50571.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn foo(_: [i32; 2]) {} //~^ ERROR: patterns aren't allowed in methods without bodies diff --git a/tests/ui/issues/issue-50571.rs b/tests/ui/issues/issue-50571.rs index 56f422e7d5838..6fe13e3f707db 100644 --- a/tests/ui/issues/issue-50571.rs +++ b/tests/ui/issues/issue-50571.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn foo([a, b]: [i32; 2]) {} //~^ ERROR: patterns aren't allowed in methods without bodies diff --git a/tests/ui/issues/issue-50571.stderr b/tests/ui/issues/issue-50571.stderr index fe47790f1ddfb..12256ded1c0a8 100644 --- a/tests/ui/issues/issue-50571.stderr +++ b/tests/ui/issues/issue-50571.stderr @@ -1,5 +1,5 @@ error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/issue-50571.rs:4:12 + --> $DIR/issue-50571.rs:5:12 | LL | fn foo([a, b]: [i32; 2]) {} | ^^^^^^ diff --git a/tests/ui/issues/issue-56199.stderr b/tests/ui/issues/issue-56199.stderr index 7aaf8e4ac2f14..eb6d7005979f6 100644 --- a/tests/ui/issues/issue-56199.stderr +++ b/tests/ui/issues/issue-56199.stderr @@ -10,7 +10,7 @@ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:8:17 | LL | let _ = Self(); - | ^^^^ + | ^^^^^^ | = help: did you mean to use one of the enum's variants? @@ -24,7 +24,7 @@ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/issue-56199.rs:17:17 | LL | let _ = Self(); - | ^^^^ help: use curly brackets: `Self { /* fields */ }` + | ^^^^^^ help: use curly brackets: `Self { /* fields */ }` error: aborting due to 4 previous errors diff --git a/tests/ui/issues/issue-67535.rs b/tests/ui/issues/issue-67535.rs index 24f50621310f1..153b95a167434 100644 --- a/tests/ui/issues/issue-67535.rs +++ b/tests/ui/issues/issue-67535.rs @@ -2,21 +2,21 @@ 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: ()) -> () { + fn add_assign(&self, other: ()) -> () { //~ ERROR incompatible type () } } 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] { + fn add_assign(&self, other: [(); 1]) -> [(); 1] { //~ ERROR incompatible type [()] } } 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] { + fn add_assign(&self, other: &[u8]) -> &[u8] { //~ ERROR incompatible type self } } diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr index 4d7a02a50969f..c8bde2cb88c77 100644 --- a/tests/ui/issues/issue-67535.stderr +++ b/tests/ui/issues/issue-67535.stderr @@ -34,6 +34,43 @@ LL | impl std::ops::AddAssign for &[u8] { | = note: define and implement a trait or new type instead -error: aborting due to 3 previous errors +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:5:19 + | +LL | fn add_assign(&self, other: ()) -> () { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut (), ())` + found signature `fn(&(), ())` + +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:12:19 + | +LL | fn add_assign(&self, other: [(); 1]) -> [(); 1] { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut _, _)` + found signature `fn(&_, _) -> [(); 1]` + +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:19:19 + | +LL | fn add_assign(&self, other: &[u8]) -> &[u8] { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut &_, &_)` + found signature `fn(&&_, &_) -> &[u8]` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0053, E0117. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr index 7371e2105de8d..15cb2d875c13c 100644 --- a/tests/ui/issues/issue-7364.stderr +++ b/tests/ui/issues/issue-7364.stderr @@ -4,7 +4,7 @@ error[E0277]: `RefCell` cannot be shared between threads safely LL | static boxed: Box> = Box::new(RefCell::new(0)); | ^^^^^^^^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `RefCell` + = help: the trait `Sync` is not implemented for `RefCell`, which is required by `Box>: Sync` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead = note: required for `Unique>` to implement `Sync` note: required because it appears within the type `Box>` diff --git a/tests/ui/issues/issue-7575.rs b/tests/ui/issues/issue-7575.rs index ac69f2b1c80b6..0074f660c4ef0 100644 --- a/tests/ui/issues/issue-7575.rs +++ b/tests/ui/issues/issue-7575.rs @@ -1,6 +1,6 @@ // run-pass -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn new() -> bool { false } fn dummy(&self) { } } diff --git a/tests/ui/issues/issue-7575.stderr b/tests/ui/issues/issue-7575.stderr new file mode 100644 index 0000000000000..2f987d19c80ce --- /dev/null +++ b/tests/ui/issues/issue-7575.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/issue-7575.rs:3:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-7911.rs b/tests/ui/issues/issue-7911.rs index d4db3b0776bca..114574b9009d8 100644 --- a/tests/ui/issues/issue-7911.rs +++ b/tests/ui/issues/issue-7911.rs @@ -4,7 +4,7 @@ #![allow(unused_variables)] // unused foobar_immut + foobar_mut trait FooBar { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } struct Bar(#[allow(dead_code)] i32); struct Foo { bar: Bar } diff --git a/tests/ui/issues/issue-7911.stderr b/tests/ui/issues/issue-7911.stderr new file mode 100644 index 0000000000000..ead7ee191ac9b --- /dev/null +++ b/tests/ui/issues/issue-7911.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-7911.rs:7:8 + | +LL | trait FooBar { + | ------ method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-8248.rs b/tests/ui/issues/issue-8248.rs index 31a305c31bee2..94b1a5203b47e 100644 --- a/tests/ui/issues/issue-8248.rs +++ b/tests/ui/issues/issue-8248.rs @@ -2,7 +2,7 @@ // pretty-expanded FIXME #23616 trait A { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } struct B; impl A for B {} diff --git a/tests/ui/issues/issue-8248.stderr b/tests/ui/issues/issue-8248.stderr new file mode 100644 index 0000000000000..a0098bcb771ae --- /dev/null +++ b/tests/ui/issues/issue-8248.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-8248.rs:5:8 + | +LL | trait A { + | - method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr index d81bc3615575e..34433eef5c70b 100644 --- a/tests/ui/issues/issue-87199.stderr +++ b/tests/ui/issues/issue-87199.stderr @@ -23,11 +23,11 @@ LL | ref_arg::<[i32]>(&[5]); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` -note: required by a bound in `ref_arg` +note: required by an implicit `Sized` bound in `ref_arg` --> $DIR/issue-87199.rs:10:12 | LL | fn ref_arg(_: &T) {} - | ^ required by this bound in `ref_arg` + | ^ required by the implicit `Sized` requirement on this type parameter in `ref_arg` help: consider relaxing the implicit `Sized` restriction | LL | fn ref_arg(_: &T) {} diff --git a/tests/ui/issues/issue-9951.rs b/tests/ui/issues/issue-9951.rs index 2698a3b17c6c2..5db3f74efaa3e 100644 --- a/tests/ui/issues/issue-9951.rs +++ b/tests/ui/issues/issue-9951.rs @@ -4,7 +4,7 @@ #![allow(unused_variables)] trait Bar { - fn noop(&self); + fn noop(&self); //~ WARN method `noop` is never used } impl Bar for u8 { fn noop(&self) {} diff --git a/tests/ui/issues/issue-9951.stderr b/tests/ui/issues/issue-9951.stderr new file mode 100644 index 0000000000000..475f2817914d3 --- /dev/null +++ b/tests/ui/issues/issue-9951.stderr @@ -0,0 +1,12 @@ +warning: method `noop` is never used + --> $DIR/issue-9951.rs:7:6 + | +LL | trait Bar { + | --- method in this trait +LL | fn noop(&self); + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs index 045d40a6f71ae..120e56a6549e4 100644 --- a/tests/ui/iterators/collect-into-slice.rs +++ b/tests/ui/iterators/collect-into-slice.rs @@ -8,7 +8,7 @@ fn main() { //~| ERROR the size for values of type `[i32]` cannot be known at compilation time //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size //~| NOTE try explicitly collecting into a `Vec<{integer}>` - //~| NOTE required by a bound in `collect` + //~| NOTE required by an implicit `Sized` bound in `collect` //~| NOTE required by a bound in `collect` //~| NOTE all local variables must have a statically known size //~| NOTE doesn't have a size known at compile-time diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr index 45685ef0ce9cd..56f1bf770607e 100644 --- a/tests/ui/iterators/collect-into-slice.stderr +++ b/tests/ui/iterators/collect-into-slice.stderr @@ -25,7 +25,7 @@ LL | let some_generated_vec = (0..10).collect(); | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` -note: required by a bound in `collect` +note: required by an implicit `Sized` bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere diff --git a/tests/ui/iterators/float_iterator_hint.stderr b/tests/ui/iterators/float_iterator_hint.stderr index c3cb00c3c684c..29319b9400f03 100644 --- a/tests/ui/iterators/float_iterator_hint.stderr +++ b/tests/ui/iterators/float_iterator_hint.stderr @@ -4,7 +4,7 @@ error[E0277]: `{float}` is not an iterator LL | for i in 0.2 { | ^^^ `{float}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{float}` + = help: the trait `Iterator` is not implemented for `{float}`, which is required by `{float}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{float}` to implement `IntoIterator` diff --git a/tests/ui/iterators/integral.stderr b/tests/ui/iterators/integral.stderr index c142fec8da0f6..74bbe28d6b719 100644 --- a/tests/ui/iterators/integral.stderr +++ b/tests/ui/iterators/integral.stderr @@ -4,7 +4,7 @@ error[E0277]: `{integer}` is not an iterator LL | for _ in 42 {} | ^^ `{integer}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{integer}` + = help: the trait `Iterator` is not implemented for `{integer}`, which is required by `{integer}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{integer}` to implement `IntoIterator` @@ -14,7 +14,7 @@ error[E0277]: `u8` is not an iterator LL | for _ in 42 as u8 {} | ^^^^^^^^ `u8` is not an iterator | - = help: the trait `Iterator` is not implemented for `u8` + = help: the trait `Iterator` is not implemented for `u8`, which is required by `u8: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u8` to implement `IntoIterator` @@ -24,7 +24,7 @@ error[E0277]: `i8` is not an iterator LL | for _ in 42 as i8 {} | ^^^^^^^^ `i8` is not an iterator | - = help: the trait `Iterator` is not implemented for `i8` + = help: the trait `Iterator` is not implemented for `i8`, which is required by `i8: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i8` to implement `IntoIterator` @@ -34,7 +34,7 @@ error[E0277]: `u16` is not an iterator LL | for _ in 42 as u16 {} | ^^^^^^^^^ `u16` is not an iterator | - = help: the trait `Iterator` is not implemented for `u16` + = help: the trait `Iterator` is not implemented for `u16`, which is required by `u16: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u16` to implement `IntoIterator` @@ -44,7 +44,7 @@ error[E0277]: `i16` is not an iterator LL | for _ in 42 as i16 {} | ^^^^^^^^^ `i16` is not an iterator | - = help: the trait `Iterator` is not implemented for `i16` + = help: the trait `Iterator` is not implemented for `i16`, which is required by `i16: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i16` to implement `IntoIterator` @@ -54,7 +54,7 @@ error[E0277]: `u32` is not an iterator LL | for _ in 42 as u32 {} | ^^^^^^^^^ `u32` is not an iterator | - = help: the trait `Iterator` is not implemented for `u32` + = help: the trait `Iterator` is not implemented for `u32`, which is required by `u32: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u32` to implement `IntoIterator` @@ -64,7 +64,7 @@ error[E0277]: `i32` is not an iterator LL | for _ in 42 as i32 {} | ^^^^^^^^^ `i32` is not an iterator | - = help: the trait `Iterator` is not implemented for `i32` + = help: the trait `Iterator` is not implemented for `i32`, which is required by `i32: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i32` to implement `IntoIterator` @@ -74,7 +74,7 @@ error[E0277]: `u64` is not an iterator LL | for _ in 42 as u64 {} | ^^^^^^^^^ `u64` is not an iterator | - = help: the trait `Iterator` is not implemented for `u64` + = help: the trait `Iterator` is not implemented for `u64`, which is required by `u64: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `u64` to implement `IntoIterator` @@ -84,7 +84,7 @@ error[E0277]: `i64` is not an iterator LL | for _ in 42 as i64 {} | ^^^^^^^^^ `i64` is not an iterator | - = help: the trait `Iterator` is not implemented for `i64` + = help: the trait `Iterator` is not implemented for `i64`, which is required by `i64: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `i64` to implement `IntoIterator` @@ -94,7 +94,7 @@ error[E0277]: `usize` is not an iterator LL | for _ in 42 as usize {} | ^^^^^^^^^^^ `usize` is not an iterator | - = help: the trait `Iterator` is not implemented for `usize` + = help: the trait `Iterator` is not implemented for `usize`, which is required by `usize: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `usize` to implement `IntoIterator` @@ -104,7 +104,7 @@ error[E0277]: `isize` is not an iterator LL | for _ in 42 as isize {} | ^^^^^^^^^^^ `isize` is not an iterator | - = help: the trait `Iterator` is not implemented for `isize` + = help: the trait `Iterator` is not implemented for `isize`, which is required by `isize: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `isize` to implement `IntoIterator` @@ -114,7 +114,7 @@ error[E0277]: `{float}` is not an iterator LL | for _ in 42.0 {} | ^^^^ `{float}` is not an iterator | - = help: the trait `Iterator` is not implemented for `{float}` + = help: the trait `Iterator` is not implemented for `{float}`, which is required by `{float}: IntoIterator` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` = note: required for `{float}` to implement `IntoIterator` diff --git a/tests/ui/iterators/issue-28098.rs b/tests/ui/iterators/issue-28098.rs index 80c77edae9eb1..62a90d90d12de 100644 --- a/tests/ui/iterators/issue-28098.rs +++ b/tests/ui/iterators/issue-28098.rs @@ -2,14 +2,12 @@ fn main() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator //~| ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator other() } @@ -20,11 +18,9 @@ pub fn other() { let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator //~| ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator let _ = Iterator::next(&mut ()); //~^ ERROR `()` is not an iterator - //~| ERROR `()` is not an iterator for _ in false {} //~^ ERROR `bool` is not an iterator diff --git a/tests/ui/iterators/issue-28098.stderr b/tests/ui/iterators/issue-28098.stderr index 3256e57d4361b..3cb1b2f72700c 100644 --- a/tests/ui/iterators/issue-28098.stderr +++ b/tests/ui/iterators/issue-28098.stderr @@ -8,25 +8,17 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:2:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:7:14 + --> $DIR/issue-28098.rs:6:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator | - = help: the trait `Iterator` is not implemented for `bool` + = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator` = note: required for `bool` to implement `IntoIterator` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:10:28 + --> $DIR/issue-28098.rs:9:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -35,24 +27,16 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:10:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - error[E0277]: `()` is not an iterator --> $DIR/issue-28098.rs:2:13 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:20:28 + --> $DIR/issue-28098.rs:18:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -62,15 +46,7 @@ LL | let _ = Iterator::next(&mut ()); = help: the trait `Iterator` is not implemented for `()` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:20:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:25:28 + --> $DIR/issue-28098.rs:22:28 | LL | let _ = Iterator::next(&mut ()); | -------------- ^^^^^^^ `()` is not an iterator @@ -79,31 +55,23 @@ LL | let _ = Iterator::next(&mut ()); | = help: the trait `Iterator` is not implemented for `()` -error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:25:13 - | -LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator - | - = help: the trait `Iterator` is not implemented for `()` - error[E0277]: `bool` is not an iterator - --> $DIR/issue-28098.rs:29:14 + --> $DIR/issue-28098.rs:25:14 | LL | for _ in false {} | ^^^^^ `bool` is not an iterator | - = help: the trait `Iterator` is not implemented for `bool` + = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator` = note: required for `bool` to implement `IntoIterator` error[E0277]: `()` is not an iterator - --> $DIR/issue-28098.rs:20:13 + --> $DIR/issue-28098.rs:18:13 | LL | let _ = Iterator::next(&mut ()); - | ^^^^^^^^^^^^^^ `()` is not an iterator + | ^^^^^^^^^^^^^^^^^^^^^^^ `()` is not an iterator | = help: the trait `Iterator` is not implemented for `()` -error: aborting due to 12 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/iterators/ranges.stderr b/tests/ui/iterators/ranges.stderr index b9fbcd5304b1f..a5d43ecbb6331 100644 --- a/tests/ui/iterators/ranges.stderr +++ b/tests/ui/iterators/ranges.stderr @@ -4,7 +4,7 @@ error[E0277]: `RangeTo<{integer}>` is not an iterator LL | for _ in ..10 {} | ^^^^ if you meant to iterate until a value, add a starting value | - = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>` + = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`, which is required by `RangeTo<{integer}>: IntoIterator` = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end` = note: required for `RangeTo<{integer}>` to implement `IntoIterator` @@ -14,7 +14,7 @@ error[E0277]: `RangeToInclusive<{integer}>` is not an iterator LL | for _ in ..=10 {} | ^^^^^ if you meant to iterate until a value (including it), add a starting value | - = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>` + = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`, which is required by `RangeToInclusive<{integer}>: IntoIterator` = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end` = note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator` diff --git a/tests/ui/iterators/string.stderr b/tests/ui/iterators/string.stderr index ddfe0169b848f..29f560677c07d 100644 --- a/tests/ui/iterators/string.stderr +++ b/tests/ui/iterators/string.stderr @@ -4,7 +4,7 @@ error[E0277]: `String` is not an iterator LL | for _ in "".to_owned() {} | ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()` | - = help: the trait `Iterator` is not implemented for `String` + = help: the trait `Iterator` is not implemented for `String`, which is required by `String: IntoIterator` = note: required for `String` to implement `IntoIterator` error[E0277]: `&str` is not an iterator @@ -13,7 +13,7 @@ error[E0277]: `&str` is not an iterator LL | for _ in "" {} | ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()` | - = help: the trait `Iterator` is not implemented for `&str` + = help: the trait `Iterator` is not implemented for `&str`, which is required by `&str: IntoIterator` = note: required for `&str` to implement `IntoIterator` error: aborting due to 2 previous errors diff --git a/tests/ui/kindck/kindck-impl-type-params-2.stderr b/tests/ui/kindck/kindck-impl-type-params-2.stderr index a51232090adbb..46c0bda95352f 100644 --- a/tests/ui/kindck/kindck-impl-type-params-2.stderr +++ b/tests/ui/kindck/kindck-impl-type-params-2.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied --> $DIR/kindck-impl-type-params-2.rs:13:16 | LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` | | | required by a bound introduced by this call | diff --git a/tests/ui/kindck/kindck-impl-type-params.rs b/tests/ui/kindck/kindck-impl-type-params.rs index 72a6599c32696..707c5dbaec30e 100644 --- a/tests/ui/kindck/kindck-impl-type-params.rs +++ b/tests/ui/kindck/kindck-impl-type-params.rs @@ -28,6 +28,7 @@ fn g(val: T) { fn foo<'a>() { let t: S<&'a isize> = S(marker::PhantomData); let a = &t as &dyn Gettable<&'a isize>; + //~^ ERROR: lifetime may not live long enough } fn foo2<'a>() { diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index 53c1940491f84..aad020e4ec97a 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -21,7 +21,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:16:13 | LL | let a = &t as &dyn Gettable; - | ^^ the trait `Copy` is not implemented for `T` + | ^^ the trait `Copy` is not implemented for `T`, which is required by `S: Gettable` | note: required for `S` to implement `Gettable` --> $DIR/kindck-impl-type-params.rs:12:32 @@ -59,7 +59,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:23:31 | LL | let a: &dyn Gettable = &t; - | ^^ the trait `Copy` is not implemented for `T` + | ^^ the trait `Copy` is not implemented for `T`, which is required by `S: Gettable` | note: required for `S` to implement `Gettable` --> $DIR/kindck-impl-type-params.rs:12:32 @@ -75,10 +75,10 @@ LL | fn g(val: T) { | +++++++++++++++++++ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/kindck-impl-type-params.rs:35:13 + --> $DIR/kindck-impl-type-params.rs:36:13 | LL | let a = t as Box>; - | ^ the trait `Copy` is not implemented for `String` + | ^ the trait `Copy` is not implemented for `String`, which is required by `S: Gettable` | = help: the trait `Gettable` is implemented for `S` note: required for `S` to implement `Gettable` @@ -91,10 +91,10 @@ LL | impl Gettable for S {} = note: required for the cast from `Box>` to `Box>` error[E0277]: the trait bound `Foo: Copy` is not satisfied - --> $DIR/kindck-impl-type-params.rs:43:37 + --> $DIR/kindck-impl-type-params.rs:44:37 | LL | let a: Box> = t; - | ^ the trait `Copy` is not implemented for `Foo` + | ^ the trait `Copy` is not implemented for `Foo`, which is required by `S: Gettable` | = help: the trait `Gettable` is implemented for `S` note: required for `S` to implement `Gettable` @@ -111,6 +111,15 @@ LL + #[derive(Copy)] LL | struct Foo; // does not impl Copy | -error: aborting due to 6 previous errors +error: lifetime may not live long enough + --> $DIR/kindck-impl-type-params.rs:30:13 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let t: S<&'a isize> = S(marker::PhantomData); +LL | let a = &t as &dyn Gettable<&'a isize>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr index 2949517655640..a85815d8cc498 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` | | | required by a bound introduced by this call | diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr index 3e164ebf51439..687660fe7eea3 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied --> $DIR/kindck-inherited-copy-bound.rs:21:16 | LL | take_param(&x); - | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>` + | ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`, which is required by `Box<{integer}>: Foo` | | | required by a bound introduced by this call | diff --git a/tests/ui/kindck/kindck-nonsendable-1.stderr b/tests/ui/kindck/kindck-nonsendable-1.stderr index 8bb784d1d4966..8cc931bc48ed3 100644 --- a/tests/ui/kindck/kindck-nonsendable-1.stderr +++ b/tests/ui/kindck/kindck-nonsendable-1.stderr @@ -8,7 +8,7 @@ LL | bar(move|| foo(x)); | | within this `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}` | required by a bound introduced by this call | - = help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc` + = help: within `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}`, the trait `Send` is not implemented for `Rc`, which is required by `{closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15}: Send` note: required because it's used within this closure --> $DIR/kindck-nonsendable-1.rs:9:9 | diff --git a/tests/ui/kindck/kindck-send-object.stderr b/tests/ui/kindck/kindck-send-object.stderr index 284d5dcec3107..0fc9cb14c7d46 100644 --- a/tests/ui/kindck/kindck-send-object.stderr +++ b/tests/ui/kindck/kindck-send-object.stderr @@ -4,7 +4,7 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely LL | assert_send::<&'static (dyn Dummy + 'static)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object.rs:5:18 @@ -18,7 +18,7 @@ error[E0277]: `dyn Dummy` cannot be sent between threads safely LL | assert_send::>(); | ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `dyn Dummy` + = help: the trait `Send` is not implemented for `dyn Dummy`, which is required by `Box: Send` = note: required for `Unique` to implement `Send` note: required because it appears within the type `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/kindck/kindck-send-object1.rs b/tests/ui/kindck/kindck-send-object1.rs index 787d0f8f6cbfb..0ce3995dccc9a 100644 --- a/tests/ui/kindck/kindck-send-object1.rs +++ b/tests/ui/kindck/kindck-send-object1.rs @@ -12,6 +12,7 @@ fn test51<'a>() { } fn test52<'a>() { assert_send::<&'a (dyn Dummy + Sync)>(); + //~^ ERROR: lifetime may not live long enough } // ...unless they are properly bounded diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index c0d516e3f626b..39343b9993b5a 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -4,7 +4,7 @@ error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely LL | assert_send::<&'a dyn Dummy>(); | ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` = note: required for `&'a (dyn Dummy + 'a)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object1.rs:5:18 @@ -13,12 +13,12 @@ LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely - --> $DIR/kindck-send-object1.rs:28:19 + --> $DIR/kindck-send-object1.rs:29:19 | LL | assert_send::>(); | ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)` + = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`, which is required by `Box<(dyn Dummy + 'a)>: Send` = note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send` note: required because it appears within the type `Box<(dyn Dummy + 'a)>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -28,6 +28,14 @@ note: required by a bound in `assert_send` LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` -error: aborting due to 2 previous errors +error: lifetime may not live long enough + --> $DIR/kindck-send-object1.rs:14:5 + | +LL | fn test52<'a>() { + | -- lifetime `'a` defined here +LL | assert_send::<&'a (dyn Dummy + Sync)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object2.stderr b/tests/ui/kindck/kindck-send-object2.stderr index 6b8df60227f55..758a517e12885 100644 --- a/tests/ui/kindck/kindck-send-object2.stderr +++ b/tests/ui/kindck/kindck-send-object2.stderr @@ -4,7 +4,7 @@ error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely LL | assert_send::<&'static dyn Dummy>(); | ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)` + = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send` note: required by a bound in `assert_send` --> $DIR/kindck-send-object2.rs:3:18 @@ -18,7 +18,7 @@ error[E0277]: `dyn Dummy` cannot be sent between threads safely LL | assert_send::>(); | ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `dyn Dummy` + = help: the trait `Send` is not implemented for `dyn Dummy`, which is required by `Box: Send` = note: required for `Unique` to implement `Send` note: required because it appears within the type `Box` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/kindck/kindck-send-owned.stderr b/tests/ui/kindck/kindck-send-owned.stderr index 860a9391bbb08..4bc0212089b11 100644 --- a/tests/ui/kindck/kindck-send-owned.stderr +++ b/tests/ui/kindck/kindck-send-owned.stderr @@ -4,7 +4,7 @@ error[E0277]: `*mut u8` cannot be sent between threads safely LL | assert_send::>(); | ^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `*mut u8` + = help: the trait `Send` is not implemented for `*mut u8`, which is required by `Box<*mut u8>: Send` = note: required for `Unique<*mut u8>` to implement `Send` note: required because it appears within the type `Box<*mut u8>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/lang-items/bad-add-impl.rs b/tests/ui/lang-items/bad-add-impl.rs deleted file mode 100644 index 0c44edbe51a0c..0000000000000 --- a/tests/ui/lang-items/bad-add-impl.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![feature(no_core)] -#![feature(lang_items)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - -#[lang = "add"] -trait Add { - const add: u32 = 1u32; -} - -impl Add for u32 {} - -fn main() { - 1u32 + 1u32; - //~^ ERROR cannot add `u32` to `u32` -} diff --git a/tests/ui/lang-items/bad-add-impl.stderr b/tests/ui/lang-items/bad-add-impl.stderr deleted file mode 100644 index c5ad9ff2a0856..0000000000000 --- a/tests/ui/lang-items/bad-add-impl.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0369]: cannot add `u32` to `u32` - --> $DIR/bad-add-impl.rs:16:10 - | -LL | 1u32 + 1u32; - | ---- ^ ---- u32 - | | - | u32 - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/lang-items/duplicate.rs b/tests/ui/lang-items/duplicate.rs new file mode 100644 index 0000000000000..f88d23544145a --- /dev/null +++ b/tests/ui/lang-items/duplicate.rs @@ -0,0 +1,10 @@ +// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib" +#![feature(lang_items)] + +#[lang = "sized"] +trait Sized {} +//~^ ERROR: duplicate lang item + +#[lang = "tuple_trait"] +pub trait Tuple {} +// no error diff --git a/tests/ui/lang-items/duplicate.stderr b/tests/ui/lang-items/duplicate.stderr new file mode 100644 index 0000000000000..aaa8f5e605afa --- /dev/null +++ b/tests/ui/lang-items/duplicate.stderr @@ -0,0 +1,13 @@ +error[E0152]: found duplicate lang item `sized` + --> $DIR/duplicate.rs:5:1 + | +LL | trait Sized {} + | ^^^^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `core` (which `std` depends on) + = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib + = note: second definition in the local crate (`duplicate`) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0152`. diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr deleted file mode 100644 index ff603111e94c5..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:39:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:43:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr deleted file mode 100644 index ff603111e94c5..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:39:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:43:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_mut_bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_item.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr deleted file mode 100644 index 02e33c597fe87..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.fn_once_bad_sig.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:42:5 - | -LL | a(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: failed to find an overloaded call trait for closure call - --> $DIR/fn-fn_mut-call-ill-formed.rs:47:5 - | -LL | b(); - | ^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 2 previous errors - diff --git a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs b/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs deleted file mode 100644 index 757c6538d05b0..0000000000000 --- a/tests/ui/lang-items/fn-fn_mut-call-ill-formed.rs +++ /dev/null @@ -1,49 +0,0 @@ -// revisions: fn_once_bad_item fn_once_bad_sig fn_mut_bad_item fn_mut_bad_sig fn_bad_item fn_bad_sig - -#![feature(lang_items)] -#![feature(no_core)] -#![no_core] - -#[lang = "sized"] -trait Sized {} - -#[cfg(any(fn_bad_item, fn_bad_sig))] -#[lang = "fn"] -trait MyFn { - #[cfg(fn_bad_sig)] - fn call(i: i32) -> i32 { 0 } - - #[cfg(fn_bad_item)] - const call: i32 = 42; -} - -#[cfg(any(fn_mut_bad_item, fn_mut_bad_sig))] -#[lang = "fn_mut"] -trait MyFnMut { - #[cfg(fn_mut_bad_sig)] - fn call_mut(i: i32) -> i32 { 0 } - - #[cfg(fn_mut_bad_item)] - const call_mut: i32 = 42; -} - -#[cfg(any(fn_once_bad_item, fn_once_bad_sig))] -#[lang = "fn_once"] -trait MyFnOnce { - #[cfg(fn_once_bad_sig)] - fn call_once(i: i32) -> i32 { 0 } - - #[cfg(fn_once_bad_item)] - const call_once: i32 = 42; -} - -fn main() { - let a = || 42; - a(); - //~^ ERROR failed to find an overloaded call trait for closure call - - let mut i = 0; - let mut b = || { }; - b(); - //~^ ERROR failed to find an overloaded call trait for closure call -} diff --git a/tests/ui/lang-items/issue-31076.rs b/tests/ui/lang-items/issue-31076.rs deleted file mode 100644 index cdb196d4ff23f..0000000000000 --- a/tests/ui/lang-items/issue-31076.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(no_core, lang_items)] -#![no_core] - -#[lang="sized"] -trait Sized {} - -#[lang="add"] -trait Add {} - -impl Add for i32 {} - -fn main() { - let x = 5 + 6; - //~^ ERROR cannot add `i32` to `{integer}` - let y = 5i32 + 6i32; - //~^ ERROR cannot add `i32` to `i32` -} diff --git a/tests/ui/lang-items/issue-31076.stderr b/tests/ui/lang-items/issue-31076.stderr deleted file mode 100644 index ac0d9dc752879..0000000000000 --- a/tests/ui/lang-items/issue-31076.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0369]: cannot add `i32` to `{integer}` - --> $DIR/issue-31076.rs:13:15 - | -LL | let x = 5 + 6; - | - ^ - i32 - | | - | {integer} - -error[E0369]: cannot add `i32` to `i32` - --> $DIR/issue-31076.rs:15:18 - | -LL | let y = 5i32 + 6i32; - | ---- ^ ---- i32 - | | - | i32 - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/lang-items/issue-86238.rs b/tests/ui/lang-items/issue-86238.rs deleted file mode 100644 index 509f94f3834a5..0000000000000 --- a/tests/ui/lang-items/issue-86238.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Regression test for the ICE described in issue #86238. - -#![feature(lang_items)] -#![feature(no_core)] - -#![no_core] -fn main() { - let one = || {}; - one() - //~^ ERROR: failed to find an overloaded call trait for closure call - //~| HELP: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined -} -#[lang = "sized"] -trait Sized {} -#[lang = "copy"] -trait Copy {} diff --git a/tests/ui/lang-items/issue-86238.stderr b/tests/ui/lang-items/issue-86238.stderr deleted file mode 100644 index b492904bcc73a..0000000000000 --- a/tests/ui/lang-items/issue-86238.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: failed to find an overloaded call trait for closure call - --> $DIR/issue-86238.rs:9:5 - | -LL | one() - | ^^^^^ - | - = help: make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods - -error: aborting due to 1 previous error - diff --git a/tests/ui/lang-items/lang-item-generic-requirements.stderr b/tests/ui/lang-items/lang-item-generic-requirements.stderr index 8072e6797e49c..30abdf84046ea 100644 --- a/tests/ui/lang-items/lang-item-generic-requirements.stderr +++ b/tests/ui/lang-items/lang-item-generic-requirements.stderr @@ -50,23 +50,23 @@ LL | LL | fn start(_: *const u8, _: isize, _: *const *const u8) -> isize { | - this function has 0 generic arguments -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/lang-item-generic-requirements.rs:24:22 | LL | struct MyPhantomData; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T` or referring to it in a field - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0392]: parameter `U` is never used +error[E0392]: type parameter `U` is never used --> $DIR/lang-item-generic-requirements.rs:24:25 | LL | struct MyPhantomData; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `U` or referring to it in a field - = help: if you intended `U` to be a const parameter, use `const U: usize` instead + = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead error[E0369]: cannot add `{integer}` to `{integer}` --> $DIR/lang-item-generic-requirements.rs:44:7 diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.rs b/tests/ui/lazy-type-alias/unused-generic-parameters.rs new file mode 100644 index 0000000000000..9d02de7a7212b --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.rs @@ -0,0 +1,22 @@ +// Check that we reject bivariant generic parameters as unused. +// Furthermore, check that we only emit a single diagnostic for unused type parameters: +// Previously, we would emit *two* errors, namely E0392 and E0091. + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type A<'a> = (); +//~^ ERROR lifetime parameter `'a` is never used +//~| HELP consider removing `'a` + +type B = (); +//~^ ERROR type parameter `T` is never used +//~| HELP consider removing `T` +//~| HELP if you intended `T` to be a const parameter + +// Check that we don't emit the const param help message here: +type C = (); +//~^ ERROR type parameter `T` is never used +//~| HELP consider removing `T` + +fn main() {} diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.stderr b/tests/ui/lazy-type-alias/unused-generic-parameters.stderr new file mode 100644 index 0000000000000..484e21b0a03f9 --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.stderr @@ -0,0 +1,28 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/unused-generic-parameters.rs:8:8 + | +LL | type A<'a> = (); + | ^^ unused lifetime parameter + | + = help: consider removing `'a` or referring to it in the body of the type alias + +error[E0392]: type parameter `T` is never used + --> $DIR/unused-generic-parameters.rs:12:8 + | +LL | type B = (); + | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/unused-generic-parameters.rs:18:8 + | +LL | type C = (); + | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/lifetimes/issue-17728.rs b/tests/ui/lifetimes/issue-17728.rs index 6aca159c47e34..ff8783029ff52 100644 --- a/tests/ui/lifetimes/issue-17728.rs +++ b/tests/ui/lifetimes/issue-17728.rs @@ -12,7 +12,7 @@ trait TraversesWorld { let direction = str_to_direction(directionStr); let maybe_room = room.direction_to_room.get(&direction); match maybe_room { - Some(entry) => Ok(entry), + Some(entry) => Ok(entry), //~ ERROR: lifetime may not live long enough _ => Err("Direction does not exist in room.") } } diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr index fb1c7cf7ad35b..23547f722a116 100644 --- a/tests/ui/lifetimes/issue-17728.stderr +++ b/tests/ui/lifetimes/issue-17728.stderr @@ -16,6 +16,22 @@ LL | | } = note: expected enum `RoomDirection` found enum `Option<_>` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/issue-17728.rs:15:28 + | +LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +... +LL | Some(entry) => Ok(entry), + | ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter + | +LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> { + | ++++ ++ ++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr index ec4aea623911a..534ba933ba5d0 100644 --- a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr +++ b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr @@ -13,19 +13,19 @@ error: generic `Self` types are currently not permitted in anonymous constants LL | array: [(); size_of::<&Self>()], | ^^^^ -error[E0392]: parameter `'s` is never used +error[E0392]: lifetime parameter `'s` is never used --> $DIR/issue-64173-unused-lifetimes.rs:3:12 | LL | struct Foo<'s> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'s`, referring to it in a field, or using a marker such as `PhantomData` -error[E0392]: parameter `'a` is never used +error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-64173-unused-lifetimes.rs:15:12 | LL | struct Bar<'a> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs index d6c918843c700..56f89b7041085 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs @@ -1,5 +1,7 @@ fn foo(x: &i32, y: &i32) -> &i32 { //~ ERROR missing lifetime if x > y { x } else { y } + //~^ ERROR: lifetime may not live long enough + //~| ERROR: lifetime may not live long enough } fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index 62b0a8a04bf79..db5b039d1c2f0 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -10,6 +10,22 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { | ++++ ++ ++ ++ -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/ex1b-return-no-names-if-else.rs:2:16 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | - let's call the lifetime of this reference `'1` +LL | if x > y { x } else { y } + | ^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/ex1b-return-no-names-if-else.rs:2:27 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | - let's call the lifetime of this reference `'2` +LL | if x > y { x } else { y } + | ^ returning this value requires that `'2` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lint/dead-code/anon-const-in-pat.rs b/tests/ui/lint/dead-code/anon-const-in-pat.rs index d3e39c0de69c8..4d7fdddf246ed 100644 --- a/tests/ui/lint/dead-code/anon-const-in-pat.rs +++ b/tests/ui/lint/dead-code/anon-const-in-pat.rs @@ -1,6 +1,5 @@ // check-pass #![feature(inline_const_pat)] -#![allow(incomplete_features)] #![deny(dead_code)] const fn one() -> i32 { diff --git a/tests/ui/lint/dead-code/associated-type.rs b/tests/ui/lint/dead-code/associated-type.rs index 1cf66e75a95a5..25106a66e7e36 100644 --- a/tests/ui/lint/dead-code/associated-type.rs +++ b/tests/ui/lint/dead-code/associated-type.rs @@ -15,5 +15,5 @@ impl Foo for Ex { } pub fn main() { - let _x = Ex; + let _x: &dyn Foo::Bar> = &Ex; } diff --git a/tests/ui/lint/dead-code/issue-41883.rs b/tests/ui/lint/dead-code/issue-41883.rs new file mode 100644 index 0000000000000..e165861e893e0 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-41883.rs @@ -0,0 +1,29 @@ +#![deny(dead_code)] + +enum Category { + Dead, //~ ERROR variant `Dead` is never constructed + Used, +} + +trait UnusedTrait { //~ ERROR trait `UnusedTrait` is never used + fn this_is_unused(&self) -> Category { + Category::Dead + } +} + +struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed + +impl UnusedTrait for UnusedStruct { + fn this_is_unused(&self) -> Category { + Category::Used + } +} + +mod private { + #[derive(Debug)] + struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed +} + +fn main() { + let _c = Category::Used; +} diff --git a/tests/ui/lint/dead-code/issue-41883.stderr b/tests/ui/lint/dead-code/issue-41883.stderr new file mode 100644 index 0000000000000..cf079e4dda33a --- /dev/null +++ b/tests/ui/lint/dead-code/issue-41883.stderr @@ -0,0 +1,36 @@ +error: variant `Dead` is never constructed + --> $DIR/issue-41883.rs:4:5 + | +LL | enum Category { + | -------- variant in this enum +LL | Dead, + | ^^^^ + | +note: the lint level is defined here + --> $DIR/issue-41883.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: trait `UnusedTrait` is never used + --> $DIR/issue-41883.rs:8:7 + | +LL | trait UnusedTrait { + | ^^^^^^^^^^^ + +error: struct `UnusedStruct` is never constructed + --> $DIR/issue-41883.rs:14:8 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + +error: struct `UnusedStruct` is never constructed + --> $DIR/issue-41883.rs:24:12 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + | + = note: `UnusedStruct` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs index 942c551650032..2d6364aa0cde1 100644 --- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs @@ -17,7 +17,7 @@ struct Bar { // Issue 119267: this should not ICE. #[derive(Debug)] -struct Foo(usize, #[allow(unused)] usize); //~ WARN field `0` is never read +struct Foo(usize, #[allow(unused)] usize); //~ WARN struct `Foo` is never constructed fn main() { Bar { diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr index 06f9b229c18c1..b992005318f2e 100644 --- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -51,19 +51,13 @@ note: the lint level is defined here LL | #[forbid(dead_code)] | ^^^^^^^^^ -warning: field `0` is never read - --> $DIR/multiple-dead-codes-in-the-same-struct.rs:20:12 +warning: struct `Foo` is never constructed + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:20:8 | LL | struct Foo(usize, #[allow(unused)] usize); - | --- ^^^^^ - | | - | field in this struct + | ^^^ | = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis -help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field - | -LL | struct Foo((), #[allow(unused)] usize); - | ~~ error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs index 631a8cb2f08cc..9b1edba41aafe 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr index 8b83afb509f55..388dc6160cb95 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -12,33 +12,5 @@ help: if this is an object-safe trait, use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/cap-lints-allow.rs b/tests/ui/lint/force-warn/cap-lints-allow.rs index fdba7f4105e73..9609ea994312f 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.rs +++ b/tests/ui/lint/force-warn/cap-lints-allow.rs @@ -8,9 +8,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr index 0c16106b6c60e..a037fb671af29 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.stderr +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -12,33 +12,5 @@ help: if this is an object-safe trait, use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/cap-lints-allow.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/cap-lints-allow.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs index 7ad7462ddc550..9736027452a8d 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs @@ -8,9 +8,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr index 4fcd1f96affd7..a74cda2239f50 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -13,33 +13,5 @@ help: if this is an object-safe trait, use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs index ee5a18c38292b..99cad614c25cd 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr index 5303ca3a6a0e3..c9472a3b9b9d3 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -13,33 +13,5 @@ help: if this is an object-safe trait, use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-lint-group.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-lint-group.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs index 248aece6fe77c..f0aacd773401f 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr index 69658a1b2a83c..558d5cbb53156 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -13,33 +13,5 @@ help: if this is an object-safe trait, use `dyn` LL | pub fn function(_x: Box) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | pub fn function(_x: Box) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/future-incompat-json-test.stderr b/tests/ui/lint/future-incompat-json-test.stderr index c4ab5a00d16cc..18fc3f17f0020 100644 --- a/tests/ui/lint/future-incompat-json-test.stderr +++ b/tests/ui/lint/future-incompat-json-test.stderr @@ -1,4 +1,4 @@ -{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` +{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` --> $DIR/future-incompat-json-test.rs:9:9 | LL | let x = 1; diff --git a/tests/ui/lint/issue-20343.rs b/tests/ui/lint/issue-20343.rs index 000b6398442a3..f0f4eccc676a1 100644 --- a/tests/ui/lint/issue-20343.rs +++ b/tests/ui/lint/issue-20343.rs @@ -22,6 +22,8 @@ impl B { // test for unused code in generics fn baz>() {} + + fn foz>(a: A) { a.dummy(D); } } pub fn main() { @@ -29,4 +31,5 @@ pub fn main() { B::foo(b); B::bar(); B::baz::<()>(); + B::foz::<()>(()); } diff --git a/tests/ui/lint/issue-86600-lint-twice.rs b/tests/ui/lint/issue-86600-lint-twice.rs deleted file mode 100644 index 0e8a837d987f6..0000000000000 --- a/tests/ui/lint/issue-86600-lint-twice.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Regression test for #86600, where an instance of the -// `illegal_floating_point_literal_pattern` lint was issued twice. - -// check-pass - -fn main() { - let x = 42.0; - - match x { - 5.0 => {} - //~^ WARNING: floating-point types cannot be used in patterns - //~| WARNING: this was previously accepted by the compiler - _ => {} - } -} diff --git a/tests/ui/lint/issue-86600-lint-twice.stderr b/tests/ui/lint/issue-86600-lint-twice.stderr deleted file mode 100644 index 5a65c61212858..0000000000000 --- a/tests/ui/lint/issue-86600-lint-twice.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: floating-point types cannot be used in patterns - --> $DIR/issue-86600-lint-twice.rs:10:9 - | -LL | 5.0 => {} - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/lint/lint-stability-deprecated.rs b/tests/ui/lint/lint-stability-deprecated.rs index a56a37228e533..80bc85ff557fc 100644 --- a/tests/ui/lint/lint-stability-deprecated.rs +++ b/tests/ui/lint/lint-stability-deprecated.rs @@ -96,13 +96,10 @@ mod cross_crate { struct S1(T::TypeUnstable); struct S2(T::TypeDeprecated); //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text type A = dyn TraitWithAssociatedTypes< TypeUnstable = u8, TypeDeprecated = u16, //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` >; let _ = DeprecatedStruct { //~ WARN use of deprecated struct `lint_stability::DeprecatedStruct` diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr index 609fc56a8ae5f..51205ff434062 100644 --- a/tests/ui/lint/lint-stability-deprecated.stderr +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -77,241 +77,241 @@ LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:108:17 + --> $DIR/lint-stability-deprecated.rs:105:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedUnstableStruct`: text - --> $DIR/lint-stability-deprecated.rs:111:17 + --> $DIR/lint-stability-deprecated.rs:108:17 | LL | let _ = DeprecatedUnstableStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `lint_stability::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:118:17 + --> $DIR/lint-stability-deprecated.rs:115:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `lint_stability::DeprecatedUnstableUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:119:17 + --> $DIR/lint-stability-deprecated.rs:116:17 | LL | let _ = DeprecatedUnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:123:23 + --> $DIR/lint-stability-deprecated.rs:120:23 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant`: text - --> $DIR/lint-stability-deprecated.rs:124:23 + --> $DIR/lint-stability-deprecated.rs:121:23 | LL | let _ = Enum::DeprecatedUnstableVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:128:17 + --> $DIR/lint-stability-deprecated.rs:125:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:129:17 + --> $DIR/lint-stability-deprecated.rs:126:17 | LL | let _ = DeprecatedUnstableTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:138:25 + --> $DIR/lint-stability-deprecated.rs:135:25 | LL | macro_test_arg!(deprecated_text()); | ^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:139:25 + --> $DIR/lint-stability-deprecated.rs:136:25 | LL | macro_test_arg!(deprecated_unstable_text()); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:140:41 + --> $DIR/lint-stability-deprecated.rs:137:41 | LL | macro_test_arg!(macro_test_arg!(deprecated_text())); | ^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:145:16 + --> $DIR/lint-stability-deprecated.rs:142:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:147:25 + --> $DIR/lint-stability-deprecated.rs:144:25 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:149:16 + --> $DIR/lint-stability-deprecated.rs:146:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:151:25 + --> $DIR/lint-stability-deprecated.rs:148:25 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:153:16 + --> $DIR/lint-stability-deprecated.rs:150:16 | LL | Trait::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:155:25 + --> $DIR/lint-stability-deprecated.rs:152:25 | LL | ... ::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:157:16 + --> $DIR/lint-stability-deprecated.rs:154:16 | LL | ... Trait::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:159:25 + --> $DIR/lint-stability-deprecated.rs:156:25 | LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:187:10 + --> $DIR/lint-stability-deprecated.rs:184:10 | LL | impl DeprecatedTrait for S {} | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:189:25 + --> $DIR/lint-stability-deprecated.rs:186:25 | LL | trait LocalTrait2 : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:208:23 + --> $DIR/lint-stability-deprecated.rs:205:23 | LL | unstable_mod::deprecated(); | ^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:330:9 + --> $DIR/lint-stability-deprecated.rs:327:9 | LL | deprecated(); | ^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:335:16 + --> $DIR/lint-stability-deprecated.rs:332:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:337:25 + --> $DIR/lint-stability-deprecated.rs:334:25 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:339:9 + --> $DIR/lint-stability-deprecated.rs:336:9 | LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:344:16 + --> $DIR/lint-stability-deprecated.rs:341:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:346:25 + --> $DIR/lint-stability-deprecated.rs:343:25 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `this_crate::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:384:17 + --> $DIR/lint-stability-deprecated.rs:381:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:391:17 + --> $DIR/lint-stability-deprecated.rs:388:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:395:23 + --> $DIR/lint-stability-deprecated.rs:392:23 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:399:17 + --> $DIR/lint-stability-deprecated.rs:396:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:406:16 + --> $DIR/lint-stability-deprecated.rs:403:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:408:25 + --> $DIR/lint-stability-deprecated.rs:405:25 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:410:16 + --> $DIR/lint-stability-deprecated.rs:407:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:412:25 + --> $DIR/lint-stability-deprecated.rs:409:25 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text - --> $DIR/lint-stability-deprecated.rs:439:9 + --> $DIR/lint-stability-deprecated.rs:436:9 | LL | fn_in_body(); | ^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:459:10 + --> $DIR/lint-stability-deprecated.rs:456:10 | LL | impl DeprecatedTrait for S { } | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:461:24 + --> $DIR/lint-stability-deprecated.rs:458:24 | LL | trait LocalTrait : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text - --> $DIR/lint-stability-deprecated.rs:447:13 + --> $DIR/lint-stability-deprecated.rs:444:13 | LL | fn_in_body(); | ^^^^^^^^^^ @@ -323,7 +323,7 @@ LL | struct S2(T::TypeDeprecated); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 + --> $DIR/lint-stability-deprecated.rs:101:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ @@ -449,214 +449,190 @@ LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `lint_stability::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:109:13 + --> $DIR/lint-stability-deprecated.rs:106:13 | LL | i: 0 | ^^^^ warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:113:13 + --> $DIR/lint-stability-deprecated.rs:110:13 | LL | i: 0 | ^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:144:13 + --> $DIR/lint-stability-deprecated.rs:141:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:146:16 + --> $DIR/lint-stability-deprecated.rs:143:16 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:148:13 + --> $DIR/lint-stability-deprecated.rs:145:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:150:16 + --> $DIR/lint-stability-deprecated.rs:147:16 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:152:13 + --> $DIR/lint-stability-deprecated.rs:149:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:154:16 + --> $DIR/lint-stability-deprecated.rs:151:16 | LL | ::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:156:13 + --> $DIR/lint-stability-deprecated.rs:153:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:158:16 + --> $DIR/lint-stability-deprecated.rs:155:16 | LL | ... ::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:175:13 + --> $DIR/lint-stability-deprecated.rs:172:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:176:13 + --> $DIR/lint-stability-deprecated.rs:173:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:177:13 + --> $DIR/lint-stability-deprecated.rs:174:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:178:13 + --> $DIR/lint-stability-deprecated.rs:175:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:331:13 + --> $DIR/lint-stability-deprecated.rs:328:13 | LL | foo.method_deprecated(); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:332:14 + --> $DIR/lint-stability-deprecated.rs:329:14 | LL | Foo::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:333:16 + --> $DIR/lint-stability-deprecated.rs:330:16 | LL | ::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:334:13 + --> $DIR/lint-stability-deprecated.rs:331:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:336:16 + --> $DIR/lint-stability-deprecated.rs:333:16 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:340:13 + --> $DIR/lint-stability-deprecated.rs:337:13 | LL | foo.method_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:341:14 + --> $DIR/lint-stability-deprecated.rs:338:14 | LL | Foo::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:342:16 + --> $DIR/lint-stability-deprecated.rs:339:16 | LL | ::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:343:13 + --> $DIR/lint-stability-deprecated.rs:340:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:345:16 + --> $DIR/lint-stability-deprecated.rs:342:16 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:386:13 + --> $DIR/lint-stability-deprecated.rs:383:13 | LL | i: 0 | ^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:405:13 + --> $DIR/lint-stability-deprecated.rs:402:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:407:16 + --> $DIR/lint-stability-deprecated.rs:404:16 | LL | ::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:409:13 + --> $DIR/lint-stability-deprecated.rs:406:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:411:16 + --> $DIR/lint-stability-deprecated.rs:408:16 | LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:428:13 + --> $DIR/lint-stability-deprecated.rs:425:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:429:13 + --> $DIR/lint-stability-deprecated.rs:426:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:97:48 - | -LL | struct S2(T::TypeDeprecated); - | ^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 - | -LL | TypeDeprecated = u16, - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 - | -LL | TypeDeprecated = u16, - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 108 warnings emitted +warning: 105 warnings emitted diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs index f80fe88cbb97e..82ca49461ed23 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.rs @@ -22,12 +22,8 @@ mod rustc_ok { pub fn rustc_lints() { let x = 42.0; - #[expect(illegal_floating_point_literal_pattern)] - match x { - 5.0 => {} - 6.0 => {} - _ => {} - } + #[expect(invalid_nan_comparisons)] + let _b = x == f32::NAN; } } @@ -40,13 +36,9 @@ mod rustc_warn { pub fn rustc_lints() { let x = 42; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] //~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations] - match x { - 5 => {} - 6 => {} - _ => {} - } + let _b = x == 5; } } diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr index 6d49e7543dc59..efe1aa04e5e29 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ warning: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:37:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:33:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -7,10 +7,10 @@ LL | #[expect(dead_code)] = note: `#[warn(unfulfilled_lint_expectations)]` on by default warning: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:43:18 + --> $DIR/expect_tool_lint_rfc_2383.rs:39:18 | -LL | #[expect(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[expect(invalid_nan_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^ warning: 2 warnings emitted diff --git a/tests/ui/liveness/liveness-forgot-ret.rs b/tests/ui/liveness/liveness-forgot-ret.rs index b8c2bc7343892..3ba2f2d276ef6 100644 --- a/tests/ui/liveness/liveness-forgot-ret.rs +++ b/tests/ui/liveness/liveness-forgot-ret.rs @@ -1,4 +1,5 @@ fn god_exists(a: isize) -> bool { return god_exists(a); } +//~^ WARN function cannot return without recursing fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } //~^ ERROR mismatched types diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr index a5adadca26ee2..f72a30fc4e9c7 100644 --- a/tests/ui/liveness/liveness-forgot-ret.stderr +++ b/tests/ui/liveness/liveness-forgot-ret.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/liveness-forgot-ret.rs:3:19 + --> $DIR/liveness-forgot-ret.rs:4:19 | LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } | - ^^^^^ expected `isize`, found `()` @@ -11,6 +11,17 @@ help: consider returning the local binding `a` LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a } | + -error: aborting due to 1 previous error +warning: function cannot return without recursing + --> $DIR/liveness-forgot-ret.rs:1:1 + | +LL | fn god_exists(a: isize) -> bool { return god_exists(a); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-else-break-with-value.rs b/tests/ui/loops/loop-else-break-with-value.rs index 670d8a145c0af..7ccf71b2edf4a 100644 --- a/tests/ui/loops/loop-else-break-with-value.rs +++ b/tests/ui/loops/loop-else-break-with-value.rs @@ -1,6 +1,11 @@ fn main() { let Some(1) = loop { //~^ NOTE `else` is attached to this loop + //~| ERROR refutable pattern in local binding + //~| NOTE not covered + //~| NOTE for more information + //~| NOTE matched value is of type + //~| NOTE require an "irrefutable pattern" break Some(1) } else { //~^ ERROR `loop...else` loops are not supported diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr index c933e0d0cd8ea..13d4c5faf7326 100644 --- a/tests/ui/loops/loop-else-break-with-value.stderr +++ b/tests/ui/loops/loop-else-break-with-value.stderr @@ -1,5 +1,5 @@ error: `loop...else` loops are not supported - --> $DIR/loop-else-break-with-value.rs:5:7 + --> $DIR/loop-else-break-with-value.rs:10:7 | LL | let Some(1) = loop { | ---- `else` is attached to this loop @@ -14,5 +14,24 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to 1 previous error +error[E0005]: refutable pattern in local binding + --> $DIR/loop-else-break-with-value.rs:2:9 + | +LL | let Some(1) = loop { + | ^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Option` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL ~ if let Some(1) = loop { +LL | + ... +LL | return; +LL ~ } { todo!() }; + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/auxiliary/hello_macro.rs b/tests/ui/macros/auxiliary/hello_macro.rs similarity index 100% rename from tests/ui/auxiliary/hello_macro.rs rename to tests/ui/macros/auxiliary/hello_macro.rs diff --git a/tests/ui/macros/issue-22463.rs b/tests/ui/macros/issue-22463.rs index fdf5a2fca7255..8f7b27cb9a056 100644 --- a/tests/ui/macros/issue-22463.rs +++ b/tests/ui/macros/issue-22463.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass macro_rules! items { () => { type A = (); diff --git a/tests/ui/issues/issue-46438.rs b/tests/ui/macros/issue-46438.rs similarity index 100% rename from tests/ui/issues/issue-46438.rs rename to tests/ui/macros/issue-46438.rs diff --git a/tests/ui/issues/issue-46438.stderr b/tests/ui/macros/issue-46438.stderr similarity index 100% rename from tests/ui/issues/issue-46438.stderr rename to tests/ui/macros/issue-46438.stderr diff --git a/tests/ui/macro-quote-test.rs b/tests/ui/macros/macro-quote-test.rs similarity index 100% rename from tests/ui/macro-quote-test.rs rename to tests/ui/macros/macro-quote-test.rs diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index 192e6e0cc985d..8cef833f48d26 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -107,9 +107,9 @@ fn test_expr() { c1!(expr, [ true || false ], "true || false"); c1!(expr, [ true || false && false ], "true || false && false"); c1!(expr, [ a < 1 && 2 < b && c > 3 && 4 > d ], "a < 1 && 2 < b && c > 3 && 4 > d"); - c2!(expr, [ a & b & !c ], "a & b & !c", "a & b &!c"); // FIXME + c1!(expr, [ a & b & !c ], "a & b & !c"); c1!(expr, [ a + b * c - d + -1 * -2 - -3], "a + b * c - d + -1 * -2 - -3"); - c2!(expr, [ x = !y ], "x = !y", "x =!y"); // FIXME + c1!(expr, [ x = !y ], "x = !y"); // ExprKind::Unary c1!(expr, [ *expr ], "*expr"); @@ -141,15 +141,14 @@ fn test_expr() { "if let _ = (true && false) {}", "if let _ = true && false {}", ); - c2!(expr, + c1!(expr, [ match () { _ if let _ = Struct {} => {} } ], - "match () { _ if let _ = Struct {} => {} }", - "match() { _ if let _ = Struct {} => {} }", + "match () { _ if let _ = Struct {} => {} }" ); // ExprKind::If c1!(expr, [ if true {} ], "if true {}"); - c2!(expr, [ if !true {} ], "if !true {}", "if!true {}"); // FIXME + c1!(expr, [ if !true {} ], "if !true {}"); c1!(expr, [ if ::std::blah() { } else { } ], "if ::std::blah() {} else {}"); c1!(expr, [ if let true = true {} else {} ], "if let true = true {} else {}"); c1!(expr, @@ -212,7 +211,7 @@ fn test_expr() { c2_match_arm!( [ { 1 } - 1 ], "match () { _ => ({ 1 }) - 1, }", - "match() { _ => { 1 } - 1 }", + "match () { _ => { 1 } - 1 }", ); // ExprKind::Closure @@ -655,11 +654,11 @@ fn test_stmt() { c2!(stmt, [ let _ ], "let _;", "let _"); c2!(stmt, [ let x = true ], "let x = true;", "let x = true"); c2!(stmt, [ let x: bool = true ], "let x: bool = true;", "let x: bool = true"); - c2!(stmt, [ let (a, b) = (1, 2) ], "let (a, b) = (1, 2);", "let(a, b) = (1, 2)"); // FIXME + c2!(stmt, [ let (a, b) = (1, 2) ], "let (a, b) = (1, 2);", "let (a, b) = (1, 2)"); c2!(stmt, [ let (a, b): (u32, u32) = (1, 2) ], "let (a, b): (u32, u32) = (1, 2);", - "let(a, b): (u32, u32) = (1, 2)" // FIXME + "let (a, b): (u32, u32) = (1, 2)" ); macro_rules! c2_let_expr_minus_one { ([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => { @@ -776,8 +775,8 @@ fn test_ty() { c1!(ty, [ Ref<'a> ], "Ref<'a>"); c1!(ty, [ PhantomData ], "PhantomData"); c2!(ty, [ PhantomData:: ], "PhantomData", "PhantomData::"); - c2!(ty, [ Fn() -> ! ], "Fn() -> !", "Fn() ->!"); - c2!(ty, [ Fn(u8) -> ! ], "Fn(u8) -> !", "Fn(u8) ->!"); // FIXME + c1!(ty, [ Fn() -> ! ], "Fn() -> !"); + c1!(ty, [ Fn(u8) -> ! ], "Fn(u8) -> !"); c1!(ty, [ ::Type ], "::Type"); // TyKind::TraitObject @@ -857,16 +856,16 @@ fn test_punct() { // Otherwise, any old proc macro that parses pretty-printed code might glue // together tokens that shouldn't be glued. p!([ = = < < <= <= == == != != >= >= > > ], "= = < < <= <= == == != != >= >= > >"); - p!([ && && & & || || | | ! ! ], "&& && & & || || | |!!"); // FIXME + p!([ && && & & || || | | ! ! ], "&& && & & || || | | ! !"); p!([ ~ ~ @ @ # # ], "~ ~ @ @ # #"); - p!([ . . .. .. ... ... ..= ..=], ".... .. ... ... ..= ..="); // FIXME - p!([ , , ; ; : : :: :: ], ",, ; ; : : :: ::"); // FIXME + p!([ . . .. .. ... ... ..= ..=], ". . .. .. ... ... ..= ..="); + p!([ , , ; ; : : :: :: ], ", , ; ; : : :: ::"); p!([ -> -> <- <- => =>], "-> -> <- <- => =>"); - p!([ $ $ ? ? ' ' ], "$$? ? ' '"); // FIXME + p!([ $ $ ? ? ' ' ], "$ $ ? ? ' '"); p!([ + + += += - - -= -= * * *= *= / / /= /= ], "+ + += += - - -= -= * * *= *= / / /= /="); p!([ % % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>= ], "% % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>="); - p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ?= |> >>@ --> <-- $$=====>"); - p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ",; ;, ** @@ $+$>< <> ?? +=="); // FIXME: `$ >` -> `$>` + p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ?= |> >>@ --> <-- $$ =====>"); + p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ",; ;, ** @@ $+$ >< <> ?? +=="); p!([ :#!@|$=&*,+;*~? ], ":#!@|$=&*,+;*~?"); } diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr index 81047c7a21ae7..69607600b55c8 100644 --- a/tests/ui/macros/trace_faulty_macros.stderr +++ b/tests/ui/macros/trace_faulty_macros.stderr @@ -111,7 +111,7 @@ LL | test!(let x = 1+1); = note: expanding `test! { let x = 1+1 }` = note: to `test! ((x, 1 + 1))` = note: expanding `test! { (x, 1 + 1) }` - = note: to `let x = 1 + 1 ;` + = note: to `let x = 1 + 1;` error: aborting due to 5 previous errors diff --git a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr index 27b86145e90f4..41d0f17366b1e 100644 --- a/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr +++ b/tests/ui/malformed/do-not-ice-on-note_and_explain.stderr @@ -60,11 +60,11 @@ LL | implA{fn d(){fn d(){Self(1)}}} | | | this type parameter needs to be `Sized` | -note: required by a bound in `A` +note: required by an implicit `Sized` bound in `A` --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 | LL | struct A(B); - | ^ required by this bound in `A` + | ^ required by the implicit `Sized` requirement on this type parameter in `A` help: you could relax the implicit `Sized` bound on `B` if it were used through indirection like `&B` or `Box` --> $DIR/do-not-ice-on-note_and_explain.rs:1:10 | diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs index 5376fc89d4f4a..d91a8055aa16d 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs @@ -3,7 +3,9 @@ #[marker] trait Marker { const N: usize = 0; + //~^ ERROR marker traits cannot have associated items fn do_something() {} + //~^ ERROR marker traits cannot have associated items } struct OverrideConst; diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr index 1d30c6d566742..92a54cff7f5fa 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr @@ -1,15 +1,28 @@ error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:10:1 + --> $DIR/override-item-on-marker-trait.rs:12:1 | LL | impl Marker for OverrideConst { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:16:1 + --> $DIR/override-item-on-marker-trait.rs:18:1 | LL | impl Marker for OverrideFn { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0714]: marker traits cannot have associated items + --> $DIR/override-item-on-marker-trait.rs:5:5 + | +LL | const N: usize = 0; + | ^^^^^^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/override-item-on-marker-trait.rs:7:5 + | +LL | fn do_something() {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0715`. +Some errors have detailed explanations: E0714, E0715. +For more information about an error, try `rustc --explain E0714`. diff --git a/tests/ui/match/issue-112438.rs b/tests/ui/match/issue-112438.rs index 15f380f7fb471..46c69d5ba9c77 100644 --- a/tests/ui/match/issue-112438.rs +++ b/tests/ui/match/issue-112438.rs @@ -1,7 +1,6 @@ // run-pass #![feature(inline_const_pat)] #![allow(dead_code)] -#![allow(incomplete_features)] fn foo() { match 0 { const { 1 << 5 } | _ => {} diff --git a/tests/ui/match/issue-41255.rs b/tests/ui/match/issue-41255.rs deleted file mode 100644 index d163801fd1902..0000000000000 --- a/tests/ui/match/issue-41255.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Matching against float literals should result in a linter error - -#![feature(exclusive_range_pattern)] -#![allow(unused)] -#![forbid(illegal_floating_point_literal_pattern)] - -fn main() { - let x = 42.0; - match x { - 5.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - 5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - 1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - 39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns - //~| ERROR floating-point types cannot be used in patterns - //~| WARNING hard error - //~| WARNING hard error - - ..71.0 => {} - //~^ ERROR floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler - ..=72.0 => {} - //~^ ERROR floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler - 71.0.. => {} - //~^ ERROR floating-point types cannot be used in patterns - //~| WARNING this was previously accepted by the compiler - _ => {}, - }; - let y = 5.0; - // Same for tuples - match (x, 5) { - (3.14, 1) => {}, //~ ERROR floating-point types cannot be used - //~| WARNING hard error - _ => {}, - } - // Or structs - struct Foo { x: f32 }; - match (Foo { x }) { - Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used - //~| WARNING hard error - _ => {}, - } -} diff --git a/tests/ui/match/issue-41255.stderr b/tests/ui/match/issue-41255.stderr deleted file mode 100644 index 9bc49654e6d4b..0000000000000 --- a/tests/ui/match/issue-41255.stderr +++ /dev/null @@ -1,115 +0,0 @@ -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:10:9 - | -LL | 5.0 => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 -note: the lint level is defined here - --> $DIR/issue-41255.rs:5:11 - | -LL | #![forbid(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:12:9 - | -LL | 5.0f32 => {}, - | ^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:14:10 - | -LL | -5.0 => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:16:9 - | -LL | 1.0 .. 33.0 => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:16:16 - | -LL | 1.0 .. 33.0 => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:20:9 - | -LL | 39.0 ..= 70.0 => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:20:18 - | -LL | 39.0 ..= 70.0 => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:25:11 - | -LL | ..71.0 => {} - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:28:12 - | -LL | ..=72.0 => {} - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:31:9 - | -LL | 71.0.. => {} - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:39:10 - | -LL | (3.14, 1) => {}, - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: floating-point types cannot be used in patterns - --> $DIR/issue-41255.rs:46:18 - | -LL | Foo { x: 2.0 } => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: aborting due to 12 previous errors - diff --git a/tests/ui/match/match-float.rs b/tests/ui/match/match-float.rs new file mode 100644 index 0000000000000..8da6a9ed2049c --- /dev/null +++ b/tests/ui/match/match-float.rs @@ -0,0 +1,11 @@ +// run-pass +// Makes sure we use `==` (not bitwise) semantics for float comparison. + +fn main() { + const F1: f32 = 0.0; + const F2: f32 = -0.0; + assert_eq!(F1, F2); + assert_ne!(F1.to_bits(), F2.to_bits()); + assert!(matches!(F1, F2)); + assert!(matches!(F2, F1)); +} diff --git a/tests/ui/match/validate-range-endpoints.rs b/tests/ui/match/validate-range-endpoints.rs index 1d1737f8b82f4..31d5bc3b65d50 100644 --- a/tests/ui/match/validate-range-endpoints.rs +++ b/tests/ui/match/validate-range-endpoints.rs @@ -1,6 +1,5 @@ #![feature(exclusive_range_pattern)] #![feature(inline_const_pat)] -#![allow(incomplete_features)] #![allow(overlapping_range_endpoints)] fn main() { diff --git a/tests/ui/match/validate-range-endpoints.stderr b/tests/ui/match/validate-range-endpoints.stderr index 0813fccff5187..b3b4066cd9158 100644 --- a/tests/ui/match/validate-range-endpoints.stderr +++ b/tests/ui/match/validate-range-endpoints.stderr @@ -1,59 +1,59 @@ error: literal out of range for `u8` - --> $DIR/validate-range-endpoints.rs:9:12 + --> $DIR/validate-range-endpoints.rs:8:12 | LL | 1..257 => {} | ^^^ this value does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` - --> $DIR/validate-range-endpoints.rs:11:13 + --> $DIR/validate-range-endpoints.rs:10:13 | LL | 1..=256 => {} | ^^^ this value does not fit into the type `u8` whose range is `0..=255` error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/validate-range-endpoints.rs:20:9 + --> $DIR/validate-range-endpoints.rs:19:9 | LL | 1..=TOO_BIG => {} | ^^^^^^^^^^^ lower bound larger than upper bound error[E0030]: lower range bound must be less than or equal to upper - --> $DIR/validate-range-endpoints.rs:22:9 + --> $DIR/validate-range-endpoints.rs:21:9 | LL | 1..=const { 256 } => {} | ^^^^^^^^^^^^^^^^^ lower bound larger than upper bound error: literal out of range for `u64` - --> $DIR/validate-range-endpoints.rs:28:32 + --> $DIR/validate-range-endpoints.rs:27:32 | LL | 10000000000000000000..=99999999999999999999 => {} | ^^^^^^^^^^^^^^^^^^^^ this value does not fit into the type `u64` whose range is `0..=18446744073709551615` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:34:12 + --> $DIR/validate-range-endpoints.rs:33:12 | LL | 0..129 => {} | ^^^ this value does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:36:13 + --> $DIR/validate-range-endpoints.rs:35:13 | LL | 0..=128 => {} | ^^^ this value does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:38:9 + --> $DIR/validate-range-endpoints.rs:37:9 | LL | -129..0 => {} | ^^^^ this value does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` - --> $DIR/validate-range-endpoints.rs:40:9 + --> $DIR/validate-range-endpoints.rs:39:9 | LL | -10000..=-20 => {} | ^^^^^^ this value does not fit into the type `i8` whose range is `-128..=127` error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered - --> $DIR/validate-range-endpoints.rs:51:11 + --> $DIR/validate-range-endpoints.rs:50:11 | LL | match 0i8 { | ^^^ patterns `i8::MIN..=-17_i8` and `1_i8..=i8::MAX` not covered @@ -66,7 +66,7 @@ LL + i8::MIN..=-17_i8 | 1_i8..=i8::MAX => todo!() | error[E0004]: non-exhaustive patterns: `i8::MIN..=-17_i8` not covered - --> $DIR/validate-range-endpoints.rs:55:11 + --> $DIR/validate-range-endpoints.rs:54:11 | LL | match 0i8 { | ^^^ pattern `i8::MIN..=-17_i8` not covered diff --git a/tests/ui/methods/assign-to-method.rs b/tests/ui/methods/assign-to-method.rs index 71e40759c848b..58dcca77e62cb 100644 --- a/tests/ui/methods/assign-to-method.rs +++ b/tests/ui/methods/assign-to-method.rs @@ -6,7 +6,7 @@ struct Cat { } impl Cat { - pub fn speak(&self) { self.meows += 1; } + pub fn speak(&mut self) { self.meows += 1; } } fn cat(in_x : usize, in_y : isize) -> Cat { diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr index 2670a3e4755b1..35001ae22a6c7 100644 --- a/tests/ui/methods/issues/issue-61525.stderr +++ b/tests/ui/methods/issues/issue-61525.stderr @@ -7,11 +7,11 @@ LL | 1.query::("") | required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `dyn ToString` -note: required by a bound in `Example::query` +note: required by an implicit `Sized` bound in `Example::query` --> $DIR/issue-61525.rs:2:14 | LL | fn query(self, q: Q); - | ^ required by this bound in `Example::query` + | ^ required by the implicit `Sized` requirement on this type parameter in `Example::query` help: consider relaxing the implicit `Sized` restriction | LL | fn query(self, q: Q); diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr index f431085745405..6df49e432a13a 100644 --- a/tests/ui/methods/method-call-err-msg.stderr +++ b/tests/ui/methods/method-call-err-msg.stderr @@ -63,8 +63,9 @@ LL | | .take() note: the trait `Iterator` must be implemented --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `take`, perhaps you need to implement it: - candidate #1: `Iterator` + = note: the following traits define an item `take`, perhaps you need to implement one of them: + candidate #1: `std::io::Read` + candidate #2: `Iterator` error[E0061]: this method takes 3 arguments but 0 arguments were supplied --> $DIR/method-call-err-msg.rs:21:7 diff --git a/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs index 986fe103cdc79..5a46cf35dec0e 100644 --- a/tests/ui/methods/method-lookup-order.rs +++ b/tests/ui/methods/method-lookup-order.rs @@ -1,6 +1,7 @@ // ignore-tidy-linelength // run-pass +#![allow(dead_code)] // There are five cfg's below. I explored the set of all non-empty combinations // of the below five cfg's, which is 2^5 - 1 = 31 combinations. diff --git a/tests/ui/methods/method-recursive-blanket-impl.rs b/tests/ui/methods/method-recursive-blanket-impl.rs index a2db75b4e85d8..e7e83cbec7756 100644 --- a/tests/ui/methods/method-recursive-blanket-impl.rs +++ b/tests/ui/methods/method-recursive-blanket-impl.rs @@ -11,7 +11,7 @@ use std::marker::Sized; // Note: this must be generic for the problem to show up -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn foo(&self, a: A); } diff --git a/tests/ui/methods/method-recursive-blanket-impl.stderr b/tests/ui/methods/method-recursive-blanket-impl.stderr new file mode 100644 index 0000000000000..9797a8f6c8308 --- /dev/null +++ b/tests/ui/methods/method-recursive-blanket-impl.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/method-recursive-blanket-impl.rs:14:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/methods/method-two-trait-defer-resolution-2.rs b/tests/ui/methods/method-two-trait-defer-resolution-2.rs index fc5766da9714b..d6076126732bc 100644 --- a/tests/ui/methods/method-two-trait-defer-resolution-2.rs +++ b/tests/ui/methods/method-two-trait-defer-resolution-2.rs @@ -14,7 +14,7 @@ trait Foo { fn foo(&self) -> isize; } -trait MyCopy { fn foo(&self) { } } +trait MyCopy { fn foo(&self) { } } //~ WARN method `foo` is never used impl MyCopy for i32 { } impl Foo for Vec { diff --git a/tests/ui/methods/method-two-trait-defer-resolution-2.stderr b/tests/ui/methods/method-two-trait-defer-resolution-2.stderr new file mode 100644 index 0000000000000..4501ea5d24334 --- /dev/null +++ b/tests/ui/methods/method-two-trait-defer-resolution-2.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/method-two-trait-defer-resolution-2.rs:17:19 + | +LL | trait MyCopy { fn foo(&self) { } } + | ------ ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs index d820d2ad08ae8..2fd6c3bfab868 100644 --- a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs +++ b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs @@ -4,7 +4,7 @@ // pretty-expanded FIXME #23616 -trait A { +trait A { //~ WARN trait `A` is never used fn foo(self); } diff --git a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr new file mode 100644 index 0000000000000..0a60c6242bb2d --- /dev/null +++ b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr @@ -0,0 +1,10 @@ +warning: trait `A` is never used + --> $DIR/method-two-traits-distinguished-via-where-clause.rs:7:7 + | +LL | trait A { + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.rs b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs index 624b464ecef25..cbca3eebf19d1 100644 --- a/tests/ui/mir/drop-elaboration-after-borrowck-error.rs +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -6,7 +6,6 @@ static A: () = { //~^ ERROR destructor of a[0] = String::new(); //~^ ERROR destructor of - //~| ERROR binding `a` isn't initialized }; struct B([T; 1]); @@ -17,7 +16,6 @@ impl B { //~^ ERROR destructor of self.0[0] = other; //~^ ERROR destructor of - //~| ERROR use of moved value self } } diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr index d961061729d4c..22d05fa4ddab0 100644 --- a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -16,22 +16,8 @@ LL | let a: [String; 1]; LL | }; | - value is dropped here -error[E0381]: used binding `a` isn't initialized - --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 - | -LL | let a: [String; 1]; - | - binding declared here but left uninitialized -LL | -LL | a[0] = String::new(); - | ^^^^ `a` used here but it isn't initialized - | -help: consider assigning a value - | -LL | let a: [String; 1] = todo!(); - | +++++++++ - error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 + --> $DIR/drop-elaboration-after-borrowck-error.rs:17:9 | LL | self.0[0] = other; | ^^^^^^^^^ @@ -40,7 +26,7 @@ LL | self.0[0] = other; | value is dropped here error[E0493]: destructor of `B` cannot be evaluated at compile-time - --> $DIR/drop-elaboration-after-borrowck-error.rs:16:13 + --> $DIR/drop-elaboration-after-borrowck-error.rs:15:13 | LL | let _this = self; | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -48,18 +34,6 @@ LL | let _this = self; LL | } | - value is dropped here -error[E0382]: use of moved value: `self.0` - --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 - | -LL | pub const fn f(mut self, other: T) -> Self { - | -------- move occurs because `self` has type `B`, which does not implement the `Copy` trait -LL | let _this = self; - | ---- value moved here -LL | -LL | self.0[0] = other; - | ^^^^^^^^^ value used here after move - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0381, E0382, E0493. -For more information about an error, try `rustc --explain E0381`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs index 8e5a2043dc696..e141aa03aa985 100644 --- a/tests/ui/mir/mir_raw_fat_ptr.rs +++ b/tests/ui/mir/mir_raw_fat_ptr.rs @@ -98,7 +98,7 @@ fn assert_inorder(a: &[T], } } -trait Foo { fn foo(&self) -> usize; } +trait Foo { fn foo(&self) -> usize; } //~ WARN method `foo` is never used impl Foo for T { fn foo(&self) -> usize { mem::size_of::() diff --git a/tests/ui/mir/mir_raw_fat_ptr.stderr b/tests/ui/mir/mir_raw_fat_ptr.stderr new file mode 100644 index 0000000000000..a9e9dd66ebdfa --- /dev/null +++ b/tests/ui/mir/mir_raw_fat_ptr.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/mir_raw_fat_ptr.rs:101:16 + | +LL | trait Foo { fn foo(&self) -> usize; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mir/validate/error-body.rs b/tests/ui/mir/validate/error-body.rs new file mode 100644 index 0000000000000..5b2fbb0b04699 --- /dev/null +++ b/tests/ui/mir/validate/error-body.rs @@ -0,0 +1,9 @@ +// compile-flags: -Zvalidate-mir + +fn _test() { + let x = || 45; + missing(); + //~^ ERROR cannot find function `missing` in this scope +} + +fn main() {} diff --git a/tests/ui/mir/validate/error-body.stderr b/tests/ui/mir/validate/error-body.stderr new file mode 100644 index 0000000000000..1dfeaf0b7e2cb --- /dev/null +++ b/tests/ui/mir/validate/error-body.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `missing` in this scope + --> $DIR/error-body.rs:5:5 + | +LL | missing(); + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/mismatched_types/E0631.stderr b/tests/ui/mismatched_types/E0631.stderr index 9ba8f5035c5f6..dcd66c28e3cfb 100644 --- a/tests/ui/mismatched_types/E0631.stderr +++ b/tests/ui/mismatched_types/E0631.stderr @@ -2,8 +2,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:7:5 | LL | foo(|_: isize| {}); - | ^^^ ---------- found signature defined here - | | + | ^^^^----------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `fn(usize) -> _` @@ -18,8 +19,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/E0631.rs:8:5 | LL | bar(|_: isize| {}); - | ^^^ ---------- found signature defined here - | | + | ^^^^----------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `fn(usize) -> _` diff --git a/tests/ui/mismatched_types/closure-arg-count.stderr b/tests/ui/mismatched_types/closure-arg-count.stderr index 2ecab9f024a12..0e2ca8feec545 100644 --- a/tests/ui/mismatched_types/closure-arg-count.stderr +++ b/tests/ui/mismatched_types/closure-arg-count.stderr @@ -49,8 +49,9 @@ error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:13:5 | LL | f(|| panic!()); - | ^ -- takes 0 arguments - | | + | ^^--^^^^^^^^^^ + | | | + | | takes 0 arguments | expected closure that takes 1 argument | note: required by a bound in `f` @@ -67,8 +68,9 @@ error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:15:5 | LL | f( move || panic!()); - | ^ ---------- takes 0 arguments - | | + | ^^^^----------^^^^^^^^^^ + | | | + | | takes 0 arguments | expected closure that takes 1 argument | note: required by a bound in `f` diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs index 98abb0ba97951..e73a33dfded7c 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -8,4 +8,7 @@ fn main() { fn baz(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { baz(f); + //~^ ERROR: mismatched types + //~| ERROR: borrowed data escapes + //~| ERROR: not general enough } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index e9808b8699186..e63d3f6a075db 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -41,6 +41,52 @@ LL | a.iter().map(|_: (u16, u16)| 45); note: required by a bound in `map` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | -- - `f` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | baz(f); + | ^^^^^^ + | | + | `f` escapes the function body here + | argument requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `&u32` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Fn(*mut &'a u32)` + found trait `Fn(*mut &u32)` +note: the lifetime requirement is introduced here + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | ^^^^^^^^^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0631`. +Some errors have detailed explanations: E0308, E0521, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr index 0d203c1aacba4..d5405c6576a8b 100644 --- a/tests/ui/modules/issue-107649.stderr +++ b/tests/ui/modules/issue-107649.stderr @@ -4,7 +4,7 @@ error[E0277]: `Dummy` doesn't implement `Debug` 105 | dbg!(lib::Dummy); | ^^^^^^^^^^^^^^^^ `Dummy` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `Dummy` + = help: the trait `Debug` is not implemented for `Dummy`, which is required by `&Dummy: Debug` = note: add `#[derive(Debug)]` to `Dummy` or manually `impl Debug for Dummy` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Dummy` with `#[derive(Debug)]` diff --git a/tests/ui/moves/issue-22536-copy-mustnt-zero.rs b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs index 017f36484c1cf..b3fc1a56f882f 100644 --- a/tests/ui/moves/issue-22536-copy-mustnt-zero.rs +++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs @@ -5,7 +5,7 @@ trait Resources { type Buffer: Copy; - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } struct BufferHandle { diff --git a/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr b/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr new file mode 100644 index 0000000000000..b1fcdfa44c33d --- /dev/null +++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr @@ -0,0 +1,13 @@ +warning: method `foo` is never used + --> $DIR/issue-22536-copy-mustnt-zero.rs:8:8 + | +LL | trait Resources { + | --------- method in this trait +LL | type Buffer: Copy; +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mut/mutable-enum-indirect.stderr b/tests/ui/mut/mutable-enum-indirect.stderr index 0b7783b3318b1..d7af327df5a33 100644 --- a/tests/ui/mut/mutable-enum-indirect.stderr +++ b/tests/ui/mut/mutable-enum-indirect.stderr @@ -6,7 +6,7 @@ LL | bar(&x); | | | required by a bound introduced by this call | - = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync` + = help: within `&Foo`, the trait `Sync` is not implemented for `NoSync`, which is required by `&Foo: Sync` note: required because it appears within the type `Foo` --> $DIR/mutable-enum-indirect.rs:11:6 | diff --git a/tests/ui/never_type/never-type-in-nested-fn-decl.rs b/tests/ui/never_type/never-type-in-nested-fn-decl.rs new file mode 100644 index 0000000000000..df546c4717eb6 --- /dev/null +++ b/tests/ui/never_type/never-type-in-nested-fn-decl.rs @@ -0,0 +1,7 @@ +// build-pass + +trait X {} + +fn hello ! { loop {} } 1 }>>() {} + +fn main() {} diff --git a/tests/ui/nll/continue-after-missing-main.rs b/tests/ui/nll/continue-after-missing-main.rs index 778639158d7f9..5968364878994 100644 --- a/tests/ui/nll/continue-after-missing-main.rs +++ b/tests/ui/nll/continue-after-missing-main.rs @@ -26,4 +26,6 @@ fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>, ) { let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + //~^ ERROR: lifetime may not live long enough + //~| ERROR: `tableau` does not live long enough } //~ ERROR `main` function not found in crate diff --git a/tests/ui/nll/continue-after-missing-main.stderr b/tests/ui/nll/continue-after-missing-main.stderr index 960503e8fd5bf..5178d1b7ee25e 100644 --- a/tests/ui/nll/continue-after-missing-main.stderr +++ b/tests/ui/nll/continue-after-missing-main.stderr @@ -1,9 +1,39 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` - --> $DIR/continue-after-missing-main.rs:29:2 + --> $DIR/continue-after-missing-main.rs:31:2 | LL | } | ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/continue-after-missing-main.rs:28:12 + | +LL | fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( + | -------------- -------------- lifetime `'original_data` defined here + | | + | lifetime `'data_provider` defined here +... +LL | let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'data_provider` must outlive `'original_data` + | + = help: consider adding the following bound: `'data_provider: 'original_data` + +error[E0597]: `tableau` does not live long enough + --> $DIR/continue-after-missing-main.rs:28:56 + | +LL | fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( + | -------------- lifetime `'original_data` defined here +LL | tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>, + | ------- binding `tableau` declared here +LL | ) { +LL | let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + | ----------------------------------------- ^^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `tableau` is borrowed for `'original_data` +... +LL | } + | - `tableau` dropped here while still borrowed + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0601`. +Some errors have detailed explanations: E0597, E0601. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/no-send-res-ports.stderr b/tests/ui/no-send-res-ports.stderr index 9c30261e5cb73..c71d8ecba371c 100644 --- a/tests/ui/no-send-res-ports.stderr +++ b/tests/ui/no-send-res-ports.stderr @@ -13,7 +13,7 @@ LL | | println!("{:?}", y); LL | | }); | |_____^ `Rc<()>` cannot be sent between threads safely | - = help: within `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}`, the trait `Send` is not implemented for `Rc<()>` + = help: within `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}`, the trait `Send` is not implemented for `Rc<()>`, which is required by `{closure@$DIR/no-send-res-ports.rs:25:19: 25:25}: Send` note: required because it appears within the type `Port<()>` --> $DIR/no-send-res-ports.rs:5:8 | diff --git a/tests/ui/no_send-enum.stderr b/tests/ui/no_send-enum.stderr index 3b66c7db545e1..e24f79c7dd6aa 100644 --- a/tests/ui/no_send-enum.stderr +++ b/tests/ui/no_send-enum.stderr @@ -6,7 +6,7 @@ LL | bar(x); | | | required by a bound introduced by this call | - = help: within `Foo`, the trait `Send` is not implemented for `NoSend` + = help: within `Foo`, the trait `Send` is not implemented for `NoSend`, which is required by `Foo: Send` note: required because it appears within the type `Foo` --> $DIR/no_send-enum.rs:8:6 | diff --git a/tests/ui/no_share-enum.stderr b/tests/ui/no_share-enum.stderr index 89939216d5b16..5b6c8bf0b4fd9 100644 --- a/tests/ui/no_share-enum.stderr +++ b/tests/ui/no_share-enum.stderr @@ -6,7 +6,7 @@ LL | bar(x); | | | required by a bound introduced by this call | - = help: within `Foo`, the trait `Sync` is not implemented for `NoSync` + = help: within `Foo`, the trait `Sync` is not implemented for `NoSync`, which is required by `Foo: Sync` note: required because it appears within the type `Foo` --> $DIR/no_share-enum.rs:8:6 | diff --git a/tests/ui/not-clone-closure.stderr b/tests/ui/not-clone-closure.stderr index 783c165eeb21c..9b557b1558290 100644 --- a/tests/ui/not-clone-closure.stderr +++ b/tests/ui/not-clone-closure.stderr @@ -5,7 +5,7 @@ LL | let hello = move || { | ------- within this `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}` ... LL | let hello = hello.clone(); - | ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S` + | ^^^^^ within `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}`, the trait `Clone` is not implemented for `S`, which is required by `{closure@$DIR/not-clone-closure.rs:7:17: 7:24}: Clone` | note: required because it's used within this closure --> $DIR/not-clone-closure.rs:7:17 diff --git a/tests/ui/not-panic/not-panic-safe-2.stderr b/tests/ui/not-panic/not-panic-safe-2.stderr index 0c399f15a25bb..8c4cf9c98ed61 100644 --- a/tests/ui/not-panic/not-panic-safe-2.stderr +++ b/tests/ui/not-panic/not-panic-safe-2.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::>>(); | ^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Rc>: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `Rc>` to implement `UnwindSafe` @@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::>>(); | ^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Rc>: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/not-panic/not-panic-safe-3.stderr b/tests/ui/not-panic/not-panic-safe-3.stderr index 53028d6a3371a..2373ada63f66d 100644 --- a/tests/ui/not-panic/not-panic-safe-3.stderr +++ b/tests/ui/not-panic/not-panic-safe-3.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::>>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Arc>: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `Arc>` to implement `UnwindSafe` @@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::>>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `Arc>: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/not-panic/not-panic-safe-4.stderr b/tests/ui/not-panic/not-panic-safe-4.stderr index b1361cfd87ef2..d77cac8f272d0 100644 --- a/tests/ui/not-panic/not-panic-safe-4.stderr +++ b/tests/ui/not-panic/not-panic-safe-4.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `&RefCell: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `&RefCell` to implement `UnwindSafe` @@ -25,7 +25,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::<&RefCell>(); | ^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `&RefCell: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/not-panic/not-panic-safe-5.stderr b/tests/ui/not-panic/not-panic-safe-5.stderr index fbbd81d6d4c53..0de9a2cc0cd93 100644 --- a/tests/ui/not-panic/not-panic-safe-5.stderr +++ b/tests/ui/not-panic/not-panic-safe-5.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::<*const UnsafeCell>(); | ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `*const UnsafeCell: UnwindSafe` = note: required for `*const UnsafeCell` to implement `UnwindSafe` note: required by a bound in `assert` --> $DIR/not-panic-safe-5.rs:6:14 diff --git a/tests/ui/not-panic/not-panic-safe-6.stderr b/tests/ui/not-panic/not-panic-safe-6.stderr index 47f28257409eb..7714a577f8a25 100644 --- a/tests/ui/not-panic/not-panic-safe-6.stderr +++ b/tests/ui/not-panic/not-panic-safe-6.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a r LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `*mut RefCell: UnwindSafe` note: required because it appears within the type `RefCell` --> $SRC_DIR/core/src/cell.rs:LL:COL = note: required for `*mut RefCell` to implement `UnwindSafe` @@ -20,7 +20,7 @@ error[E0277]: the type `UnsafeCell` may contain interior mutability and a LL | assert::<*mut RefCell>(); | ^^^^^^^^^^^^^^^^^ `UnsafeCell` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary | - = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` + = help: within `RefCell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell`, which is required by `*mut RefCell: UnwindSafe` note: required because it appears within the type `Cell` --> $SRC_DIR/core/src/cell.rs:LL:COL note: required because it appears within the type `RefCell` diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed index 45c7e07a26471..52046a8ab693d 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait TraitWithAType { type Item: ?Sized; } diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs index c3e958f498390..96620c0abda34 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait TraitWithAType { type Item; } diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr index cd2aa9fdbe3e4..9bb770ce43199 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr @@ -1,12 +1,12 @@ error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/assoc_type_bounds_implicit_sized.rs:8:17 + --> $DIR/assoc_type_bounds_implicit_sized.rs:9:17 | LL | type Item = dyn Trait; | ^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)` note: required by a bound in `TraitWithAType::Item` - --> $DIR/assoc_type_bounds_implicit_sized.rs:3:5 + --> $DIR/assoc_type_bounds_implicit_sized.rs:4:5 | LL | type Item; | ^^^^^^^^^^ required by this bound in `TraitWithAType::Item` diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs index 800624e3124b6..34daa81e48ea5 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs @@ -8,8 +8,6 @@ trait Foo { fn foo(_: &dyn Foo) {} //~^ WARN: unnecessary associated type bound for not object safe associated type -//~| WARN: unnecessary associated type bound for not object safe associated type -//~| WARN: unnecessary associated type bound for not object safe associated type #[allow(unused_associated_type_bounds)] fn bar(_: &dyn Foo) {} diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr index 659679e444095..f2bc8bd8400ce 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr @@ -7,23 +7,5 @@ LL | fn foo(_: &dyn Foo) {} = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. = note: `#[warn(unused_associated_type_bounds)]` on by default -warning: unnecessary associated type bound for not object safe associated type - --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 - | -LL | fn foo(_: &dyn Foo) {} - | ^^^^^^^^ help: remove this bound - | - = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unnecessary associated type bound for not object safe associated type - --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 - | -LL | fn foo(_: &dyn Foo) {} - | ^^^^^^^^ help: remove this bound - | - = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr index 22adc19c8029f..e7fcdbd0c9c53 100644 --- a/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr +++ b/tests/ui/object-safety/object-safety-supertrait-mentions-Self.stderr @@ -22,11 +22,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | trait Baz : Bar { | ^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Bar` +note: required by an implicit `Sized` bound in `Bar` --> $DIR/object-safety-supertrait-mentions-Self.rs:4:11 | LL | trait Bar { - | ^ required by this bound in `Bar` + | ^ required by the implicit `Sized` requirement on this type parameter in `Bar` help: consider further restricting `Self` | LL | trait Baz : Bar + Sized { diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr index 658678dc4ed3c..753ba809e7da1 100644 --- a/tests/ui/offset-of/offset-of-dst-field.stderr +++ b/tests/ui/offset-of/offset-of-dst-field.stderr @@ -40,7 +40,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | offset_of!(Delta, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]` + = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`, which is required by `Alpha: Sized` note: required because it appears within the type `Alpha` --> $DIR/offset-of-dst-field.rs:5:8 | diff --git a/tests/ui/on-unimplemented/multiple-impls.rs b/tests/ui/on-unimplemented/multiple-impls.rs index a32fd4566231d..b74957ebcd406 100644 --- a/tests/ui/on-unimplemented/multiple-impls.rs +++ b/tests/ui/on-unimplemented/multiple-impls.rs @@ -33,13 +33,10 @@ fn main() { Index::index(&[] as &[i32], 2u32); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 Index::index(&[] as &[i32], Foo(2u32)); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 Index::index(&[] as &[i32], Bar(2u32)); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 } diff --git a/tests/ui/on-unimplemented/multiple-impls.stderr b/tests/ui/on-unimplemented/multiple-impls.stderr index 3d0e36db75215..f59c93a7c375e 100644 --- a/tests/ui/on-unimplemented/multiple-impls.stderr +++ b/tests/ui/on-unimplemented/multiple-impls.stderr @@ -11,19 +11,8 @@ LL | Index::index(&[] as &[i32], 2u32); <[i32] as Index>> <[i32] as Index>> -error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/multiple-impls.rs:33:5 - | -LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message - | - = help: the trait `Index` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:37:33 + --> $DIR/multiple-impls.rs:36:33 | LL | Index::index(&[] as &[i32], Foo(2u32)); | ------------ ^^^^^^^^^ on impl for Foo @@ -35,19 +24,8 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); <[i32] as Index>> <[i32] as Index>> -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:37:5 - | -LL | Index::index(&[] as &[i32], Foo(2u32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo - | - = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:41:33 + --> $DIR/multiple-impls.rs:39:33 | LL | Index::index(&[] as &[i32], Bar(2u32)); | ------------ ^^^^^^^^^ on impl for Bar @@ -59,22 +37,11 @@ LL | Index::index(&[] as &[i32], Bar(2u32)); <[i32] as Index>> <[i32] as Index>> -error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:41:5 - | -LL | Index::index(&[] as &[i32], Bar(2u32)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar - | - = help: the trait `Index>` is not implemented for `[i32]` - = help: the following other types implement trait `Index`: - <[i32] as Index>> - <[i32] as Index>> - error[E0277]: the trait bound `[i32]: Index` is not satisfied --> $DIR/multiple-impls.rs:33:5 | LL | Index::index(&[] as &[i32], 2u32); - | ^^^^^^^^^^^^ trait message + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message | = help: the trait `Index` is not implemented for `[i32]` = help: the following other types implement trait `Index`: @@ -82,10 +49,10 @@ LL | Index::index(&[] as &[i32], 2u32); <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:37:5 + --> $DIR/multiple-impls.rs:36:5 | LL | Index::index(&[] as &[i32], Foo(2u32)); - | ^^^^^^^^^^^^ on impl for Foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo | = help: the trait `Index>` is not implemented for `[i32]` = help: the following other types implement trait `Index`: @@ -93,16 +60,16 @@ LL | Index::index(&[] as &[i32], Foo(2u32)); <[i32] as Index>> error[E0277]: the trait bound `[i32]: Index>` is not satisfied - --> $DIR/multiple-impls.rs:41:5 + --> $DIR/multiple-impls.rs:39:5 | LL | Index::index(&[] as &[i32], Bar(2u32)); - | ^^^^^^^^^^^^ on impl for Bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar | = help: the trait `Index>` is not implemented for `[i32]` = help: the following other types implement trait `Index`: <[i32] as Index>> <[i32] as Index>> -error: aborting due to 9 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/on-impl.rs b/tests/ui/on-unimplemented/on-impl.rs index d0537810ce11e..ab3e67d01fe44 100644 --- a/tests/ui/on-unimplemented/on-impl.rs +++ b/tests/ui/on-unimplemented/on-impl.rs @@ -22,5 +22,4 @@ fn main() { Index::::index(&[1, 2, 3] as &[i32], 2u32); //~^ ERROR E0277 //~| ERROR E0277 - //~| ERROR E0277 } diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr index 3a0b8353fa5eb..c7d2a78af6cba 100644 --- a/tests/ui/on-unimplemented/on-impl.stderr +++ b/tests/ui/on-unimplemented/on-impl.stderr @@ -20,16 +20,6 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); = help: the trait `Index` is implemented for `[i32]` = help: for that trait implementation, expected `usize`, found `u32` -error[E0277]: the trait bound `[i32]: Index` is not satisfied - --> $DIR/on-impl.rs:22:5 - | -LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); - | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice - | - = help: the trait `Index` is not implemented for `[i32]` - = help: the trait `Index` is implemented for `[i32]` - = help: for that trait implementation, expected `usize`, found `u32` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/on-unimplemented/on-trait.stderr b/tests/ui/on-unimplemented/on-trait.stderr index 4847a1a5a6119..4097ee1350dbc 100644 --- a/tests/ui/on-unimplemented/on-trait.stderr +++ b/tests/ui/on-unimplemented/on-trait.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Option>: MyFromIterator<&u8>` is not sati --> $DIR/on-trait.rs:28:30 | LL | let y: Option> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() - | ^^^^^^^ a collection of type `Option>` cannot be built from an iterator over elements of type `&u8` + | ^^^^^^^^^^^^^^^^^ a collection of type `Option>` cannot be built from an iterator over elements of type `&u8` | = help: the trait `MyFromIterator<&u8>` is not implemented for `Option>` help: this trait has no implementations, consider adding one @@ -20,7 +20,7 @@ error[E0277]: the trait bound `String: Foo` is not satisfied --> $DIR/on-trait.rs:31:21 | LL | let x: String = foobar(); - | ^^^^^^ test error `String` with `u8` `_` `u32` in `Foo` + | ^^^^^^^^ test error `String` with `u8` `_` `u32` in `Foo` | = help: the trait `Foo` is not implemented for `String` help: this trait has no implementations, consider adding one diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index 5e0117be5295c..c0314fa42d721 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[i32]` cannot be indexed by `i32` LL | x[1i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` + = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`, which is required by `[i32]: Index<_>` = help: the trait `SliceIndex<[i32]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[i32]` to implement `Index` @@ -15,7 +15,7 @@ error[E0277]: the type `[i32]` cannot be indexed by `RangeTo` LL | x[..1i32]; | ^^^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo` + = help: the trait `SliceIndex<[i32]>` is not implemented for `RangeTo`, which is required by `[i32]: Index<_>` = help: the following other types implement trait `SliceIndex`: as SliceIndex> as SliceIndex<[T]>> diff --git a/tests/ui/or-patterns/missing-bindings.rs b/tests/ui/or-patterns/missing-bindings.rs index 7c26012c0e93d..20844c17ec1a3 100644 --- a/tests/ui/or-patterns/missing-bindings.rs +++ b/tests/ui/or-patterns/missing-bindings.rs @@ -17,8 +17,10 @@ fn check_handling_of_paths() { use bar::foo::{alpha, charlie}; let (alpha | beta | charlie) = alpha; //~ ERROR variable `beta` is not bound in all patterns - match Some(alpha) { + //~^ ERROR: `beta` is named the same as one of the variants + match Some(alpha) { //~ ERROR `None` not covered Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns + //~^ ERROR: `beta` is named the same as one of the variants } } diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr index 7f182a857871d..677b40a7f0dc1 100644 --- a/tests/ui/or-patterns/missing-bindings.stderr +++ b/tests/ui/or-patterns/missing-bindings.stderr @@ -8,7 +8,7 @@ LL | let (alpha | beta | charlie) = alpha; | pattern doesn't bind `beta` error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/missing-bindings.rs:21:14 + --> $DIR/missing-bindings.rs:22:14 | LL | Some(alpha | beta) => {} | ^^^^^ ---- variable not in all patterns @@ -16,7 +16,7 @@ LL | Some(alpha | beta) => {} | pattern doesn't bind `beta` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:33:20 + --> $DIR/missing-bindings.rs:35:20 | LL | let (A(a, _) | _) = X; | - ^ pattern doesn't bind `a` @@ -24,7 +24,7 @@ LL | let (A(a, _) | _) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:34:10 + --> $DIR/missing-bindings.rs:36:10 | LL | let (_ | B(a)) = X; | ^ - variable not in all patterns @@ -32,7 +32,7 @@ LL | let (_ | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:35:10 + --> $DIR/missing-bindings.rs:37:10 | LL | let (A(..) | B(a)) = X; | ^^^^^ - variable not in all patterns @@ -40,7 +40,7 @@ LL | let (A(..) | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:36:20 + --> $DIR/missing-bindings.rs:38:20 | LL | let (A(a, _) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -48,7 +48,7 @@ LL | let (A(a, _) | B(_)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:37:20 + --> $DIR/missing-bindings.rs:39:20 | LL | let (A(_, a) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -56,7 +56,7 @@ LL | let (A(_, a) | B(_)) = X; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:38:20 + --> $DIR/missing-bindings.rs:40:20 | LL | let (A(a, b) | B(a)) = X; | - ^^^^ pattern doesn't bind `b` @@ -64,7 +64,7 @@ LL | let (A(a, b) | B(a)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:42:10 + --> $DIR/missing-bindings.rs:44:10 | LL | let (A(A(..) | B(_), _) | B(a)) = Y; | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -72,7 +72,7 @@ LL | let (A(A(..) | B(_), _) | B(a)) = Y; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:43:12 + --> $DIR/missing-bindings.rs:45:12 | LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | ^^^^^ - variable not in all patterns @@ -80,7 +80,7 @@ LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | pattern doesn't bind `a` error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:12 + --> $DIR/missing-bindings.rs:47:12 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^ - variable not in all patterns @@ -88,7 +88,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `c` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:22 + --> $DIR/missing-bindings.rs:47:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -96,7 +96,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:22 + --> $DIR/missing-bindings.rs:47:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -104,7 +104,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `e` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:10 + --> $DIR/missing-bindings.rs:47:10 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -112,7 +112,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `e` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -120,7 +120,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -128,7 +128,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `c` @@ -136,7 +136,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `d` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `d` @@ -144,7 +144,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:61:29 + --> $DIR/missing-bindings.rs:63:29 | LL | Ok(a) | Err(_), | - ^^^^^^ pattern doesn't bind `a` @@ -152,7 +152,7 @@ LL | Ok(a) | Err(_), | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:68:21 + --> $DIR/missing-bindings.rs:70:21 | LL | A(_, a) | | ^^^^^^^ pattern doesn't bind `b` @@ -160,7 +160,7 @@ LL | B(b), | - variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:69:21 + --> $DIR/missing-bindings.rs:71:21 | LL | A(_, a) | | - variable not in all patterns @@ -168,7 +168,7 @@ LL | B(b), | ^^^^ pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:72:17 + --> $DIR/missing-bindings.rs:74:17 | LL | A(_, a) | | - variable not in all patterns @@ -177,7 +177,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `a` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:72:17 + --> $DIR/missing-bindings.rs:74:17 | LL | B(b), | - variable not in all patterns @@ -186,7 +186,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `b` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 + --> $DIR/missing-bindings.rs:59:13 | LL | / V1( LL | | @@ -204,7 +204,7 @@ LL | V3(c), | ^^^^^ pattern doesn't bind `b` error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 + --> $DIR/missing-bindings.rs:59:13 | LL | / V1( LL | | @@ -226,7 +226,7 @@ LL | V3(c), | - variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:76:13 + --> $DIR/missing-bindings.rs:78:13 | LL | B(Ok(a) | Err(a)) | - variable not in all patterns @@ -237,6 +237,38 @@ LL | A(_, a) | LL | V3(c), | ^^^^^ pattern doesn't bind `a` -error: aborting due to 26 previous errors +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `check_handling_of_paths::bar::foo` + --> $DIR/missing-bindings.rs:19:18 + | +LL | let (alpha | beta | charlie) = alpha; + | ^^^^ + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `check_handling_of_paths::bar::foo` + --> $DIR/missing-bindings.rs:22:22 + | +LL | Some(alpha | beta) => {} + | ^^^^ help: to match on the variant, qualify the path: `check_handling_of_paths::bar::foo::beta` + +error[E0004]: non-exhaustive patterns: `None` not covered + --> $DIR/missing-bindings.rs:21:11 + | +LL | match Some(alpha) { + | ^^^^^^^^^^^ pattern `None` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | Some(alpha | beta) => {}, None => todo!() + | +++++++++++++++++ + +error: aborting due to 29 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0004, E0170, E0408. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/overloaded/issue-14958.rs b/tests/ui/overloaded/issue-14958.rs index a12564ca9c0ee..80abf5e4e7689 100644 --- a/tests/ui/overloaded/issue-14958.rs +++ b/tests/ui/overloaded/issue-14958.rs @@ -3,7 +3,7 @@ #![feature(fn_traits, unboxed_closures)] -trait Foo { fn dummy(&self) { }} +trait Foo { fn dummy(&self) { }} //~ WARN method `dummy` is never used struct Bar; diff --git a/tests/ui/overloaded/issue-14958.stderr b/tests/ui/overloaded/issue-14958.stderr new file mode 100644 index 0000000000000..cc97730239c30 --- /dev/null +++ b/tests/ui/overloaded/issue-14958.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-14958.rs:6:16 + | +LL | trait Foo { fn dummy(&self) { }} + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/overloaded/overloaded-index-in-field.rs b/tests/ui/overloaded/overloaded-index-in-field.rs index 8a1fa7deb9996..0dc45ea8ca2b8 100644 --- a/tests/ui/overloaded/overloaded-index-in-field.rs +++ b/tests/ui/overloaded/overloaded-index-in-field.rs @@ -27,7 +27,7 @@ impl Index for Foo { trait Int { fn get(self) -> isize; - fn get_from_ref(&self) -> isize; + fn get_from_ref(&self) -> isize; //~ WARN methods `get_from_ref` and `inc` are never used fn inc(&mut self); } diff --git a/tests/ui/overloaded/overloaded-index-in-field.stderr b/tests/ui/overloaded/overloaded-index-in-field.stderr new file mode 100644 index 0000000000000..10c0a3faeb59a --- /dev/null +++ b/tests/ui/overloaded/overloaded-index-in-field.stderr @@ -0,0 +1,15 @@ +warning: methods `get_from_ref` and `inc` are never used + --> $DIR/overloaded-index-in-field.rs:30:8 + | +LL | trait Int { + | --- methods in this trait +LL | fn get(self) -> isize; +LL | fn get_from_ref(&self) -> isize; + | ^^^^^^^^^^^^ +LL | fn inc(&mut self); + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/panic-handler/panic-handler-requires-panic-info.rs b/tests/ui/panic-handler/panic-handler-requires-panic-info.rs index f13c12fc52e4e..b59023b50e1e0 100644 --- a/tests/ui/panic-handler/panic-handler-requires-panic-info.rs +++ b/tests/ui/panic-handler/panic-handler-requires-panic-info.rs @@ -1,5 +1,4 @@ // compile-flags:-C panic=abort -// error-pattern: language item required, but not found: `panic_info` #![feature(lang_items)] #![feature(no_core)] @@ -8,6 +7,7 @@ #[panic_handler] fn panic() -> ! { + //~^ ERROR requires `panic_info` lang_item loop {} } diff --git a/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr index 06ff8e3098aa4..873f61a51632b 100644 --- a/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr +++ b/tests/ui/panic-handler/panic-handler-requires-panic-info.stderr @@ -1,4 +1,8 @@ -error: language item required, but not found: `panic_info` +error: requires `panic_info` lang_item + --> $DIR/panic-handler-requires-panic-info.rs:9:1 + | +LL | fn panic() -> ! { + | ^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs new file mode 100644 index 0000000000000..148a59240f99a --- /dev/null +++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs @@ -0,0 +1,16 @@ +// compile-flags: -Z threads=16 +// build-fail + +#![crate_type="rlib"] +#![allow(warnings)] + +#[export_name="fail"] +pub fn a() { +} + +#[export_name="fail"] +pub fn b() { +//~^ Error symbol `fail` is already defined +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr new file mode 100644 index 0000000000000..7963165e31b0a --- /dev/null +++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/cache-after-waiting-issue-111528.rs:12:1 + | +LL | pub fn b() { + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs new file mode 100644 index 0000000000000..8240b249018e2 --- /dev/null +++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs @@ -0,0 +1,7 @@ +// compile-flags:-C extra-filename=-1 -Z threads=16 +// no-prefer-dynamic +// build-pass +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs new file mode 100644 index 0000000000000..691c36cfc9ec4 --- /dev/null +++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs @@ -0,0 +1,22 @@ +// compile-flags: -Z threads=16 +// build-pass + +pub static GLOBAL: isize = 3; + +static GLOBAL0: isize = 4; + +pub static GLOBAL2: &'static isize = &GLOBAL0; + +pub fn verify_same(a: &'static isize) { + let a = a as *const isize as usize; + let b = &GLOBAL as *const isize as usize; + assert_eq!(a, b); +} + +pub fn verify_same2(a: &'static isize) { + let a = a as *const isize as usize; + let b = GLOBAL2 as *const isize as usize; + assert_eq!(a, b); +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/hello_world.rs b/tests/ui/parallel-rustc/hello_world.rs new file mode 100644 index 0000000000000..53e95c890ef52 --- /dev/null +++ b/tests/ui/parallel-rustc/hello_world.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z threads=8 +// run-pass + +fn main() { + println!("Hello world!"); +} diff --git a/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs new file mode 100644 index 0000000000000..1907348cf09dc --- /dev/null +++ b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z threads=16 +// run-pass + +#[repr(transparent)] +struct Sched { + i: i32, +} +impl Sched { + extern "C" fn get(self) -> i32 { self.i } +} + +fn main() { + let s = Sched { i: 4 }; + let f = || -> i32 { + s.get() + }; + println!("f: {}", f()); +} diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index a42e8c41c2efd..c3126a493e546 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -5,6 +5,7 @@ fn a() { let foo = { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -23,6 +24,7 @@ fn b() { fn c() { let foo = if true { + //~^ WARN irrefutable `let...else` pattern 1 } else { 0 @@ -43,6 +45,7 @@ fn d() { fn e() { let foo = match true { + //~^ WARN irrefutable `let...else` pattern true => 1, false => 0 } else { @@ -54,6 +57,7 @@ fn e() { struct X {a: i32} fn f() { let foo = X { + //~^ WARN irrefutable `let...else` pattern a: 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -72,6 +76,7 @@ fn g() { fn h() { let foo = const { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -81,6 +86,7 @@ fn h() { fn i() { let foo = &{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -90,7 +96,8 @@ fn i() { fn j() { let bar = 0; - let foo = bar = { + let foo = bar = { //~ ERROR: cannot assign twice + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -100,6 +107,7 @@ fn j() { fn k() { let foo = 1 + { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -109,6 +117,7 @@ fn k() { fn l() { let foo = 1..{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -118,6 +127,7 @@ fn l() { fn m() { let foo = return { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -127,6 +137,7 @@ fn m() { fn n() { let foo = -{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -136,6 +147,7 @@ fn n() { fn o() -> Result<(), ()> { let foo = do yeet { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -145,6 +157,7 @@ fn o() -> Result<(), ()> { fn p() { let foo = become { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -154,6 +167,7 @@ fn p() { fn q() { let foo = |x: i32| { + //~^ WARN irrefutable `let...else` pattern x } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -163,14 +177,18 @@ fn q() { fn r() { let ok = format_args!("") else { return; }; + //~^ WARN irrefutable `let...else` pattern let bad = format_args! {""} else { return; }; //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~| WARN irrefutable `let...else` pattern } fn s() { macro_rules! a { () => { {} } + //~^ WARN irrefutable `let...else` pattern + //~| WARN irrefutable `let...else` pattern } macro_rules! b { diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 887455913d84a..12df8f849abd2 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -1,5 +1,5 @@ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:9:5 + --> $DIR/bad-let-else-statement.rs:10:5 | LL | } else { | ^ @@ -7,12 +7,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = ({ +LL | LL | 1 LL ~ }) else { | error: `for...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:18:7 + --> $DIR/bad-let-else-statement.rs:19:7 | LL | let foo = for i in 1..2 { | --- `else` is attached to this loop @@ -27,7 +28,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:29:5 + --> $DIR/bad-let-else-statement.rs:31:5 | LL | } else { | ^ @@ -35,14 +36,14 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (if true { -LL | 1 -LL | } else { +LL | + ... LL | 0 LL ~ }) else { | error: `loop...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:38:7 + --> $DIR/bad-let-else-statement.rs:40:7 | LL | let foo = loop { | ---- `else` is attached to this loop @@ -57,7 +58,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:48:5 + --> $DIR/bad-let-else-statement.rs:51:5 | LL | } else { | ^ @@ -65,13 +66,14 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (match true { +LL | LL | true => 1, LL | false => 0 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:58:5 + --> $DIR/bad-let-else-statement.rs:62:5 | LL | } else { | ^ @@ -79,12 +81,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (X { +LL | LL | a: 1 LL ~ }) else { | error: `while...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:67:7 + --> $DIR/bad-let-else-statement.rs:71:7 | LL | let foo = while false { | ----- `else` is attached to this loop @@ -99,7 +102,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:76:5 + --> $DIR/bad-let-else-statement.rs:81:5 | LL | } else { | ^ @@ -107,12 +110,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (const { +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:85:5 + --> $DIR/bad-let-else-statement.rs:91:5 | LL | } else { | ^ @@ -120,12 +124,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = &({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:95:5 + --> $DIR/bad-let-else-statement.rs:102:5 | LL | } else { | ^ @@ -133,12 +138,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = bar = ({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:104:5 + --> $DIR/bad-let-else-statement.rs:112:5 | LL | } else { | ^ @@ -146,12 +152,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = 1 + ({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:113:5 + --> $DIR/bad-let-else-statement.rs:122:5 | LL | } else { | ^ @@ -159,12 +166,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = 1..({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:122:5 + --> $DIR/bad-let-else-statement.rs:132:5 | LL | } else { | ^ @@ -172,12 +180,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = return ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:131:5 + --> $DIR/bad-let-else-statement.rs:142:5 | LL | } else { | ^ @@ -185,12 +194,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = -({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:140:5 + --> $DIR/bad-let-else-statement.rs:152:5 | LL | } else { | ^ @@ -198,12 +208,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = do yeet ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:149:5 + --> $DIR/bad-let-else-statement.rs:162:5 | LL | } else { | ^ @@ -211,12 +222,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = become ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:158:5 + --> $DIR/bad-let-else-statement.rs:172:5 | LL | } else { | ^ @@ -224,12 +236,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = |x: i32| ({ +LL | LL | x LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:167:31 + --> $DIR/bad-let-else-statement.rs:182:31 | LL | let bad = format_args! {""} else { return; }; | ^ @@ -240,7 +253,7 @@ LL | let bad = format_args! ("") else { return; }; | ~ ~ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:181:25 + --> $DIR/bad-let-else-statement.rs:199:25 | LL | let x = a! {} else { return; }; | ^ @@ -254,5 +267,251 @@ help: use parentheses instead of braces for this macro LL | let x = a! () else { return; }; | ~~ -error: aborting due to 19 previous errors +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:7:5 + | +LL | / let foo = { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:26:5 + | +LL | / let foo = if true { +LL | | +LL | | 1 +LL | | } else { +LL | | 0 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:47:5 + | +LL | / let foo = match true { +LL | | +LL | | true => 1, +LL | | false => 0 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:59:5 + | +LL | / let foo = X { +LL | | +LL | | a: 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:78:5 + | +LL | / let foo = const { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:88:5 + | +LL | / let foo = &{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:99:5 + | +LL | / let foo = bar = { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +error[E0384]: cannot assign twice to immutable variable `bar` + --> $DIR/bad-let-else-statement.rs:99:15 + | +LL | let bar = 0; + | --- + | | + | first assignment to `bar` + | help: consider making this binding mutable: `mut bar` +LL | let foo = bar = { + | _______________^ +LL | | +LL | | 1 +LL | | } else { + | |_____^ cannot assign twice to immutable variable + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:109:5 + | +LL | / let foo = 1 + { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:119:5 + | +LL | / let foo = 1..{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:129:5 + | +LL | / let foo = return { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:139:5 + | +LL | / let foo = -{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:149:5 + | +LL | / let foo = do yeet { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:159:5 + | +LL | / let foo = become { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:169:5 + | +LL | / let foo = |x: i32| { +LL | | +LL | | x +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:179:5 + | +LL | let ok = format_args!("") else { return; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:182:5 + | +LL | let bad = format_args! {""} else { return; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:189:19 + | +LL | () => { {} } + | ___________________^ +LL | | +LL | | +LL | | } +... | +LL | | (1) => { +LL | | let x = a!() else { return; }; + | |____________^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:189:19 + | +LL | () => { {} } + | ___________________^ +LL | | +LL | | +LL | | } +... | +LL | | (2) => { +LL | | let x = a! {} else { return; }; + | |____________^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 20 previous errors; 18 warnings emitted +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs index 3d110adef3e34..c1c847d92d04b 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs @@ -129,6 +129,7 @@ pub fn inside_block() { static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); //~^ ERROR: cast cannot be followed by indexing +//~| ERROR: cannot call non-const operator in statics static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); //~^ ERROR: expected one of diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr index d313c888e51c6..6a8cbd9389b76 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr @@ -235,13 +235,13 @@ LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]); | + + error: expected one of `)`, `,`, `.`, `?`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:133:36 + --> $DIR/issue-35813-postfix-after-cast.rs:134:36 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); | ^ expected one of `)`, `,`, `.`, `?`, or an operator error: cast cannot be followed by `?` - --> $DIR/issue-35813-postfix-after-cast.rs:138:5 + --> $DIR/issue-35813-postfix-after-cast.rs:139:5 | LL | Err(0u64) as Result?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -252,13 +252,13 @@ LL | (Err(0u64) as Result)?; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:140:14 + --> $DIR/issue-35813-postfix-after-cast.rs:141:14 | LL | Err(0u64): Result?; | ^ expected one of `.`, `;`, `?`, `}`, or an operator error: expected identifier, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:152:13 + --> $DIR/issue-35813-postfix-after-cast.rs:153:13 | LL | drop_ptr: F(); | ^ expected identifier @@ -266,13 +266,13 @@ LL | drop_ptr: F(); = note: type ascription syntax has been removed, see issue #101728 error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:159:13 + --> $DIR/issue-35813-postfix-after-cast.rs:160:13 | LL | drop_ptr: fn(u8); | ^ expected one of 8 possible tokens error: cast cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:165:5 + --> $DIR/issue-35813-postfix-after-cast.rs:166:5 | LL | drop as fn(u8)(0); | ^^^^^^^^^^^^^^ @@ -283,13 +283,13 @@ LL | (drop as fn(u8))(0); | + + error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:167:13 + --> $DIR/issue-35813-postfix-after-cast.rs:168:13 | LL | drop_ptr: fn(u8)(0); | ^ expected one of 8 possible tokens error: cast cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:172:5 + --> $DIR/issue-35813-postfix-after-cast.rs:173:5 | LL | Box::pin(noop()) as Pin>>.await; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -300,13 +300,13 @@ LL | (Box::pin(noop()) as Pin>>).await; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:175:21 + --> $DIR/issue-35813-postfix-after-cast.rs:176:21 | LL | Box::pin(noop()): Pin>.await; | ^ expected one of `.`, `;`, `?`, `}`, or an operator error: cast cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:187:5 + --> $DIR/issue-35813-postfix-after-cast.rs:188:5 | LL | Foo::default() as Foo.bar; | ^^^^^^^^^^^^^^^^^^^^^ @@ -317,7 +317,7 @@ LL | (Foo::default() as Foo).bar; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:189:19 + --> $DIR/issue-35813-postfix-after-cast.rs:190:19 | LL | Foo::default(): Foo.bar; | ^ expected one of `.`, `;`, `?`, `}`, or an operator @@ -340,11 +340,22 @@ LL | if true { 33 } else { 44 }: i32.max(0) | ^ expected one of `,`, `.`, `?`, or an operator error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:150:13 + --> $DIR/issue-35813-postfix-after-cast.rs:151:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 39 previous errors +error[E0015]: cannot call non-const operator in statics + --> $DIR/issue-35813-postfix-after-cast.rs:130:42 + | +LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); + | ^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error: aborting due to 40 previous errors -For more information about this error, try `rustc --explain E0214`. +Some errors have detailed explanations: E0015, E0214. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/parser/issues/issue-7222.rs b/tests/ui/parser/issues/issue-7222.rs index 6490731662664..fb18f4cd62eca 100644 --- a/tests/ui/parser/issues/issue-7222.rs +++ b/tests/ui/parser/issues/issue-7222.rs @@ -1,6 +1,5 @@ // run-pass // pretty-expanded FIXME #23616 -#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620 pub fn main() { const FOO: f64 = 10.0; diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs index e1ea38f2795df..d081c06044f14 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -37,9 +37,10 @@ fn g1() { //~| HELP: maybe write a path separator here _ => {} } - if let Foo:Bar = f() { + if let Foo:Bar = f() { //~ WARN: irrefutable `if let` pattern //~^ ERROR: expected one of //~| HELP: maybe write a path separator here + //~| HELP: consider replacing the `if let` with a `let` } } diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr index 63b072ac4cdc6..b6e24faf5dabb 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -64,7 +64,7 @@ LL | if let Foo::Bar = f() { | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:48:16 + --> $DIR/issue-87086-colon-path-sep.rs:49:16 | LL | ref qux: Foo::Baz => {} | ^ -------- specifying the type of a pattern isn't supported @@ -77,7 +77,7 @@ LL | ref qux::Foo::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:57:16 + --> $DIR/issue-87086-colon-path-sep.rs:58:16 | LL | mut qux: Foo::Baz => {} | ^ -------- specifying the type of a pattern isn't supported @@ -90,7 +90,7 @@ LL | mut qux::Foo::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:68:12 + --> $DIR/issue-87086-colon-path-sep.rs:69:12 | LL | Foo:Bar::Baz => {} | ^-------- specifying the type of a pattern isn't supported @@ -103,7 +103,7 @@ LL | Foo::Bar::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:74:12 + --> $DIR/issue-87086-colon-path-sep.rs:75:12 | LL | Foo:Bar => {} | ^--- specifying the type of a pattern isn't supported @@ -115,5 +115,15 @@ help: maybe write a path separator here LL | Foo::Bar => {} | ~~ -error: aborting due to 9 previous errors +warning: irrefutable `if let` pattern + --> $DIR/issue-87086-colon-path-sep.rs:40:8 + | +LL | if let Foo:Bar = f() { + | ^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + +error: aborting due to 9 previous errors; 1 warning emitted diff --git a/tests/ui/parser/issues/issue-89574.rs b/tests/ui/parser/issues/issue-89574.rs index 0a477f1aa5fb6..bafb0ce5e6680 100644 --- a/tests/ui/parser/issues/issue-89574.rs +++ b/tests/ui/parser/issues/issue-89574.rs @@ -1,4 +1,6 @@ fn main() { const EMPTY_ARRAY = []; //~^ missing type for `const` item + //~| ERROR type annotations needed + //~| ERROR type annotations needed } diff --git a/tests/ui/parser/issues/issue-89574.stderr b/tests/ui/parser/issues/issue-89574.stderr index 5f8f6f9396938..a0586d41e2e59 100644 --- a/tests/ui/parser/issues/issue-89574.stderr +++ b/tests/ui/parser/issues/issue-89574.stderr @@ -1,8 +1,23 @@ +error[E0282]: type annotations needed + --> $DIR/issue-89574.rs:2:25 + | +LL | const EMPTY_ARRAY = []; + | ^^ cannot infer type + error: missing type for `const` item --> $DIR/issue-89574.rs:2:22 | LL | const EMPTY_ARRAY = []; | ^ help: provide a type for the item: `: ` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/issue-89574.rs:2:25 + | +LL | const EMPTY_ARRAY = []; + | ^^ cannot infer type + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.rs b/tests/ui/parser/item-free-type-bounds-semantic-fail.rs index 9db4111fbabd9..062b51e597845 100644 --- a/tests/ui/parser/item-free-type-bounds-semantic-fail.rs +++ b/tests/ui/parser/item-free-type-bounds-semantic-fail.rs @@ -13,8 +13,8 @@ fn semantics() { //~| ERROR free type alias without body type E<_T>: Ord = u8; //~^ ERROR bounds on `type`s in this context have no effect - //~| ERROR type parameter `_T` is unused + //~| ERROR type parameter `_T` is never used type F<_T>: Ord where 'static: 'static = u8; //~^ ERROR bounds on `type`s in this context have no effect - //~| ERROR type parameter `_T` is unused + //~| ERROR type parameter `_T` is never used } diff --git a/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr b/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr index 1b086512891f2..1077c10392888 100644 --- a/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr +++ b/tests/ui/parser/item-free-type-bounds-semantic-fail.stderr @@ -50,17 +50,23 @@ error: bounds on `type`s in this context have no effect LL | type F<_T>: Ord where 'static: 'static = u8; | ^^^ -error[E0091]: type parameter `_T` is unused +error[E0091]: type parameter `_T` is never used --> $DIR/item-free-type-bounds-semantic-fail.rs:14:12 | LL | type E<_T>: Ord = u8; | ^^ unused type parameter + | + = help: consider removing `_T` or referring to it in the body of the type alias + = help: if you intended `_T` to be a const parameter, use `const _T: /* Type */` instead -error[E0091]: type parameter `_T` is unused +error[E0091]: type parameter `_T` is never used --> $DIR/item-free-type-bounds-semantic-fail.rs:17:12 | LL | type F<_T>: Ord where 'static: 'static = u8; | ^^ unused type parameter + | + = help: consider removing `_T` or referring to it in the body of the type alias + = help: if you intended `_T` to be a const parameter, use `const _T: /* Type */` instead error: aborting due to 10 previous errors diff --git a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr index e40d985826282..b21e788aa7300 100644 --- a/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr +++ b/tests/ui/parser/missing-closing-angle-bracket-eq-constraint.stderr @@ -41,7 +41,7 @@ error[E0282]: type annotations needed for `Vec<_>` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:7:7 | LL | let v : Vec<(u32,_) = vec![]; - | ^ + | ^ ------ type must be known at this point | help: consider giving `v` an explicit type, where the placeholders `_` are specified | @@ -52,7 +52,7 @@ error[E0282]: type annotations needed for `Vec<_>` --> $DIR/missing-closing-angle-bracket-eq-constraint.rs:18:7 | LL | let v : Vec<'a = vec![]; - | ^ + | ^ ------ type must be known at this point | help: consider giving `v` an explicit type, where the placeholders `_` are specified | diff --git a/tests/ui/parser/parse-assoc-type-lt.rs b/tests/ui/parser/parse-assoc-type-lt.rs index d3fe6079a5d2a..913fcd920bdb6 100644 --- a/tests/ui/parser/parse-assoc-type-lt.rs +++ b/tests/ui/parser/parse-assoc-type-lt.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr index 3681a796c53ed..17138a6f07921 100644 --- a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr +++ b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr @@ -30,8 +30,9 @@ error[E0631]: type mismatch in closure arguments --> $DIR/recover-fn-trait-from-fn-kw.rs:10:5 | LL | foo2(|_: ()| {}); - | ^^^^ ------- found signature defined here - | | + | ^^^^^-------^^^^ + | | | + | | found signature defined here | expected due to this | = note: expected closure signature `fn(i32) -> _` diff --git a/tests/ui/parser/recover/recover-range-pats.rs b/tests/ui/parser/recover/recover-range-pats.rs index 156c7ad94d36a..3dc525cd6e104 100644 --- a/tests/ui/parser/recover/recover-range-pats.rs +++ b/tests/ui/parser/recover/recover-range-pats.rs @@ -134,10 +134,13 @@ fn with_macro_expr_var() { macro_rules! mac2 { ($e1:expr, $e2:expr) => { let $e1..$e2; + //~^ ERROR refutable pattern in local binding let $e1...$e2; //~^ ERROR `...` range patterns are deprecated //~| WARN this is accepted in the current edition + //~| ERROR refutable pattern in local binding let $e1..=$e2; + //~^ ERROR refutable pattern in local binding } } @@ -146,12 +149,18 @@ fn with_macro_expr_var() { macro_rules! mac { ($e:expr) => { let ..$e; + //~^ ERROR refutable pattern in local binding let ...$e; //~^ ERROR range-to patterns with `...` are not allowed + //~| ERROR refutable pattern in local binding let ..=$e; + //~^ ERROR refutable pattern in local binding let $e..; + //~^ ERROR refutable pattern in local binding let $e...; //~ ERROR inclusive range with no end + //~^ ERROR refutable pattern in local binding let $e..=; //~ ERROR inclusive range with no end + //~^ ERROR refutable pattern in local binding } } diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr index 5b69ca5cd6dfa..7c5cc4777b6b4 100644 --- a/tests/ui/parser/recover/recover-range-pats.stderr +++ b/tests/ui/parser/recover/recover-range-pats.stderr @@ -159,7 +159,7 @@ LL | if let ....3 = 0 {} | ^^^ help: use `..=` instead error: range-to patterns with `...` are not allowed - --> $DIR/recover-range-pats.rs:149:17 + --> $DIR/recover-range-pats.rs:153:17 | LL | let ...$e; | ^^^ help: use `..=` instead @@ -170,7 +170,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/recover-range-pats.rs:153:19 + --> $DIR/recover-range-pats.rs:160:19 | LL | let $e...; | ^^^ help: use `..` instead @@ -182,7 +182,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/recover-range-pats.rs:154:19 + --> $DIR/recover-range-pats.rs:162:19 | LL | let $e..=; | ^^^ help: use `..` instead @@ -271,7 +271,7 @@ LL | if let X... .0 = 0 {} = note: for more information, see error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:137:20 + --> $DIR/recover-range-pats.rs:138:20 | LL | let $e1...$e2; | ^^^ help: use `..=` for an inclusive range @@ -478,7 +478,169 @@ LL | if let ....3 = 0 {} | | | expected integer, found floating-point number -error: aborting due to 60 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:136:17 + | +LL | let $e1..$e2; + | ^^^^^^^^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1..$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:138:17 + | +LL | let $e1...$e2; + | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1...$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:142:17 + | +LL | let $e1..=$e2; + | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1..=$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:151:17 + | +LL | let ..$e; + | ^^^^ pattern `0_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ..$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:153:17 + | +LL | let ...$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ...$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:156:17 + | +LL | let ..=$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ..=$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:158:17 + | +LL | let $e..; + | ^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:160:17 + | +LL | let $e...; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e...; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:162:17 + | +LL | let $e..=; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..=; { todo!() } + | ++ +++++++++++ + +error: aborting due to 69 previous errors -Some errors have detailed explanations: E0029, E0308, E0586. -For more information about an error, try `rustc --explain E0029`. +Some errors have detailed explanations: E0005, E0029, E0308, E0586. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/parser/struct-literal-in-for.stderr b/tests/ui/parser/struct-literal-in-for.stderr index 1c91eba68e399..d2ef2ad7b5ad1 100644 --- a/tests/ui/parser/struct-literal-in-for.stderr +++ b/tests/ui/parser/struct-literal-in-for.stderr @@ -23,7 +23,7 @@ LL | | x: 3 LL | | }.hi() { | |__________^ `bool` is not an iterator | - = help: the trait `Iterator` is not implemented for `bool` + = help: the trait `Iterator` is not implemented for `bool`, which is required by `bool: IntoIterator` = note: required for `bool` to implement `IntoIterator` error: aborting due to 2 previous errors diff --git a/tests/ui/parser/suggest-assoc-const.fixed b/tests/ui/parser/suggest-assoc-const.fixed index 259f37b23a584..4229135ebb23b 100644 --- a/tests/ui/parser/suggest-assoc-const.fixed +++ b/tests/ui/parser/suggest-assoc-const.fixed @@ -1,5 +1,6 @@ // Issue: 101797, Suggest associated const for incorrect use of let in traits // run-rustfix +#![allow(dead_code)] trait Trait { const _X: i32; //~^ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-assoc-const.rs b/tests/ui/parser/suggest-assoc-const.rs index c7be712ec076e..0cf695bd40aff 100644 --- a/tests/ui/parser/suggest-assoc-const.rs +++ b/tests/ui/parser/suggest-assoc-const.rs @@ -1,5 +1,6 @@ // Issue: 101797, Suggest associated const for incorrect use of let in traits // run-rustfix +#![allow(dead_code)] trait Trait { let _X: i32; //~^ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-assoc-const.stderr b/tests/ui/parser/suggest-assoc-const.stderr index 7ba1dbdff7e59..6e29fad98d466 100644 --- a/tests/ui/parser/suggest-assoc-const.stderr +++ b/tests/ui/parser/suggest-assoc-const.stderr @@ -1,5 +1,5 @@ error: non-item in item list - --> $DIR/suggest-assoc-const.rs:4:5 + --> $DIR/suggest-assoc-const.rs:5:5 | LL | let _X: i32; | ^^^ help: consider using `const` instead of `let` for associated const: `const` diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed index 63704735490fa..81ee6cdf0a722 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn bar() {} //~ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs index 4650b05e20ce8..c8f525fc4f0ad 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn bar() {}; //~ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr index c716d5908ea11..396c76ac85f2f 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -1,5 +1,5 @@ error: non-item in item list - --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16 + --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:5:16 | LL | trait Foo { | - item list starts here diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index b173e23e7a183..a2d2388ff5088 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -34,10 +34,12 @@ extern "C" fn f3_3(..., x: isize) {} const unsafe extern "C" fn f4_1(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic +//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_2(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_3(..., x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic @@ -48,7 +50,7 @@ extern "C" { fn e_f1(...); //~^ ERROR C-variadic function must be declared with at least one named argument fn e_f2(..., x: isize); -//~^ ERROR `...` must be the last argument of a C-variadic function + //~^ ERROR `...` must be the last argument of a C-variadic function } struct X; @@ -68,6 +70,7 @@ impl X { const fn i_f5(x: isize, ...) {} //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR functions cannot be both `const` and C-variadic + //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time } trait T { diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index 18526080e4cb7..6a65ed79d4fbc 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -83,25 +83,25 @@ LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:38:1 + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:1 | LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:38:36 + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:36 | LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^ error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:1 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:1 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^^^ ^^^ ^^^ C-variadic because of this @@ -110,67 +110,67 @@ LL | const extern "C" fn f4_3(..., x: isize, ...) {} | `const` because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^ ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:48:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 | LL | fn e_f1(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:52:13 | LL | fn e_f2(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:57:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:59:23 | LL | fn i_f1(x: isize, ...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f2(...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f2(...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ ^^^ error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:68:5 + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:5 | LL | const fn i_f5(x: isize, ...) {} | ^^^^^ ^^^ C-variadic because of this @@ -178,70 +178,95 @@ LL | const fn i_f5(x: isize, ...) {} | `const` because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:68:29 + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:29 | LL | const fn i_f5(x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:74:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:77:23 | LL | fn t_f1(x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:76:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:79:23 | LL | fn t_f2(x: isize, ...); | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 | LL | fn t_f3(...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 | LL | fn t_f3(...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 | LL | fn t_f4(...); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 | LL | fn t_f4(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:90:13 | LL | fn t_f6(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:90:13 | LL | fn t_f6(..., x: isize); | ^^^ -error: aborting due to 40 previous errors +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:35:43 + | +LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:36 + | +LL | const extern "C" fn f4_2(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:29 + | +LL | const fn i_f5(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 43 previous errors +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs index 2b349f0ed5f99..253b2d8890100 100644 --- a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs +++ b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs @@ -1,13 +1,30 @@ // run-pass +#![allow(unused)] // Test copy -struct A { a: i32, b: i32 } -struct B { a: i32, b: C } -struct D { a: i32, d: C } -#[derive(Copy,Clone)] -struct C { c: i32 } +struct A { + a: i32, + b: i32, +} +struct B { + a: i32, + b: C, +} +struct D { + a: i32, + d: C, +} +#[derive(Copy, Clone)] +struct C { + c: i32, +} +enum E { + E { a: i32, e: C }, + NotE, +} +#[rustfmt::skip] pub fn main() { match (A {a: 10, b: 20}) { x@A {a, b: 20} => { assert!(x.a == 10); assert!(a == 10); } @@ -23,6 +40,23 @@ pub fn main() { y.d.c = 30; assert_eq!(d.c, 20); + match (E::E { a: 10, e: C { c: 20 } }) { + x @ E::E{ a, e: C { c } } => { + assert!(matches!(x, E::E { a: 10, e: C { c: 20 } })); + assert!(a == 10); + assert!(c == 20); + } + _ => panic!(), + } + match (E::E { a: 10, e: C { c: 20 } }) { + mut x @ E::E{ a, e: C { mut c } } => { + x = E::NotE; + c += 30; + assert_eq!(c, 50); + } + _ => panic!(), + } + let some_b = Some(B { a: 10, b: C { c: 20 } }); // in irrefutable pattern diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs index a61d682152407..bfb3c3b20d63c 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs @@ -15,8 +15,8 @@ fn main() { let a @ (b, c) = (u(), u()); //~ ERROR use of partially moved value match Ok(U) { - a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value - //~^ ERROR use of moved value + a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of partially moved value + //~^ ERROR use of partially moved value } fn fun(a @ b: U) {} //~ ERROR use of moved value diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr index 324897151124c..ba0622090bb7d 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -40,35 +40,33 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ (b, ref c) = (u(), u()); | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:18:16 +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:18:9 | -LL | match Ok(U) { - | ----- move occurs because value has type `Result`, which does not implement the `Copy` trait LL | a @ Ok(b) | a @ Err(b) => {} - | - ^ value used here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Ok(b) | a @ Err(b) => {} - | +++ +LL | ref a @ Ok(ref b) | a @ Err(b) => {} + | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:18:29 +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:18:21 | -LL | match Ok(U) { - | ----- move occurs because value has type `Result`, which does not implement the `Copy` trait LL | a @ Ok(b) | a @ Err(b) => {} - | - ^ value used here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | a @ Ok(b) | ref a @ Err(b) => {} - | +++ +LL | a @ Ok(b) | ref a @ Err(ref b) => {} + | +++ +++ error[E0382]: use of partially moved value --> $DIR/borrowck-move-and-move.rs:25:9 diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs index 06dc6e1c4da1f..ac57838f0298f 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs @@ -48,19 +48,17 @@ fn main() { //~^ ERROR borrow of moved value //~| ERROR borrow of moved value //~| ERROR borrow of moved value - //~| ERROR use of moved value + //~| ERROR use of partially moved value None => {} } match Some([U, U]) { mut a @ Some([ref b, ref mut c]) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } match Some(u()) { a @ Some(ref b) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } match Some((u(), u())) { @@ -68,13 +66,12 @@ fn main() { //~^ ERROR borrow of moved value //~| ERROR borrow of moved value //~| ERROR borrow of moved value - //~| ERROR use of moved value + //~| ERROR use of partially moved value None => {} } match Some([u(), u()]) { mut a @ Some([ref b, ref mut c]) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index 1ed019f0a6927..fd7a51388bc10 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -215,7 +215,7 @@ LL | ref mut a @ Some([ref b, ref mut c]) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:9 | LL | a @ Some(ref b) => {} | ^ ----- value borrowed here after move @@ -229,7 +229,7 @@ LL | ref a @ Some(ref b) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^ --------- ----- value borrowed here after move @@ -244,7 +244,7 @@ LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:19 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^^^^^ --------- value borrowed here after move @@ -258,7 +258,7 @@ LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:38 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^ ----- value borrowed here after move @@ -272,7 +272,7 @@ LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:73:9 | LL | mut a @ Some([ref b, ref mut c]) => {} | ^^^^^ ----- --------- value borrowed here after move @@ -314,66 +314,33 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9 | -LL | match Some((U, U)) { - | ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | - value moved here ^ value used here after move - | -help: borrow this binding in the pattern to avoid moving the value - | -LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | +++ - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30 - | -LL | match Some([U, U]) { - | ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait -LL | mut a @ Some([ref b, ref mut c]) => {} - | ----- ^^^^^^^^^ value borrowed here after move - | | - | value moved here - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:18 - | -LL | match Some(u()) { - | --------- move occurs because value has type `Option`, which does not implement the `Copy` trait -LL | a @ Some(ref b) => {} - | - ^^^^^ value borrowed here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Some(ref b) => {} - | +++ +LL | ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9 | -LL | match Some((u(), u())) { - | ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | - value moved here ^ value used here after move + | ^ - value partially moved here + | | + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | +++ - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30 - | -LL | match Some([u(), u()]) { - | ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait -LL | mut a @ Some([ref b, ref mut c]) => {} - | ----- ^^^^^^^^^ value borrowed here after move - | | - | value moved here +LL | ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11 @@ -457,6 +424,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {} | +++ -error: aborting due to 33 previous errors +error: aborting due to 30 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs index 0b0a7801049fe..095c871e8d205 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs @@ -58,11 +58,13 @@ fn main() { match Some([U, U]) { ref mut a @ Some([b, mut c]) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } match Some(u()) { ref a @ Some(b) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } match Some((u(), u())) { @@ -77,6 +79,7 @@ fn main() { match Some([u(), u()]) { ref mut a @ Some([b, mut c]) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr index c8c4d9b8fdb13..45ada8fd51606 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -125,7 +125,7 @@ LL | ref mut a @ Some([b, mut c]) => {} | value is mutably borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9 | LL | ref a @ Some(b) => {} | ^^^^^ - value is moved into `b` here @@ -133,7 +133,7 @@ LL | ref a @ Some(b) => {} | value is borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:9 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- - value is moved into `e` here @@ -142,7 +142,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- value is moved into `c` here @@ -150,7 +150,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `b` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ - value is moved into `e` here @@ -158,7 +158,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `d` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9 | LL | ref mut a @ Some([b, mut c]) => {} | ^^^^^^^^^ - ----- value is moved into `c` here @@ -236,8 +236,36 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref mut a @ [b, ref mut c] = [u(), u()]; | +++ +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([b, ref mut c]) => {} + | +++ + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9 + | +LL | ref a @ Some(b) => {} + | ^^^^^ - value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- value moved here @@ -251,7 +279,7 @@ LL | ref a @ Some((ref b @ ref mut c, ref d @ e)) => {} | +++ error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ - value moved here @@ -264,6 +292,20 @@ help: borrow this binding in the pattern to avoid moving the value LL | ref a @ Some((ref b @ mut c, ref d @ ref e)) => {} | +++ +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([b, ref mut c]) => {} + | +++ + error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 | @@ -345,6 +387,6 @@ LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 36 previous errors +error: aborting due to 39 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs index 6bc0d346c111a..98f316dd74bdd 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -7,7 +7,7 @@ fn main() { match &mut Some(1) { ref mut z @ &mut Some(ref a) => { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable **z = None; println!("{}", *a); } @@ -76,8 +76,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *b = U; drop(a); } @@ -87,6 +87,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot assign to `*b`, as it is immutable for the pattern guard _ => {} } @@ -101,6 +103,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot move out of `b` in pattern guard //~| ERROR cannot move out of `b` in pattern guard _ => {} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index 0b432487615b2..9359244c6ebc1 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -138,7 +138,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -146,7 +146,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -154,7 +154,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^^^^^ --------- value is mutably borrowed by `b` here @@ -162,7 +162,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^^^^^ --------- value is mutably borrowed by `b` here @@ -170,7 +170,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -178,7 +178,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -186,7 +186,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -195,7 +195,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -204,7 +204,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -213,7 +213,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:138:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ^^^^^^^^^ ----- ----- value is borrowed by `c` here @@ -221,16 +221,16 @@ LL | let ref mut a @ (ref b, ref c) = (U, U); | | value is borrowed by `b` here | value is mutably borrowed by `a` here -error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31 +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9 | LL | ref mut z @ &mut Some(ref a) => { - | --------- ^^^^^ immutable borrow occurs here + | ^^^^^^^^^ ----- immutable borrow occurs here | | | mutable borrow occurs here ... -LL | **z = None; - | ---------- mutable borrow later used here +LL | println!("{}", *a); + | -- immutable borrow later used here error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 @@ -254,27 +254,44 @@ LL | let ref a @ ref mut b = u(); LL | *b = u(); | -------- mutable borrow later used here -error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:20 +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | ----- ^^^^^^^^^ mutable borrow occurs here + | ^^^^^ --------- mutable borrow occurs here | | | immutable borrow occurs here ... -LL | drop(a); - | - immutable borrow later used here +LL | *b = U; + | ------ mutable borrow later used here -error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:45 +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | ----- ^^^^^^^^^ mutable borrow occurs here + | ^^^^^ --------- mutable borrow occurs here | | | immutable borrow occurs here ... -LL | drop(a); - | - immutable borrow later used here +LL | *b = U; + | ------ mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^ --------- mutable borrow occurs here ------ mutable borrow later used here + | | + | immutable borrow occurs here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^ --------- ------ mutable borrow later used here + | | | + | | mutable borrow occurs here + | immutable borrow occurs here error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:61 @@ -285,15 +302,32 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } = note: variables bound in patterns are immutable until the end of the pattern guard error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:61 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^^^ cannot assign | = note: variables bound in patterns are immutable until the end of the pattern guard +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^^^^^ --------- mutable borrow occurs here - mutable borrow later used here + | | + | immutable borrow occurs here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^^^^^ --------- - mutable borrow later used here + | | | + | | mutable borrow occurs here + | immutable borrow occurs here + error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait @@ -301,7 +335,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait @@ -310,7 +344,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait @@ -318,7 +352,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut Result`, which does not implement the `Copy` trait @@ -327,7 +361,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -338,7 +372,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -349,7 +383,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -409,7 +443,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} | | value borrowed here after move | move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 47 previous errors +error: aborting due to 51 previous errors Some errors have detailed explanations: E0382, E0502, E0507, E0594. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs index 99739c7bce041..5f86a6a0ca919 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -82,6 +82,8 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *b = U; } } @@ -89,8 +91,6 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time *a = Err(U); // FIXME: The binding name value used above makes for problematic diagnostics. @@ -101,8 +101,6 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time drop(a); } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index c634ea470c5d5..3446148d2b15b 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -163,7 +163,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ^^^^^^^^^ --------- value is mutably borrowed by `b` here @@ -171,7 +171,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ^^^^^^^^^ --------- value is mutably borrowed by `b` here @@ -217,48 +217,26 @@ LL | *b = U; | ------ first borrow later used here error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:24 - | -LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here - | | - | first mutable borrow occurs here -... -LL | *a = Err(U); - | ----------- first borrow later used here - -error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:53 - | -LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here - | | - | first mutable borrow occurs here -... -LL | *a = Err(U); - | ----------- first borrow later used here - -error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:101:24 + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here + | ^^^^^^^^^ --------- first mutable borrow occurs here | | - | first mutable borrow occurs here + | second mutable borrow occurs here ... -LL | drop(a); - | - first borrow later used here +LL | *b = U; + | ------ first borrow later used here error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:101:53 + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here + | ^^^^^^^^^ --------- first mutable borrow occurs here | | - | first mutable borrow occurs here + | second mutable borrow occurs here ... -LL | drop(a); - | - first borrow later used here +LL | *b = U; + | ------ first borrow later used here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11 @@ -313,7 +291,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} | | value borrowed here after move | move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 31 previous errors +error: aborting due to 29 previous errors Some errors have detailed explanations: E0382, E0499. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs index f167a3952ee9c..f0f512bef529d 100644 --- a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs @@ -10,7 +10,7 @@ fn main() { match Ok(0) { Ok(a @ b @ a) //~^ ERROR identifier `a` is bound more than once in the same pattern - | Err(a @ b @ a) + | Err(a @ b @ a) //~ ERROR cannot assign twice to immutable variable `a` //~^ ERROR identifier `a` is bound more than once in the same pattern => {} } @@ -20,7 +20,7 @@ fn main() { //~| ERROR identifier `a` is bound more than once in the same pattern let ref a @ ref a = (); //~^ ERROR identifier `a` is bound more than once in the same pattern - let ref mut a @ ref mut a = (); + let ref mut a @ ref mut a = (); //~ ERROR cannot borrow value as mutable more than once at a time //~^ ERROR identifier `a` is bound more than once in the same pattern let a @ (Ok(a) | Err(a)) = Ok(()); diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr index a165549f6b436..e25c30cd4926a 100644 --- a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr @@ -58,7 +58,27 @@ error[E0416]: identifier `a` is bound more than once in the same pattern LL | let a @ (Ok(a) | Err(a)) = Ok(()); | ^ used in a pattern more than once -error: aborting due to 10 previous errors +error: cannot borrow value as mutable more than once at a time + --> $DIR/pat-at-same-name-both.rs:23:9 + | +LL | let ref mut a @ ref mut a = (); + | ^^^^^^^^^ --------- value is mutably borrowed by `a` here + | | + | value is mutably borrowed by `a` here + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/pat-at-same-name-both.rs:13:15 + | +LL | Ok(a @ b @ a) + | - + | | + | first assignment to `a` + | help: consider making this binding mutable: `mut a` +LL | +LL | | Err(a @ b @ a) + | ^ cannot assign twice to immutable variable + +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0415, E0416. -For more information about an error, try `rustc --explain E0415`. +Some errors have detailed explanations: E0384, E0415, E0416. +For more information about an error, try `rustc --explain E0384`. diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs index c26e457f9e452..8a0f51d0b84b9 100644 --- a/tests/ui/pattern/issue-22546.rs +++ b/tests/ui/pattern/issue-22546.rs @@ -15,7 +15,7 @@ impl Foo { } } -trait Tr { +trait Tr { //~ WARN trait `Tr` is never used type U; } diff --git a/tests/ui/pattern/issue-22546.stderr b/tests/ui/pattern/issue-22546.stderr new file mode 100644 index 0000000000000..e067a95e4226c --- /dev/null +++ b/tests/ui/pattern/issue-22546.stderr @@ -0,0 +1,10 @@ +warning: trait `Tr` is never used + --> $DIR/issue-22546.rs:18:7 + | +LL | trait Tr { + | ^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-28992-empty.rs b/tests/ui/pattern/issue-28992-empty.rs similarity index 100% rename from tests/ui/issues/issue-28992-empty.rs rename to tests/ui/pattern/issue-28992-empty.rs diff --git a/tests/ui/issues/issue-28992-empty.stderr b/tests/ui/pattern/issue-28992-empty.stderr similarity index 100% rename from tests/ui/issues/issue-28992-empty.stderr rename to tests/ui/pattern/issue-28992-empty.stderr diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs index b4f19bb829407..552342a1d3841 100644 --- a/tests/ui/pattern/non-structural-match-types.rs +++ b/tests/ui/pattern/non-structural-match-types.rs @@ -1,6 +1,5 @@ // edition:2021 -#![allow(incomplete_features)] #![allow(unreachable_code)] #![feature(const_async_blocks)] #![feature(inline_const_pat)] diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr index 4a6990da56f6d..f3e0665fef51d 100644 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ b/tests/ui/pattern/non-structural-match-types.stderr @@ -1,11 +1,11 @@ -error: `{closure@$DIR/non-structural-match-types.rs:10:17: 10:19}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:10:9 +error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:9:9 | LL | const { || {} } => {} | ^^^^^^^^^^^^^^^ -error: `{async block@$DIR/non-structural-match-types.rs:13:17: 13:25}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:13:9 +error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:12:9 | LL | const { async {} } => {} | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/pattern/pattern-binding-disambiguation.rs b/tests/ui/pattern/pattern-binding-disambiguation.rs index ce1d8c6c047b1..8be70f65d0e84 100644 --- a/tests/ui/pattern/pattern-binding-disambiguation.rs +++ b/tests/ui/pattern/pattern-binding-disambiguation.rs @@ -26,7 +26,7 @@ fn main() { match doesnt_matter { BracedStruct => {} // OK, `BracedStruct` is a fresh binding } - match UnitVariant { + match UnitVariant { //~ ERROR: `E::TupleVariant` and `E::BracedVariant { }` not covered UnitVariant => {} // OK, `UnitVariant` is a unit variant pattern } match doesnt_matter { @@ -48,7 +48,7 @@ fn main() { let UnitStruct = UnitStruct; // OK, `UnitStruct` is a unit struct pattern let TupleStruct = doesnt_matter; //~ ERROR let bindings cannot shadow tuple structs let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding - let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern + let UnitVariant = UnitVariant; //~ ERROR: refutable pattern in local binding let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants let BracedVariant = doesnt_matter; // OK, `BracedVariant` is a fresh binding let CONST = CONST; // OK, `CONST` is a const pattern diff --git a/tests/ui/pattern/pattern-binding-disambiguation.stderr b/tests/ui/pattern/pattern-binding-disambiguation.stderr index d54467b3c0c08..61c32b6a17bdf 100644 --- a/tests/ui/pattern/pattern-binding-disambiguation.stderr +++ b/tests/ui/pattern/pattern-binding-disambiguation.stderr @@ -58,6 +58,53 @@ LL | static STATIC: () = (); LL | let STATIC = doesnt_matter; | ^^^^^^ cannot be named the same as a static -error: aborting due to 6 previous errors +error[E0004]: non-exhaustive patterns: `E::TupleVariant` and `E::BracedVariant { }` not covered + --> $DIR/pattern-binding-disambiguation.rs:29:11 + | +LL | match UnitVariant { + | ^^^^^^^^^^^ patterns `E::TupleVariant` and `E::BracedVariant { }` not covered + | +note: `E` defined here + --> $DIR/pattern-binding-disambiguation.rs:5:6 + | +LL | enum E { + | ^ +LL | UnitVariant, +LL | TupleVariant(), + | ------------ not covered +LL | BracedVariant{}, + | ------------- not covered + = note: the matched value is of type `E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL | UnitVariant => {}, E::TupleVariant | E::BracedVariant { } => todo!() // OK, `UnitVariant` is a unit variant pattern + | ++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/pattern-binding-disambiguation.rs:51:9 + | +LL | let UnitVariant = UnitVariant; + | ^^^^^^^^^^^ patterns `E::TupleVariant` and `E::BracedVariant { }` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/pattern-binding-disambiguation.rs:5:6 + | +LL | enum E { + | ^ +LL | UnitVariant, +LL | TupleVariant(), + | ------------ not covered +LL | BracedVariant{}, + | ------------- not covered + = note: the matched value is of type `E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let UnitVariant = UnitVariant { todo!() }; + | ++ +++++++++++ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0530`. +Some errors have detailed explanations: E0004, E0005, E0530. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs index a619fcafc8614..1eba7aeb4d64a 100644 --- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs @@ -1,9 +1,23 @@ fn main() { match &[1, 2, 3][..] { - [1, rest..] => println!("{rest:?}"), + [1, rest..] => println!("{rest}"), //~^ ERROR cannot find value `rest` in this scope //~| ERROR cannot find value `rest` in this scope //~| ERROR `X..` patterns in slices are experimental _ => {} } + match &[4, 5, 6][..] { + [] => {} + [_, ..tail] => println!("{tail}"), + //~^ ERROR cannot find value `tail` in this scope + //~| ERROR cannot find value `tail` in this scope + //~| ERROR exclusive range pattern syntax is experimental + } + match &[7, 8, 9][..] { + [] => {} + [_, ...tail] => println!("{tail}"), + //~^ ERROR cannot find value `tail` in this scope + //~| ERROR cannot find value `tail` in this scope + //~| ERROR range-to patterns with `...` are not allowed + } } diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr index c3c9131b63eb2..3a19517c85bd2 100644 --- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr @@ -1,31 +1,82 @@ +error: range-to patterns with `...` are not allowed + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:13 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^ help: use `..=` instead + error[E0425]: cannot find value `rest` in this scope --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), | ^^^^ not found in this scope | help: if you meant to collect the rest of the slice in `rest`, use the at operator | -LL | [1, rest @ ..] => println!("{rest:?}"), +LL | [1, rest @ ..] => println!("{rest}"), | + error[E0425]: cannot find value `rest` in this scope --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), + | ^^^^ not found in this scope + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:15 + | +LL | [_, ..tail] => println!("{tail}"), + | ^^^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `tail`, use the at operator + | +LL | [_, tail @ ..] => println!("{tail}"), + | ~~~~~~~~~ + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:35 + | +LL | [_, ..tail] => println!("{tail}"), | ^^^^ not found in this scope +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:16 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `tail`, use the at operator + | +LL | [_, tail @ ..] => println!("{tail}"), + | ~~~~~~~~~ + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:36 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^^ not found in this scope + error[E0658]: `X..` patterns in slices are experimental --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), | ^^^^^^ | = note: see issue #67264 for more information = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:13 + | +LL | [_, ..tail] => println!("{tail}"), + | ^^^^^^ + | + = note: see issue #37854 for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: use an inclusive range pattern, like N..=M + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0425, E0658. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr similarity index 87% rename from tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr rename to tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr index cd5c283f9fd93..553daff2d969d 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/always-inhabited-union-ref.rs:23:11 + --> $DIR/always-inhabited-union-ref.rs:26:11 | LL | match uninhab_ref() { | ^^^^^^^^^^^^^ @@ -14,13 +14,13 @@ LL + } | error[E0004]: non-exhaustive patterns: type `Foo` is non-empty - --> $DIR/always-inhabited-union-ref.rs:27:11 + --> $DIR/always-inhabited-union-ref.rs:30:11 | LL | match uninhab_union() { | ^^^^^^^^^^^^^^^ | note: `Foo` defined here - --> $DIR/always-inhabited-union-ref.rs:10:11 + --> $DIR/always-inhabited-union-ref.rs:13:11 | LL | pub union Foo { | ^^^ diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..a1d8002c64895 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr @@ -0,0 +1,46 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/always-inhabited-union-ref.rs:7:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/always-inhabited-union-ref.rs:26:11 + | +LL | match uninhab_ref() { + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_ref() { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `Foo` is non-empty + --> $DIR/always-inhabited-union-ref.rs:30:11 + | +LL | match uninhab_union() { + | ^^^^^^^^^^^^^^^ + | +note: `Foo` defined here + --> $DIR/always-inhabited-union-ref.rs:13:11 + | +LL | pub union Foo { + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_union() { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs index 7d1cac8a442f5..247b7f21f6866 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -1,9 +1,12 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns + // The precise semantics of inhabitedness with respect to unions and references is currently // undecided. This test file currently checks a conservative choice. -#![feature(exhaustive_patterns)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] - #![allow(dead_code)] #![allow(unreachable_code)] diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index 0b4d99727581b..59b454d398195 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -9,3 +9,21 @@ LL | if let CONSTANT = &&MyType { error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]` + --> $DIR/const-partial_eq-fallback-ice.rs:14:12 + | +LL | if let CONSTANT = &&MyType { + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/const-partial_eq-fallback-ice.rs:1:10 + | +LL | #![allow(warnings)] + | ^^^^^^^^ + = note: `#[allow(indirect_structural_match)]` implied by `#[allow(warnings)]` + diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 0b1a2e2736e1d..6a5bd185e39b3 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -5,7 +5,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. @@ -15,7 +15,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:108:9 @@ -24,7 +24,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:110:9 @@ -33,7 +33,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:117:9 @@ -42,7 +42,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:127:9 @@ -51,7 +51,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:139:9 @@ -60,7 +60,7 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:142:9 @@ -69,7 +69,7 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 error: unreachable pattern --> $DIR/consts-opaque.rs:48:9 @@ -166,3 +166,91 @@ LL | WRAPQUUX => {}, Wrap(_) => todo!() error: aborting due to 10 previous errors; 8 warnings emitted For more information about this error, try `rustc --explain E0004`. +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:96:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:98:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:108:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:110:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:117:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:127:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:139:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:142:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 304435cb21e8a..4c43419243190 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -43,18 +43,18 @@ help: you might want to use `if let` to ignore the variant that isn't matched LL | if let None = x { todo!() }; | ++ +++++++++++ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match-check-notes.rs:45:11 | LL | match 0u8 { - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index 40494b726f00c..45f715dc7b2dc 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -42,18 +42,18 @@ help: you might want to use `if let` to ignore the variant that isn't matched LL | if let None = x { todo!() }; | ++ +++++++++++ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match-check-notes.rs:45:11 | LL | match 0u8 { - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs index ee9ff3dcf9012..c30cdfc2e4fee 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs @@ -43,10 +43,10 @@ fn empty_foreign_enum_private(x: Option fn main() { match 0u8 { - //~^ ERROR `_` not covered + //~^ ERROR not covered //~| NOTE the matched value is of type //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE pattern `_` not covered + //~| NOTE not covered _ if false => {} } } diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 9c3bebd7797b8..5f895fab0fba4 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -7,9 +7,36 @@ LL | match_no_arms!(0u8); = note: the matched value is of type `u8` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty +error[E0004]: non-exhaustive patterns: type `i8` is non-empty --> $DIR/empty-match.rs:47:20 | +LL | match_no_arms!(0i8); + | ^^^ + | + = note: the matched value is of type `i8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/empty-match.rs:48:20 + | +LL | match_no_arms!(0usize); + | ^^^^^^ + | + = note: the matched value is of type `usize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `isize` is non-empty + --> $DIR/empty-match.rs:49:20 + | +LL | match_no_arms!(0isize); + | ^^^^^^ + | + = note: the matched value is of type `isize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:50:20 + | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | @@ -22,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -80,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -98,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -121,22 +148,64 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:55:24 +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, +LL + 0_u8..=u8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered + --> $DIR/empty-match.rs:59:24 + | +LL | match_guarded_arm!(0i8); + | ^^^ pattern `i8::MIN..=i8::MAX` not covered + | + = note: the matched value is of type `i8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + i8::MIN..=i8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `0_usize..` not covered + --> $DIR/empty-match.rs:60:24 + | +LL | match_guarded_arm!(0usize); + | ^^^^^^ pattern `0_usize..` not covered + | + = note: the matched value is of type `usize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + 0_usize.. => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:61:24 + | +LL | match_guarded_arm!(0isize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:56:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -155,7 +224,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:57:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -174,7 +243,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -193,7 +262,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -212,7 +281,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -233,7 +302,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -256,7 +325,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -284,6 +353,6 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 16 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 9c3bebd7797b8..5f895fab0fba4 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -7,9 +7,36 @@ LL | match_no_arms!(0u8); = note: the matched value is of type `u8` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty +error[E0004]: non-exhaustive patterns: type `i8` is non-empty --> $DIR/empty-match.rs:47:20 | +LL | match_no_arms!(0i8); + | ^^^ + | + = note: the matched value is of type `i8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/empty-match.rs:48:20 + | +LL | match_no_arms!(0usize); + | ^^^^^^ + | + = note: the matched value is of type `usize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `isize` is non-empty + --> $DIR/empty-match.rs:49:20 + | +LL | match_no_arms!(0isize); + | ^^^^^^ + | + = note: the matched value is of type `isize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:50:20 + | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | @@ -22,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -80,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -98,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -121,22 +148,64 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:55:24 +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, +LL + 0_u8..=u8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered + --> $DIR/empty-match.rs:59:24 + | +LL | match_guarded_arm!(0i8); + | ^^^ pattern `i8::MIN..=i8::MAX` not covered + | + = note: the matched value is of type `i8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + i8::MIN..=i8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `0_usize..` not covered + --> $DIR/empty-match.rs:60:24 + | +LL | match_guarded_arm!(0usize); + | ^^^^^^ pattern `0_usize..` not covered + | + = note: the matched value is of type `usize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + 0_usize.. => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:61:24 + | +LL | match_guarded_arm!(0isize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:56:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -155,7 +224,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:57:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -174,7 +243,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -193,7 +262,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -212,7 +281,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -233,7 +302,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -256,7 +325,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -284,6 +353,6 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 16 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index 321f24adc46b4..20ab702c9c899 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -44,6 +44,9 @@ fn nonempty() { } match_no_arms!(0u8); //~ ERROR type `u8` is non-empty + match_no_arms!(0i8); //~ ERROR type `i8` is non-empty + match_no_arms!(0usize); //~ ERROR type `usize` is non-empty + match_no_arms!(0isize); //~ ERROR type `isize` is non-empty match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty @@ -52,7 +55,10 @@ fn nonempty() { match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - match_guarded_arm!(0u8); //~ ERROR `_` not covered + match_guarded_arm!(0u8); //~ ERROR `0_u8..=u8::MAX` not covered + match_guarded_arm!(0i8); //~ ERROR `i8::MIN..=i8::MAX` not covered + match_guarded_arm!(0usize); //~ ERROR `0_usize..` not covered + match_guarded_arm!(0isize); //~ ERROR `_` not covered match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered diff --git a/tests/ui/pattern/usefulness/floats.rs b/tests/ui/pattern/usefulness/floats.rs index 2616dfadb85e8..63ce26adab2a4 100644 --- a/tests/ui/pattern/usefulness/floats.rs +++ b/tests/ui/pattern/usefulness/floats.rs @@ -1,5 +1,4 @@ #![feature(exclusive_range_pattern)] -#![allow(illegal_floating_point_literal_pattern)] #![deny(unreachable_patterns)] fn main() { diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr index f50419118246b..d99f05f52842d 100644 --- a/tests/ui/pattern/usefulness/floats.stderr +++ b/tests/ui/pattern/usefulness/floats.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/floats.rs:11:11 + --> $DIR/floats.rs:10:11 | LL | match 0.0 { | ^^^ pattern `_` not covered @@ -12,49 +12,49 @@ LL + _ => todo!() | error: unreachable pattern - --> $DIR/floats.rs:19:9 + --> $DIR/floats.rs:18:9 | LL | 0.01f64 => {} | ^^^^^^^ | note: the lint level is defined here - --> $DIR/floats.rs:3:9 + --> $DIR/floats.rs:2:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:20:9 + --> $DIR/floats.rs:19:9 | LL | 0.02f64 => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:21:9 + --> $DIR/floats.rs:20:9 | LL | 6.5f64 => {} | ^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:23:9 + --> $DIR/floats.rs:22:9 | LL | 1.0f64..=4.0f64 => {} | ^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:35:9 + --> $DIR/floats.rs:34:9 | LL | 0.01f32 => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:36:9 + --> $DIR/floats.rs:35:9 | LL | 0.02f32 => {} | ^^^^^^^ error: unreachable pattern - --> $DIR/floats.rs:37:9 + --> $DIR/floats.rs:36:9 | LL | 6.5f32 => {} | ^^^^^^ diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr similarity index 87% rename from tests/ui/pattern/usefulness/match-privately-empty.stderr rename to tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr index d760790dff6fe..708a1511244c2 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.stderr +++ b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered - --> $DIR/match-privately-empty.rs:13:11 + --> $DIR/match-privately-empty.rs:16:11 | LL | match private::DATA { | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered @@ -12,7 +12,7 @@ note: `Option` defined here = note: the matched value is of type `Option` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ }) => {}, +LL ~ Some(private::Private { misc: false, .. }) => {}, LL + Some(Private { misc: true, .. }) => todo!() | diff --git a/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..a6ce02c0c3c6a --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr @@ -0,0 +1,30 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/match-privately-empty.rs:3:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + --> $DIR/match-privately-empty.rs:16:11 + | +LL | match private::DATA { + | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Some(private::Private { misc: false, .. }) => {}, +LL + Some(Private { misc: true, .. }) => todo!() + | + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs index 315eb03d16564..67a9aa2e91614 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.rs +++ b/tests/ui/pattern/usefulness/match-privately-empty.rs @@ -1,5 +1,8 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] -#![feature(exhaustive_patterns)] mod private { pub struct Private { @@ -11,11 +14,8 @@ mod private { fn main() { match private::DATA { - //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered None => {} - Some(private::Private { - misc: false, - .. - }) => {} + Some(private::Private { misc: false, .. }) => {} } } diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.rs b/tests/ui/pattern/usefulness/non-exhaustive-match.rs index 1cb58b8cebef7..44acd397f8d58 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match.rs +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.rs @@ -1,5 +1,3 @@ -#![allow(illegal_floating_point_literal_pattern)] - enum T { A, B } fn main() { diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr index 4bebd3cbbefd0..61ed0eb4fc4e2 100644 --- a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -1,11 +1,11 @@ error[E0004]: non-exhaustive patterns: `T::A` not covered - --> $DIR/non-exhaustive-match.rs:7:11 + --> $DIR/non-exhaustive-match.rs:5:11 | LL | match x { T::B => { } } | ^ pattern `T::A` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:6 + --> $DIR/non-exhaustive-match.rs:1:6 | LL | enum T { A, B } | ^ - not covered @@ -16,7 +16,7 @@ LL | match x { T::B => { }, T::A => todo!() } | +++++++++++++++++ error[E0004]: non-exhaustive patterns: `false` not covered - --> $DIR/non-exhaustive-match.rs:8:11 + --> $DIR/non-exhaustive-match.rs:6:11 | LL | match true { | ^^^^ pattern `false` not covered @@ -29,7 +29,7 @@ LL + false => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/non-exhaustive-match.rs:11:11 + --> $DIR/non-exhaustive-match.rs:9:11 | LL | match Some(10) { | ^^^^^^^^ pattern `Some(_)` not covered @@ -47,7 +47,7 @@ LL + Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered - --> $DIR/non-exhaustive-match.rs:14:11 + --> $DIR/non-exhaustive-match.rs:12:11 | LL | match (2, 3, 4) { | ^^^^^^^^^ patterns `(_, _, i32::MIN..=3_i32)` and `(_, _, 5_i32..=i32::MAX)` not covered @@ -60,7 +60,7 @@ LL + (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!() | error[E0004]: non-exhaustive patterns: `(T::A, T::A)` and `(T::B, T::B)` not covered - --> $DIR/non-exhaustive-match.rs:18:11 + --> $DIR/non-exhaustive-match.rs:16:11 | LL | match (T::A, T::A) { | ^^^^^^^^^^^^ patterns `(T::A, T::A)` and `(T::B, T::B)` not covered @@ -73,13 +73,13 @@ LL + (T::A, T::A) | (T::B, T::B) => todo!() | error[E0004]: non-exhaustive patterns: `T::B` not covered - --> $DIR/non-exhaustive-match.rs:22:11 + --> $DIR/non-exhaustive-match.rs:20:11 | LL | match T::A { | ^^^^ pattern `T::B` not covered | note: `T` defined here - --> $DIR/non-exhaustive-match.rs:3:6 + --> $DIR/non-exhaustive-match.rs:1:6 | LL | enum T { A, B } | ^ - not covered @@ -91,7 +91,7 @@ LL + T::B => todo!() | error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/non-exhaustive-match.rs:33:11 + --> $DIR/non-exhaustive-match.rs:31:11 | LL | match *vec { | ^^^^ pattern `[]` not covered @@ -104,7 +104,7 @@ LL + [] => todo!() | error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered - --> $DIR/non-exhaustive-match.rs:46:11 + --> $DIR/non-exhaustive-match.rs:44:11 | LL | match *vec { | ^^^^ pattern `[_, _, _, _, ..]` not covered diff --git a/tests/ui/pattern/usefulness/slice_of_empty.stderr b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr similarity index 93% rename from tests/ui/pattern/usefulness/slice_of_empty.stderr rename to tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr index d56360d4cec07..9770f680b2da8 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.stderr +++ b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/slice_of_empty.rs:18:11 + --> $DIR/slice_of_empty.rs:22:11 | LL | match nevers { | ^^^^^^ pattern `&[]` not covered diff --git a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr new file mode 100644 index 0000000000000..3b9e71f50d5ff --- /dev/null +++ b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr @@ -0,0 +1,38 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/slice_of_empty.rs:3:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/slice_of_empty.rs:11:11 + | +LL | match nevers { + | ^^^^^^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &[] => (), +LL ~ &[_, ..] => todo!(), + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice_of_empty.rs:22:11 + | +LL | match nevers { + | ^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[_] => (), +LL ~ &[] | &[_, _, ..] => todo!(), + | + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/slice_of_empty.rs b/tests/ui/pattern/usefulness/slice_of_empty.rs index 3cbd0eba57fd1..5f64dd3fecc9a 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.rs +++ b/tests/ui/pattern/usefulness/slice_of_empty.rs @@ -1,11 +1,15 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] -#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] fn main() {} fn foo(nevers: &[!]) { match nevers { + //[min_exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[_, ..]` not covered &[] => (), }; @@ -16,7 +20,8 @@ fn foo(nevers: &[!]) { }; match nevers { - //~^ ERROR non-exhaustive patterns: `&[]` not covered + //[exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[]` not covered + //[min_exhaustive_patterns]~^^ ERROR non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered &[_] => (), }; } diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs new file mode 100644 index 0000000000000..c961c80035232 --- /dev/null +++ b/tests/ui/precondition-checks/misaligned-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0); + } +} diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs new file mode 100644 index 0000000000000..1e67e7f5fb1d0 --- /dev/null +++ b/tests/ui/precondition-checks/null-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0); + } +} diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs new file mode 100644 index 0000000000000..1366ba28f1c9e --- /dev/null +++ b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs @@ -0,0 +1,12 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: hint::assert_unchecked +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let sli: &[u8] = &[0]; + sli.get_unchecked(1); + } +} diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs index 5ee5085ddc8e1..feb9643850d05 100644 --- a/tests/ui/print_type_sizes/niche-filling.rs +++ b/tests/ui/print_type_sizes/niche-filling.rs @@ -1,5 +1,5 @@ -// compile-flags: -Z print-type-sizes --crate-type=lib -// ignore-debug debug assertions will print more types +// compile-flags: -Z print-type-sizes --crate-type lib +// ignore-debug: debug assertions will print more types // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout index b53b893660321..53a58ccc4eef8 100644 --- a/tests/ui/print_type_sizes/niche-filling.stdout +++ b/tests/ui/print_type_sizes/niche-filling.stdout @@ -70,6 +70,10 @@ print-type-size field `.a`: 4 bytes print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes print-type-size type: `std::num::NonZero`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes +print-type-size type: `std::option::Option>`: 4 bytes, alignment: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes print-type-size variant `Four`: 2 bytes print-type-size field `.0`: 2 bytes diff --git a/tests/ui/privacy/associated-item-privacy-trait.stderr b/tests/ui/privacy/associated-item-privacy-trait.stderr index 4e9dfa4a83519..f79c4cff72fa2 100644 --- a/tests/ui/privacy/associated-item-privacy-trait.stderr +++ b/tests/ui/privacy/associated-item-privacy-trait.stderr @@ -75,17 +75,6 @@ LL | priv_trait::mac!(); | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:29:14 - | -LL | impl PrivTr for u8 {} - | ^^^^^^ private trait -... -LL | priv_trait::mac!(); - | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) - error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:46:21 | @@ -328,5 +317,16 @@ LL | priv_parent_substs::mac!(); | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-trait.rs:29:14 + | +LL | impl PrivTr for u8 {} + | ^^^^^^ private trait +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + error: aborting due to 30 previous errors diff --git a/tests/ui/privacy/associated-item-privacy-type-binding.stderr b/tests/ui/privacy/associated-item-privacy-type-binding.stderr index de9893816fade..52bfa3c2ab889 100644 --- a/tests/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/tests/ui/privacy/associated-item-privacy-type-binding.stderr @@ -32,10 +32,10 @@ LL | priv_trait::mac1!(); = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-type-binding.rs:16:31 + --> $DIR/associated-item-privacy-type-binding.rs:16:37 | LL | trait InSignatureTr2: PubTr {} - | ^^^^^^^^^^^^^^^^^^^ private trait + | ^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | ------------------- in this macro invocation @@ -164,10 +164,10 @@ LL | priv_parent_substs::mac!(); = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private - --> $DIR/associated-item-privacy-type-binding.rs:56:31 + --> $DIR/associated-item-privacy-type-binding.rs:56:37 | LL | trait InSignatureTr2: PubTr {} - | ^^^^^^^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation diff --git a/tests/ui/issues/auxiliary/private-trait-xc.rs b/tests/ui/privacy/auxiliary/private-trait-xc.rs similarity index 100% rename from tests/ui/issues/auxiliary/private-trait-xc.rs rename to tests/ui/privacy/auxiliary/private-trait-xc.rs diff --git a/tests/ui/issues/issue-11593.rs b/tests/ui/privacy/issue-11593.rs similarity index 100% rename from tests/ui/issues/issue-11593.rs rename to tests/ui/privacy/issue-11593.rs diff --git a/tests/ui/issues/issue-11593.stderr b/tests/ui/privacy/issue-11593.stderr similarity index 100% rename from tests/ui/issues/issue-11593.stderr rename to tests/ui/privacy/issue-11593.stderr diff --git a/tests/ui/privacy/private-type-in-interface.stderr b/tests/ui/privacy/private-type-in-interface.stderr index a5e80d6962dba..091cae42dea3c 100644 --- a/tests/ui/privacy/private-type-in-interface.stderr +++ b/tests/ui/privacy/private-type-in-interface.stderr @@ -47,10 +47,10 @@ LL | fn g() -> impl Tr2 { 0 } | ^^^^^^^^^^^^^^^^^^ private type error: type `Priv` is private - --> $DIR/private-type-in-interface.rs:28:16 + --> $DIR/private-type-in-interface.rs:28:11 | LL | fn g() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private --> $DIR/private-type-in-interface.rs:30:15 @@ -59,10 +59,10 @@ LL | fn g_ext() -> impl Tr2 { 0 } | ^^^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private - --> $DIR/private-type-in-interface.rs:30:20 + --> $DIR/private-type-in-interface.rs:30:15 | LL | fn g_ext() -> impl Tr2 { 0 } - | ^^^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^^^^^^^^^ private type error: aborting due to 11 previous errors diff --git a/tests/ui/privacy/projections.rs b/tests/ui/privacy/projections.rs new file mode 100644 index 0000000000000..0e6590de4f5b4 --- /dev/null +++ b/tests/ui/privacy/projections.rs @@ -0,0 +1,60 @@ +mod m { + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` +} + +trait Trait { + type A; +} + +impl Trait for u8 { + type A = u8; +} + +fn check() -> ::A { + //~^ ERROR: `Priv` is private + 0 +} + +trait Trait2 { + type A; +} + +impl Trait2 for u8 { + type A = m::Leak; + //~^ ERROR: `Priv` is private + //~| ERROR: private type `Priv` in public interface +} + +fn check2() -> ::A { + //~^ ERROR: `Priv` is private + todo!() +} + +trait Trait3 { + type A; +} + +impl Trait3 for u8 { + type A = T::A; + //~^ ERROR: `Priv` is private + //~| ERROR: private type `Priv` in public interface +} + +fn check3() -> ::A { + todo!() +} + +trait Trait4 { + type A; +} + +impl Trait4 for u8 { + type A = T::A; +} + +fn check4() -> ::A { + todo!() +} + +fn main() {} diff --git a/tests/ui/privacy/projections.stderr b/tests/ui/privacy/projections.stderr new file mode 100644 index 0000000000000..010d77998e344 --- /dev/null +++ b/tests/ui/privacy/projections.stderr @@ -0,0 +1,62 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error[E0446]: private type `Priv` in public interface + --> $DIR/projections.rs:24:5 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type A = m::Leak; + | ^^^^^^^^^ can't leak private type + +error[E0446]: private type `Priv` in public interface + --> $DIR/projections.rs:39:5 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type A = T::A; + | ^^^^^^^^^^^^^^^^ can't leak private type + +error: type `Priv` is private + --> $DIR/projections.rs:14:15 + | +LL | fn check() -> ::A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:29:39 + | +LL | fn check2() -> ::A { + | _______________________________________^ +LL | | +LL | | todo!() +LL | | } + | |_^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:24:17 + | +LL | type A = m::Leak; + | ^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:39:24 + | +LL | type A = T::A; + | ^^^^^^^^^^^^^ private type + +error: aborting due to 6 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/projections2.rs b/tests/ui/privacy/projections2.rs new file mode 100644 index 0000000000000..1afbf6d196e58 --- /dev/null +++ b/tests/ui/privacy/projections2.rs @@ -0,0 +1,38 @@ +mod m { + use super::*; + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` + + trait Trait3 { + type A; + } + + impl Trait3 for u8 { + type A = T::A; + } + + pub trait Trait4 { + type A; + } + + impl Trait4 for u8 { + type A = ::A; + //~^ ERROR: private associated type `Trait3::A` in public interface + //~| ERROR: private trait `Trait3` in public interface + } +} + +pub trait Trait { + type A; +} + +impl Trait for u8 { + type A = u8; +} +use m::*; + +fn check4() -> ::A { + todo!() +} + +fn main() {} diff --git a/tests/ui/privacy/projections2.stderr b/tests/ui/privacy/projections2.stderr new file mode 100644 index 0000000000000..6eae9643c5a8e --- /dev/null +++ b/tests/ui/privacy/projections2.stderr @@ -0,0 +1,34 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections2.rs:4:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections2.rs:3:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error[E0446]: private associated type `Trait3::A` in public interface + --> $DIR/projections2.rs:19:9 + | +LL | type A; + | ---------------- `Trait3::A` declared as private +... +LL | type A = ::A; + | ^^^^^^^^^^^^^^^^ can't leak private associated type + +error[E0446]: private trait `Trait3` in public interface + --> $DIR/projections2.rs:19:9 + | +LL | trait Trait3 { + | ------------ `Trait3` declared as private +... +LL | type A = ::A; + | ^^^^^^^^^^^^^^^^ can't leak private trait + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed index 79b6a6516ab26..6de7b865a9914 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] pub mod a { pub use self::b::Trait; diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.rs b/tests/ui/privacy/sealed-traits/re-exported-trait.rs index 5f96dfdcbd6c4..bf07d666dff89 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.rs +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] pub mod a { pub use self::b::Trait; diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr index 9f2291e6825a6..6e2f36e3f381d 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr @@ -1,11 +1,11 @@ error[E0603]: module `b` is private - --> $DIR/re-exported-trait.rs:11:9 + --> $DIR/re-exported-trait.rs:12:9 | LL | impl a::b::Trait for S {} | ^ private module | note: the module `b` is defined here - --> $DIR/re-exported-trait.rs:5:5 + --> $DIR/re-exported-trait.rs:6:5 | LL | mod b { | ^^^^^ diff --git a/tests/ui/privacy/struct-field-type.rs b/tests/ui/privacy/struct-field-type.rs new file mode 100644 index 0000000000000..6a4a19297e190 --- /dev/null +++ b/tests/ui/privacy/struct-field-type.rs @@ -0,0 +1,10 @@ +mod m { + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` +} + +struct S { + field: m::Leak, //~ ERROR: `Priv` is private +} + +fn main() {} diff --git a/tests/ui/privacy/struct-field-type.stderr b/tests/ui/privacy/struct-field-type.stderr new file mode 100644 index 0000000000000..854ff6a98a46b --- /dev/null +++ b/tests/ui/privacy/struct-field-type.stderr @@ -0,0 +1,21 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/struct-field-type.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/struct-field-type.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error: type `Priv` is private + --> $DIR/struct-field-type.rs:7:5 + | +LL | field: m::Leak, + | ^^^^^ private type + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout b/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout index 8459f4e630550..947d411e8495e 100644 --- a/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout +++ b/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout @@ -1,5 +1,4 @@ PRINT-ATTR INPUT (DISPLAY): struct ItemWithSemi; -PRINT-ATTR RE-COLLECTED (DISPLAY): struct ItemWithSemi ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -47,7 +46,6 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!"; -PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_let] let string = "Hello, world!" ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', @@ -90,7 +88,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro!("{}", string); -PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string); PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', @@ -144,7 +142,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): second_make_stmt!(#[allow(dead_code)] struct Bar {}); -PRINT-ATTR RE-COLLECTED (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}); PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "second_make_stmt", @@ -293,7 +291,6 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct NonBracedStruct; -PRINT-ATTR RE-COLLECTED (DISPLAY): #[rustc_dummy] struct NonBracedStruct ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', diff --git a/tests/ui/proc-macro/attr-stmt-expr.stdout b/tests/ui/proc-macro/attr-stmt-expr.stdout index 5e09198bbd498..e9fcbe304a0ff 100644 --- a/tests/ui/proc-macro/attr-stmt-expr.stdout +++ b/tests/ui/proc-macro/attr-stmt-expr.stdout @@ -30,7 +30,6 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!"; -PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_let] let string = "Hello, world!" ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', @@ -73,7 +72,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro!("{}", string); -PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string); PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', @@ -127,7 +126,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): second_make_stmt!(#[allow(dead_code)] struct Bar {}); -PRINT-ATTR RE-COLLECTED (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}); PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "second_make_stmt", diff --git a/tests/ui/proc-macro/attribute-spans-preserved.stdout b/tests/ui/proc-macro/attribute-spans-preserved.stdout index 190098d021154..28f4daecc0e8e 100644 --- a/tests/ui/proc-macro/attribute-spans-preserved.stdout +++ b/tests/ui/proc-macro/attribute-spans-preserved.stdout @@ -1 +1 @@ -fn main() { let y : u32 = "z" ; { let x: u32 = "y"; } } +fn main() { let y : u32 = "z"; { let x: u32 = "y"; } } diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs index 7a29894bbcfeb..0af628884498c 100644 --- a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs +++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs @@ -10,14 +10,14 @@ use proc_macro::TokenStream; #[proc_macro_attribute] pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;"); + assert_eq!(item.to_string(), "let string = \"Hello, world!\";"); item } #[proc_macro_attribute] pub fn expect_my_macro_stmt(attr: TokenStream, item: TokenStream) -> TokenStream { assert!(attr.to_string().is_empty()); - assert_eq!(item.to_string(), "my_macro! (\"{}\", string) ;"); + assert_eq!(item.to_string(), "my_macro! (\"{}\", string);"); item } diff --git a/tests/ui/proc-macro/cfg-eval-inner.stdout b/tests/ui/proc-macro/cfg-eval-inner.stdout index 43ae47c201f8f..9fa8f437d0efa 100644 --- a/tests/ui/proc-macro/cfg-eval-inner.stdout +++ b/tests/ui/proc-macro/cfg-eval-inner.stdout @@ -11,10 +11,10 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): impl Foo < { field: [u8; { #![rustc_dummy(another_cursed_inner)] 1 }] } 0 }] > { #![rustc_dummy(evaluated_attr)] fn bar() {} } PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): impl Foo < -[u8 ; +[u8; { #! [rustc_dummy(cursed_inner)] #! [allow(unused)] struct Inner - { field : [u8 ; { #! [rustc_dummy(another_cursed_inner)] 1 }] } 0 + { field : [u8; { #! [rustc_dummy(another_cursed_inner)] 1 }] } 0 }] > { #! [rustc_dummy(evaluated_attr)] fn bar() {} } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs index 4a7e48eed46c3..b484b42e56672 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.rs +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.rs @@ -5,7 +5,7 @@ #[macro_use] extern crate test_macros; -#[derive(Empty)] //~ ERROR cannot determine resolution for the attribute macro `derive` +#[derive(Empty)] #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope struct Foo {} diff --git a/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr index fd1ed8a3d0ff3..b34713b8ca68e 100644 --- a/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr +++ b/tests/ui/proc-macro/derive-helper-legacy-spurious.stderr @@ -4,19 +4,11 @@ error: cannot find attribute `dummy` in this scope LL | #![dummy] | ^^^^^ -error: cannot determine resolution for the attribute macro `derive` - --> $DIR/derive-helper-legacy-spurious.rs:8:3 - | -LL | #[derive(Empty)] - | ^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: cannot find attribute `empty_helper` in this scope --> $DIR/derive-helper-legacy-spurious.rs:9:3 | LL | #[empty_helper] | ^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/doc-comment-preserved.stdout b/tests/ui/proc-macro/doc-comment-preserved.stdout index b0ea180d9bdba..e9db3785d3d1d 100644 --- a/tests/ui/proc-macro/doc-comment-preserved.stdout +++ b/tests/ui/proc-macro/doc-comment-preserved.stdout @@ -6,7 +6,7 @@ PRINT-BANG INPUT (DISPLAY): /** ******* */ pub struct S; -PRINT-BANG RE-COLLECTED (DISPLAY): #[doc = "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n"] pub struct S ; +PRINT-BANG RE-COLLECTED (DISPLAY): #[doc = "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n"] pub struct S; PRINT-BANG INPUT (DEBUG): TokenStream [ Punct { ch: '#', diff --git a/tests/ui/proc-macro/dollar-crate-issue-57089.stdout b/tests/ui/proc-macro/dollar-crate-issue-57089.stdout index 7f97ac9dbc20f..79b39d36ffb7d 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/tests/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -1,5 +1,4 @@ PRINT-BANG INPUT (DISPLAY): struct M($crate :: S); -PRINT-BANG RE-COLLECTED (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -40,7 +39,6 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/tests/ui/proc-macro/dollar-crate-issue-62325.stdout b/tests/ui/proc-macro/dollar-crate-issue-62325.stdout index 96161049e30b0..bfd013476f3a9 100644 --- a/tests/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/tests/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -1,5 +1,4 @@ PRINT-ATTR INPUT (DISPLAY): struct A(identity! ($crate :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -55,7 +54,6 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct B(identity! ($crate :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/tests/ui/proc-macro/dollar-crate.stdout b/tests/ui/proc-macro/dollar-crate.stdout index a6bdab00441a2..0278ef1ad0fcd 100644 --- a/tests/ui/proc-macro/dollar-crate.stdout +++ b/tests/ui/proc-macro/dollar-crate.stdout @@ -1,5 +1,4 @@ PRINT-BANG INPUT (DISPLAY): struct M($crate :: S); -PRINT-BANG RE-COLLECTED (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -40,7 +39,6 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -81,7 +79,6 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -122,7 +119,6 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ }, ] PRINT-BANG INPUT (DISPLAY): struct M($crate :: S); -PRINT-BANG RE-COLLECTED (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -163,7 +159,6 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -204,7 +199,6 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/tests/ui/proc-macro/expand-to-derive.stdout b/tests/ui/proc-macro/expand-to-derive.stdout index 9f03a469aebf5..d59b7e5b88f45 100644 --- a/tests/ui/proc-macro/expand-to-derive.stdout +++ b/tests/ui/proc-macro/expand-to-derive.stdout @@ -1,12 +1,12 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo { field : - [bool ; { #[rustc_dummy] struct Inner { other_inner_field: u8, } 0 }] + [bool; { #[rustc_dummy] struct Inner { other_inner_field: u8, } 0 }] } PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo { field : - [bool ; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }] + [bool; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }] } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout index eda2f433bce6e..ddd59b583a814 100644 --- a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout +++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout @@ -1,5 +1,5 @@ -PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0 ; 0 }, } -PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0 ; 0 }, } +PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", @@ -123,7 +123,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; }; 0 }, } -PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", @@ -203,7 +203,6 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} }; 0 }, } -PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { {} } ; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", @@ -282,7 +281,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; }; 0 }, } -PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", @@ -360,7 +359,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; }; 0 }, } -PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", @@ -451,7 +450,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; }; 0 }, } -PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 } ; 0 }, } +PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 }; 0 }, } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "enum", diff --git a/tests/ui/proc-macro/inert-attribute-order.stdout b/tests/ui/proc-macro/inert-attribute-order.stdout index 86b2721797439..95b34ae84fd10 100644 --- a/tests/ui/proc-macro/inert-attribute-order.stdout +++ b/tests/ui/proc-macro/inert-attribute-order.stdout @@ -2,10 +2,10 @@ PRINT-ATTR INPUT (DISPLAY): /// 1 #[rustfmt::attr2] #[doc = "3"] #[doc = "4"] #[rustfmt::attr5] /// 6 #[print_attr(nodebug)] struct S; PRINT-ATTR RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt::attr2] #[doc = "3"] #[doc = "4"] #[rustfmt::attr5] -#[doc = " 6"] #[print_attr(nodebug)] struct S ; +#[doc = " 6"] #[print_attr(nodebug)] struct S; PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] -#[rustfmt :: attr5] #[doc = " 6"] #[print_attr(nodebug)] struct S ; +#[rustfmt :: attr5] #[doc = " 6"] #[print_attr(nodebug)] struct S; PRINT-ATTR INPUT (DISPLAY): #[doc = " 1"] #[rustfmt::attr2] #[doc = "3"] #[doc = "4"] #[rustfmt::attr5] -#[doc = " 6"] struct S ; +#[doc = " 6"] struct S; PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] -#[rustfmt :: attr5] #[doc = " 6"] struct S ; +#[rustfmt :: attr5] #[doc = " 6"] struct S; diff --git a/tests/ui/proc-macro/inner-attrs.stdout b/tests/ui/proc-macro/inner-attrs.stdout index 39ec6834f0658..c8d93babe3a48 100644 --- a/tests/ui/proc-macro/inner-attrs.stdout +++ b/tests/ui/proc-macro/inner-attrs.stdout @@ -581,10 +581,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint { field: [u8; { match true { _ => { #![rustc_dummy(third)] true } }; 0 }] } PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct MyDerivePrint -{ - field : - [u8 ; { match true { _ => { #! [rustc_dummy(third)] true } } ; 0 }] -} +{ field : [u8; { match true { _ => { #! [rustc_dummy(third)] true } }; 0 }] } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -718,8 +715,7 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }); -PRINT-ATTR RE-COLLECTED (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }); PRINT-ATTR INPUT (DEBUG): TokenStream [ Group { delimiter: Parenthesis, @@ -834,8 +830,7 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }); -PRINT-ATTR RE-COLLECTED (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ; +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }); PRINT-ATTR INPUT (DEBUG): TokenStream [ Group { delimiter: Parenthesis, diff --git a/tests/ui/proc-macro/input-interpolated.stdout b/tests/ui/proc-macro/input-interpolated.stdout index 6a8789b2c4197..f2a0bc3b1aaf9 100644 --- a/tests/ui/proc-macro/input-interpolated.stdout +++ b/tests/ui/proc-macro/input-interpolated.stdout @@ -5,7 +5,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ span: #0 bytes(503..504), }, ] -PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0 ; +PRINT-ATTR INPUT (DISPLAY): const A : u8 = 0; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "const", diff --git a/tests/ui/proc-macro/issue-118455-skip-err-builtin.rs b/tests/ui/proc-macro/issue-118455-skip-err-builtin.rs new file mode 100644 index 0000000000000..baef020612891 --- /dev/null +++ b/tests/ui/proc-macro/issue-118455-skip-err-builtin.rs @@ -0,0 +1,6 @@ +#![some_nonexistent_attribute] +//~^ ERROR cannot find attribute `some_nonexistent_attribute` in this scope +#[derive(Debug)] +pub struct SomeUserCode; + +fn main() {} diff --git a/tests/ui/proc-macro/issue-118455-skip-err-builtin.stderr b/tests/ui/proc-macro/issue-118455-skip-err-builtin.stderr new file mode 100644 index 0000000000000..fa8af87a3d019 --- /dev/null +++ b/tests/ui/proc-macro/issue-118455-skip-err-builtin.stderr @@ -0,0 +1,8 @@ +error: cannot find attribute `some_nonexistent_attribute` in this scope + --> $DIR/issue-118455-skip-err-builtin.rs:1:4 + | +LL | #![some_nonexistent_attribute] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/proc-macro/issue-75734-pp-paren.stdout b/tests/ui/proc-macro/issue-75734-pp-paren.stdout index ee135366fb68b..9919ab5625fa1 100644 --- a/tests/ui/proc-macro/issue-75734-pp-paren.stdout +++ b/tests/ui/proc-macro/issue-75734-pp-paren.stdout @@ -1,5 +1,5 @@ PRINT-ATTR INPUT (DISPLAY): fn main() { &|_: u8| {}; mul_2!(1 + 1); } -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn main() { &| _ : u8 | {} ; mul_2! (1 + 1) ; } +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn main() { &| _ : u8 | {}; mul_2! (1 + 1); } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout index 093e37f8a8d0e..cc712abf2a576 100644 --- a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout +++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout @@ -51,22 +51,22 @@ struct Foo <#[cfg(FALSE)] A, B > { #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second : bool, third : - [u8 ; + [u8; { - #[cfg(FALSE)] struct Bar ; #[cfg(not(FALSE))] struct Inner ; - #[cfg(FALSE)] let a = 25 ; match true + #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner; + #[cfg(FALSE)] let a = 25; match true { #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))] false => {}, _ => {} - } ; #[print_helper(should_be_removed)] fn removed_fn() + }; #[print_helper(should_be_removed)] fn removed_fn() { #! [cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() - { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum + { #! [cfg(not(FALSE))] let my_val = true; } enum TupleEnum { Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32, #[cfg(FALSE)] String, u8) } struct TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32, - #[cfg(FALSE)] bool, u8) ; fn plain_removed_fn() + #[cfg(FALSE)] bool, u8); fn plain_removed_fn() { #! [cfg_attr(not(FALSE), cfg(FALSE))] } 0 }], #[print_helper(d)] fourth : B } @@ -1336,14 +1336,14 @@ PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_hel PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo { second : bool, third : - [u8 ; + [u8; { - #[cfg(not(FALSE))] struct Inner ; match true - { #[allow(warnings)] false => {}, _ => {} } ; #[print_helper(c)] + #[cfg(not(FALSE))] struct Inner; match true + { #[allow(warnings)] false => {}, _ => {} }; #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn() - { #! [cfg(not(FALSE))] let my_val = true ; } enum TupleEnum + { #! [cfg(not(FALSE))] let my_val = true; } enum TupleEnum { Foo(#[cfg(not(FALSE))] i32, u8) } struct - TupleStruct(#[cfg(not(FALSE))] i32, u8) ; 0 + TupleStruct(#[cfg(not(FALSE))] i32, u8); 0 }], #[print_helper(d)] fourth : B } PRINT-DERIVE INPUT (DEBUG): TokenStream [ diff --git a/tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout b/tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout index 09eb33f7e31a1..fdbf9118cd32f 100644 --- a/tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout +++ b/tests/ui/proc-macro/issue-76182-leading-vert-pat.stdout @@ -1,4 +1,4 @@ -PRINT-ATTR INPUT (DISPLAY): fn main() { match() { | () => () } } +PRINT-ATTR INPUT (DISPLAY): fn main() { match () { | () => () } } PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "fn", diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed new file mode 100644 index 0000000000000..a61c868ed0a1a --- /dev/null +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed @@ -0,0 +1,7 @@ +// run-rustfix + +#[derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +#[allow(dead_code)] +struct Test {} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs new file mode 100644 index 0000000000000..403f4470de77b --- /dev/null +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs @@ -0,0 +1,7 @@ +// run-rustfix + +#![derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +#[allow(dead_code)] +struct Test {} + +fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr new file mode 100644 index 0000000000000..09908160542d4 --- /dev/null +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr @@ -0,0 +1,17 @@ +error: `derive` attribute cannot be used at crate level + --> $DIR/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs:3:1 + | +LL | #![derive(Debug)] + | ^^^^^^^^^^^^^^^^^ +LL | #[allow(dead_code)] +LL | struct Test {} + | ---- the inner attribute doesn't annotate this struct + | +help: perhaps you meant to use an outer attribute + | +LL - #![derive(Debug)] +LL + #[derive(Debug)] + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/proc-macro/keep-expr-tokens.stdout b/tests/ui/proc-macro/keep-expr-tokens.stdout index 8e4d4785e2ee9..fdd191261095c 100644 --- a/tests/ui/proc-macro/keep-expr-tokens.stdout +++ b/tests/ui/proc-macro/keep-expr-tokens.stdout @@ -1,5 +1,5 @@ PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 +1; } -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[rustc_dummy] { 1 + 1 ; } +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[rustc_dummy] { 1 + 1; } PRINT-ATTR INPUT (DEBUG): TokenStream [ Punct { ch: '#', diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout index 89817a1efdc5b..257d59974b88d 100644 --- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout +++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout @@ -1,7 +1,7 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo { val : - [bool ; + [bool; { let a = #[rustc_dummy(first)] #[rustc_dummy(second)] { #![allow(unused)] 30 }; 0 @@ -10,10 +10,10 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo { val : - [bool ; + [bool; { let a = #[rustc_dummy(first)] #[rustc_dummy(second)] - { #! [allow(unused)] 30 } ; 0 + { #! [allow(unused)] 30 }; 0 }] } PRINT-DERIVE INPUT (DEBUG): TokenStream [ diff --git a/tests/ui/proc-macro/nested-derive-cfg.stdout b/tests/ui/proc-macro/nested-derive-cfg.stdout index c94808c3c0f8a..a3046e4ab85cb 100644 --- a/tests/ui/proc-macro/nested-derive-cfg.stdout +++ b/tests/ui/proc-macro/nested-derive-cfg.stdout @@ -1,7 +1,7 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo { my_array: [bool; { struct Inner { non_removed_inner_field: usize } 0 }] } PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo -{ my_array : [bool ; { struct Inner { non_removed_inner_field : usize } 0 }] } +{ my_array : [bool; { struct Inner { non_removed_inner_field : usize } 0 }] } PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index d3c2c46ac75cf..cf9addb8a947d 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -1,5 +1,4 @@ PRINT-BANG INPUT (DISPLAY): struct S; -PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): struct S ; PRINT-BANG INPUT (DEBUG): TokenStream [ Group { delimiter: None, diff --git a/tests/ui/proc-macro/pretty-print-tts.stdout b/tests/ui/proc-macro/pretty-print-tts.stdout index fbe8640a01a5f..ce40431350706 100644 --- a/tests/ui/proc-macro/pretty-print-tts.stdout +++ b/tests/ui/proc-macro/pretty-print-tts.stdout @@ -1,5 +1,5 @@ PRINT-BANG INPUT (DISPLAY): { #![rustc_dummy] let a = "hello".len(); matches!(a, 5); } -PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): { #! [rustc_dummy] let a = "hello".len() ; matches! (a, 5) ; } +PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): { #! [rustc_dummy] let a = "hello".len(); matches! (a, 5); } PRINT-BANG INPUT (DEBUG): TokenStream [ Group { delimiter: Brace, diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr index 96c1ffb2f7e32..3d9b7a940b7c8 100644 --- a/tests/ui/range/range-1.stderr +++ b/tests/ui/range/range-1.stderr @@ -8,7 +8,7 @@ error[E0277]: the trait bound `bool: Step` is not satisfied --> $DIR/range-1.rs:9:14 | LL | for i in false..true {} - | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool` + | ^^^^^^^^^^^ the trait `Step` is not implemented for `bool`, which is required by `std::ops::Range: IntoIterator` | = help: the following other types implement trait `Step`: char @@ -30,7 +30,7 @@ LL | let range = *arr..; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[{integer}]` -note: required by a bound in `RangeFrom` +note: required by an implicit `Sized` bound in `RangeFrom` --> $SRC_DIR/core/src/ops/range.rs:LL:COL error: aborting due to 3 previous errors diff --git a/tests/ui/recursion/recursive-requirements.stderr b/tests/ui/recursion/recursive-requirements.stderr index bb63f7cd0dce0..f5cbed0ce3475 100644 --- a/tests/ui/recursion/recursive-requirements.stderr +++ b/tests/ui/recursion/recursive-requirements.stderr @@ -4,7 +4,7 @@ error[E0277]: `*const Bar` cannot be shared between threads safely LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Bar` cannot be shared between threads safely | - = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar` + = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar`, which is required by `Foo: Sync` note: required because it appears within the type `Foo` --> $DIR/recursive-requirements.rs:5:12 | @@ -22,7 +22,7 @@ error[E0277]: `*const Foo` cannot be shared between threads safely LL | let _: AssertSync = unimplemented!(); | ^^^^^^^^^^^^^^^ `*const Foo` cannot be shared between threads safely | - = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo` + = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo`, which is required by `Foo: Sync` note: required because it appears within the type `Bar` --> $DIR/recursive-requirements.rs:10:12 | diff --git a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr index 2ec2ca49b1142..b15d2affeea37 100644 --- a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr +++ b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr @@ -21,11 +21,11 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined here LL | struct Foo<'a,'b,'c> { | ^^ -error[E0392]: parameter `'c` is never used +error[E0392]: lifetime parameter `'c` is never used --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18 | LL | struct Foo<'a,'b,'c> { - | ^^ unused parameter + | ^^ unused lifetime parameter | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs index d364c467714ce..2aa390bfd39f9 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs @@ -5,13 +5,13 @@ fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a { fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough } fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y); + a(x, y); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index d8269514befd9..5a02d01b4e1ca 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs index 60dafdd528cf2..baf1693b0ccdf 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -6,14 +6,14 @@ fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough *z = *y; } fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y, z); + a(x, y, z); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index e383f352b9e97..063ff46bb6c47 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 + | +LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 + | +LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y, z); + | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.rs b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs index 177f52fa72d55..c7b7b52d50d0a 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.rs +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs @@ -5,13 +5,13 @@ fn a<'a, 'b:'a>(x: &mut &'a isize, y: &mut &'b isize) { fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough } fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y); + a(x, y); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr index 989e91c702b83..830a61a21f9da 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-no-variance-from-fn-generics.rs b/tests/ui/regions/regions-no-variance-from-fn-generics.rs index 76706a8278197..a455d4efd71b5 100644 --- a/tests/ui/regions/regions-no-variance-from-fn-generics.rs +++ b/tests/ui/regions/regions-no-variance-from-fn-generics.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Issue #12856: a lifetime formal binding introduced by a generic fn // should not upset the variance inference for actual occurrences of diff --git a/tests/ui/reserved/reserved-attr-on-macro.rs b/tests/ui/reserved/reserved-attr-on-macro.rs index 2630db0d09785..5c4657e0ec2e1 100644 --- a/tests/ui/reserved/reserved-attr-on-macro.rs +++ b/tests/ui/reserved/reserved-attr-on-macro.rs @@ -7,5 +7,5 @@ macro_rules! foo { } fn main() { - foo!(); //~ ERROR cannot determine resolution for the macro `foo` + foo!(); } diff --git a/tests/ui/reserved/reserved-attr-on-macro.stderr b/tests/ui/reserved/reserved-attr-on-macro.stderr index e55b58bef2855..066f72367b1a5 100644 --- a/tests/ui/reserved/reserved-attr-on-macro.stderr +++ b/tests/ui/reserved/reserved-attr-on-macro.stderr @@ -4,19 +4,11 @@ error: attributes starting with `rustc` are reserved for use by the `rustc` comp LL | #[rustc_attribute_should_be_reserved] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: cannot determine resolution for the macro `foo` - --> $DIR/reserved-attr-on-macro.rs:10:5 - | -LL | foo!(); - | ^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: cannot find attribute `rustc_attribute_should_be_reserved` in this scope --> $DIR/reserved-attr-on-macro.rs:1:3 | LL | #[rustc_attribute_should_be_reserved] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs b/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs new file mode 100644 index 0000000000000..36fe16f64ebeb --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-0.rs @@ -0,0 +1,10 @@ +fn make() {} +//~^ ERROR expected trait, found builtin type `u32` +//~| HELP you might have meant to write a const parameter here + +struct Array([bool; N]); +//~^ ERROR expected trait, found builtin type `usize` +//~| HELP you might have meant to write a const parameter here +//~| ERROR expected value, found type parameter `N` + +fn main() {} diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr b/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr new file mode 100644 index 0000000000000..4e411eae3cbbb --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr @@ -0,0 +1,34 @@ +error[E0404]: expected trait, found builtin type `u32` + --> $DIR/change-ty-to-const-param-sugg-0.rs:1:12 + | +LL | fn make() {} + | ^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | fn make() {} + | +++++ + +error[E0404]: expected trait, found builtin type `usize` + --> $DIR/change-ty-to-const-param-sugg-0.rs:5:17 + | +LL | struct Array([bool; N]); + | ^^^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | struct Array([bool; N]); + | +++++ + +error[E0423]: expected value, found type parameter `N` + --> $DIR/change-ty-to-const-param-sugg-0.rs:5:31 + | +LL | struct Array([bool; N]); + | - ^ not a value + | | + | found this type parameter + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0404, E0423. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs b/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs new file mode 100644 index 0000000000000..b1d2595f3790f --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-1.rs @@ -0,0 +1,24 @@ +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +use std::marker::ConstParamTy; + +struct Tagged; +//~^ ERROR expected trait, found enum `Tag` +//~| HELP you might have meant to write a const parameter here +//~| ERROR expected trait, found struct `Options` +//~| HELP you might have meant to write a const parameter here + +#[derive(PartialEq, Eq, ConstParamTy)] +enum Tag { + One, + Two, +} + +#[derive(PartialEq, Eq, ConstParamTy)] +struct Options { + verbose: bool, + safe: bool, +} + +fn main() {} diff --git a/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr b/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr new file mode 100644 index 0000000000000..933fac27f8f4e --- /dev/null +++ b/tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr @@ -0,0 +1,25 @@ +error[E0404]: expected trait, found enum `Tag` + --> $DIR/change-ty-to-const-param-sugg-1.rs:6:18 + | +LL | struct Tagged; + | ^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | struct Tagged; + | +++++ + +error[E0404]: expected trait, found struct `Options` + --> $DIR/change-ty-to-const-param-sugg-1.rs:6:26 + | +LL | struct Tagged; + | ^^^^^^^ not a trait + | +help: you might have meant to write a const parameter here + | +LL | struct Tagged; + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr index 4f8538292792c..fbb9ede8aa175 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr @@ -5,6 +5,8 @@ LL | fn outer() { // outer function | - type parameter from outer item LL | const K: u32 = T::C; | ^^^^ use of generic parameter from outer item + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24 @@ -14,6 +16,8 @@ LL | impl Tr for T { // outer impl block LL | const C: u32 = { LL | const I: u32 = T::C; | ^^^^ use of generic parameter from outer item + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20 @@ -22,6 +26,8 @@ LL | struct S(U32<{ // outer struct | - type parameter from outer item LL | const _: u32 = T::C; | ^^^^ use of generic parameter from outer item + | + = note: a `const` is a separate item from the item that contains it error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 1cb55842bc665..60aa94038c3ad 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -7,6 +7,8 @@ LL | const K: u32 = T::C; | - ^^^^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `` + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24 @@ -18,6 +20,8 @@ LL | const I: u32 = T::C; | - ^^^^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `` + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20 @@ -28,6 +32,8 @@ LL | const _: u32 = T::C; | - ^^^^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `` + | + = note: a `const` is a separate item from the item that contains it error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed index e730f94660bbd..a7ab88fe99357 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![deny(unused_qualifications)] #![feature(unsized_fn_params)] diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs index 641c892e3de9a..05936b191ffea 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![deny(unused_qualifications)] #![feature(unsized_fn_params)] diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr index d9c7fd21871ba..bcda721071235 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr @@ -1,11 +1,11 @@ error: unnecessary qualification - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:12:6 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:13:6 | LL | impl ops::Index for A { | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:3:9 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:4:9 | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL + impl Index for A { | error: unnecessary qualification - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:28:6 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:29:6 | LL | impl inner::Trait for () {} | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/resolve/issue-12796.rs b/tests/ui/resolve/issue-12796.rs index de3e73437f080..e5dcf9643453b 100644 --- a/tests/ui/resolve/issue-12796.rs +++ b/tests/ui/resolve/issue-12796.rs @@ -1,7 +1,7 @@ trait Trait { fn outer(&self) { fn inner(_: &Self) { - //~^ ERROR can't use generic parameters from outer item + //~^ ERROR can't use `Self` from outer item } } } diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr index 6809fd50f7475..2305971303a71 100644 --- a/tests/ui/resolve/issue-12796.stderr +++ b/tests/ui/resolve/issue-12796.stderr @@ -1,10 +1,10 @@ -error[E0401]: can't use generic parameters from outer item +error[E0401]: can't use `Self` from outer item --> $DIR/issue-12796.rs:3:22 | LL | fn inner(_: &Self) { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | can't use `Self` here error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr index 363bb55647827..ca32147d19765 100644 --- a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr +++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr @@ -6,6 +6,8 @@ LL | unsafe fn foo() { LL | extern "C" { LL | static baz: *const A; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr index f1fe1a6002c93..98ffb4567f164 100644 --- a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -6,6 +6,8 @@ LL | fn f() { LL | extern "C" { LL | static a: *const T; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:9:22 @@ -14,6 +16,8 @@ LL | fn g() { | - type parameter from outer item LL | static a: *const T = Default::default(); | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:15:24 @@ -23,6 +27,8 @@ LL | fn h() { LL | extern "C" { LL | static a: [u8; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:21:20 @@ -31,6 +37,8 @@ LL | fn i() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:21:29 @@ -39,6 +47,8 @@ LL | fn i() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error: aborting due to 5 previous errors diff --git a/tests/ui/resolve/use-self-in-inner-fn.rs b/tests/ui/resolve/use-self-in-inner-fn.rs index f4dfa4c40ab24..62f9dc5664ffe 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.rs +++ b/tests/ui/resolve/use-self-in-inner-fn.rs @@ -4,8 +4,8 @@ impl A { //~^ NOTE `Self` type implicitly declared here, by this `impl` fn banana(&mut self) { fn peach(this: &Self) { - //~^ ERROR can't use generic parameters from outer item - //~| NOTE use of generic parameter from outer item + //~^ ERROR can't use `Self` from outer item + //~| NOTE use of `Self` from outer item //~| NOTE refer to the type directly here instead } } diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr index 165e100bf2f5c..9c388df8bc20c 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.stderr +++ b/tests/ui/resolve/use-self-in-inner-fn.stderr @@ -1,4 +1,4 @@ -error[E0401]: can't use generic parameters from outer item +error[E0401]: can't use `Self` from outer item --> $DIR/use-self-in-inner-fn.rs:6:25 | LL | impl A { @@ -7,7 +7,7 @@ LL | impl A { LL | fn peach(this: &Self) { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | refer to the type directly here instead error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs index 2490909b6a5a9..715f5874b2cc2 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs @@ -3,8 +3,9 @@ fn main() {} fn attr_in_guard() { match None:: { Some(!) //~ ERROR `!` patterns are experimental + //~^ ERROR: mismatched types if #[deny(unused_mut)] //~ ERROR attributes on expressions are experimental false //~ ERROR a guard on a never pattern will never be run } - match false {} + match false {} //~ ERROR: `bool` is non-empty } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr index a456b686e56e3..f16f5e5be8734 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:6:16 + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:7:16 | LL | if #[deny(unused_mut)] | ^^^^^^^^^^^^^^^^^^^ @@ -19,11 +19,34 @@ LL | Some(!) = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: a guard on a never pattern will never be run - --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:7:13 + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:8:13 | LL | false | ^^^^^ help: remove this guard -error: aborting due to 3 previous errors +error: mismatched types + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:5:14 + | +LL | Some(!) + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `u32` + +error[E0004]: non-exhaustive patterns: type `bool` is non-empty + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:10:11 + | +LL | match false {} + | ^^^^^ + | + = note: the matched value is of type `bool` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match false { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0004, E0658. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs index f2e238ecb136a..11489ccaacd36 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -1,6 +1,7 @@ #![feature(never_patterns)] #![allow(incomplete_features)] +#[derive(Copy, Clone)] enum Void {} fn main() { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr index b69ba80af88ea..d9c0f67335cdc 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -1,47 +1,47 @@ error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:16:15 + --> $DIR/bindings.rs:17:15 | LL | Err(&(_a, _b, !)), | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:16:19 + --> $DIR/bindings.rs:17:19 | LL | Err(&(_a, _b, !)), | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:21:25 + --> $DIR/bindings.rs:22:25 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:21:29 + --> $DIR/bindings.rs:22:29 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:34:10 + --> $DIR/bindings.rs:35:10 | LL | let (_a, (! | !)) = (true, void); | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:38:9 + --> $DIR/bindings.rs:39:9 | LL | let _a @ ! = void; | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:41:10 + --> $DIR/bindings.rs:42:10 | LL | let (_a @ (), !) = ((), void); | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:44:14 + --> $DIR/bindings.rs:45:14 | LL | (_b @ (_, !))) = (true, void); | ^^ help: use a wildcard `_` instead diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs index e298112244a22..b6da0c20e0778 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs @@ -15,18 +15,18 @@ fn no_arms_or_guards(x: Void) { //~^ ERROR a never pattern is always unreachable None => {} } - match None:: { + match None:: { //~ ERROR: `Some(_)` not covered Some(!) if true, //~^ ERROR guard on a never pattern None => {} } - match None:: { + match None:: { //~ ERROR: `Some(_)` not covered Some(!) if true => {} //~^ ERROR a never pattern is always unreachable None => {} } match None:: { - Some(never!()) => {}, + Some(never!()) => {} //~^ ERROR a never pattern is always unreachable None => {} } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr index bfbc7a1b5340c..5497252890f70 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr @@ -25,11 +25,48 @@ LL | Some(!) if true => {} error: a never pattern is always unreachable --> $DIR/check.rs:29:27 | -LL | Some(never!()) => {}, +LL | Some(never!()) => {} | ^^ | | | this will never be executed | help: remove this expression -error: aborting due to 4 previous errors +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/check.rs:18:11 + | +LL | match None:: { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/check.rs:23:11 + | +LL | match None:: { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 31a23fa002c30..72ee4d24bb629 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -2,7 +2,7 @@ //[pass] check-pass //[fail] check-fail #![feature(never_patterns)] -#![feature(exhaustive_patterns)] +#![feature(min_exhaustive_patterns)] #![allow(incomplete_features)] #[derive(Copy, Clone)] @@ -107,7 +107,7 @@ fn never_pattern_typeck_pass(void: Void) { } match (&[] as &[Void]) { [] => {} - [!], + [!, ..], } // Accept on a composite empty type. match None::<&(u32, Void)> { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs index df8e22abf6232..0374cbdbc1fd2 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs @@ -2,7 +2,7 @@ //[normal] check-pass #![feature(never_patterns)] #![allow(incomplete_features)] -#![cfg_attr(exh_pats, feature(exhaustive_patterns))] +#![cfg_attr(exh_pats, feature(min_exhaustive_patterns))] #![allow(dead_code, unreachable_code)] #![deny(unreachable_patterns)] diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr index 910d491baaf43..9945041113d79 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr @@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLIN | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr index cadd9be023c50..6ac261ae81437 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr @@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr index e4321cc6a4c71..41616fb90fe96 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr @@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itse | ^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9 + | +LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr index decc29ad67cd2..99dea5171d1bc 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr @@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9 + | +LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr index 080bf5885ba75..11163ba70ec65 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr @@ -5,7 +5,7 @@ LL | Wrap(CFN1) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: `#[warn(pointer_structural_match)]` on by default warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. @@ -15,7 +15,7 @@ LL | Wrap(CFN2) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 @@ -24,7 +24,7 @@ LL | Wrap(CFN3) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 @@ -33,7 +33,7 @@ LL | Wrap(CFN4) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 @@ -42,7 +42,7 @@ LL | Wrap(CFN5) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 @@ -51,7 +51,7 @@ LL | Wrap(CFN6) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 @@ -60,7 +60,7 @@ LL | Wrap(CFN7) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 @@ -69,7 +69,7 @@ LL | Wrap(CFN8) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 @@ -78,7 +78,7 @@ LL | Wrap(CFN9) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 @@ -87,7 +87,117 @@ LL | CFOO => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: 10 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14 + | +LL | Wrap(CFN1) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14 + | +LL | Wrap(CFN2) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 + | +LL | Wrap(CFN3) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 + | +LL | Wrap(CFN4) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 + | +LL | Wrap(CFN5) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 + | +LL | Wrap(CFN6) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 + | +LL | Wrap(CFN7) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 + | +LL | Wrap(CFN8) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 + | +LL | Wrap(CFN9) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 + | +LL | CFOO => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs index fdb67bcf2d8e4..374e5d5acd080 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs @@ -10,7 +10,7 @@ // Issue 62307 pointed out a case where the structural-match checking // was too shallow. -#![warn(indirect_structural_match, nontrivial_structural_match)] +#![warn(indirect_structural_match)] // run-pass #[derive(Debug)] diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr index d0f2b820afa90..d4ab1ce3ba2ad 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -5,13 +5,13 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 | -LL | #![warn(indirect_structural_match, nontrivial_structural_match)] +LL | #![warn(indirect_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` @@ -21,9 +21,43 @@ LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9 + | +LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9 + | +LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index 4fdfce60bb861..0edcf44c4d795 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -5,7 +5,7 @@ LL | B(TEST) => println!("matched"), | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 note: the lint level is defined here --> $DIR/issue-63479-match-fnptr.rs:8:9 | @@ -19,7 +19,37 @@ LL | TEST2 => println!("matched"), | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 + = note: for more information, see issue #120362 warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:36:7 + | +LL | B(TEST) => println!("matched"), + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:42:5 + | +LL | TEST2 => println!("matched"), + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs new file mode 100644 index 0000000000000..d43db576b3848 --- /dev/null +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.rs @@ -0,0 +1,41 @@ +// Matching against NaN should result in an error +#![feature(exclusive_range_pattern)] +#![allow(unused)] + +const NAN: f64 = f64::NAN; + +#[derive(PartialEq, Eq)] +struct MyType(T); + +const C: MyType = MyType(f32::NAN); + +fn main() { + let x = NAN; + match x { + NAN => {}, //~ ERROR cannot use NaN in patterns + _ => {}, + }; + + match [x, 1.0] { + [NAN, _] => {}, //~ ERROR cannot use NaN in patterns + _ => {}, + }; + + match MyType(1.0f32) { + C => {}, //~ ERROR cannot use NaN in patterns + _ => {}, + } + + // Also cover range patterns + match x { + NAN..=1.0 => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than or equal to upper + -1.0..=NAN => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than or equal to upper + NAN.. => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than or equal to upper + ..NAN => {}, //~ ERROR cannot use NaN in patterns + //~^ ERROR lower range bound must be less than upper + _ => {}, + }; +} diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr new file mode 100644 index 0000000000000..167ada783c24c --- /dev/null +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804-nan-match.stderr @@ -0,0 +1,91 @@ +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:15:9 + | +LL | NAN => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:20:10 + | +LL | [NAN, _] => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:25:9 + | +LL | C => {}, + | ^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:31:9 + | +LL | NAN..=1.0 => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/issue-6804-nan-match.rs:31:9 + | +LL | NAN..=1.0 => {}, + | ^^^^^^^^^ lower bound larger than upper bound + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:33:16 + | +LL | -1.0..=NAN => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/issue-6804-nan-match.rs:33:9 + | +LL | -1.0..=NAN => {}, + | ^^^^^^^^^^ lower bound larger than upper bound + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:35:9 + | +LL | NAN.. => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0030]: lower range bound must be less than or equal to upper + --> $DIR/issue-6804-nan-match.rs:35:9 + | +LL | NAN.. => {}, + | ^^^^^ lower bound larger than upper bound + +error: cannot use NaN in patterns + --> $DIR/issue-6804-nan-match.rs:37:11 + | +LL | ..NAN => {}, + | ^^^ + | + = note: NaNs compare inequal to everything, even themselves, so this pattern would never match + = help: try using the `is_nan` method instead + +error[E0579]: lower range bound must be less than upper + --> $DIR/issue-6804-nan-match.rs:37:9 + | +LL | ..NAN => {}, + | ^^^^^ + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0030, E0579. +For more information about an error, try `rustc --explain E0030`. diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs deleted file mode 100644 index 0260caa82cb1d..0000000000000 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Matching against NaN should result in a warning - -#![allow(unused)] -#![deny(illegal_floating_point_literal_pattern)] - -const NAN: f64 = f64::NAN; - -fn main() { - let x = NAN; - match x { - NAN => {}, //~ ERROR floating-point types cannot be used - //~| WARN this was previously accepted by the compiler but is being phased out - _ => {}, - }; - - match [x, 1.0] { - [NAN, _] => {}, //~ ERROR floating-point types cannot be used - //~| WARN this was previously accepted by the compiler but is being phased out - _ => {}, - }; -} diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr deleted file mode 100644 index f37255d0828cd..0000000000000 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error: floating-point types cannot be used in patterns - --> $DIR/issue-6804.rs:11:9 - | -LL | NAN => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 -note: the lint level is defined here - --> $DIR/issue-6804.rs:4:9 - | -LL | #![deny(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: floating-point types cannot be used in patterns - --> $DIR/issue-6804.rs:17:10 - | -LL | [NAN, _] => {}, - | ^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #41620 - -error: aborting due to 2 previous errors - diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index 0a703367d969d..4d23922892ea9 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `f32: Termination` is not satisfied LL | #[test] | ------- in this procedural macro expansion LL | fn can_parse_zero_as_f32() -> Result { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`, which is required by `Result: Termination` | = note: required for `Result` to implement `Termination` note: required by a bound in `assert_test_result` diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr new file mode 100644 index 0000000000000..4a219ff8b5562 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr new file mode 100644 index 0000000000000..4a219ff8b5562 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs index c7665affb992b..c8eee9835fed3 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -19,7 +19,7 @@ trait Bad { } trait Good { - fn good_virt(&self) -> char { + fn good_virt(&self) -> char { //~ WARN methods `good_virt` and `good_indirect` are never used panic!() } fn good_indirect(&self) -> char { diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs index 43e33cbb12061..351438a54707a 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs @@ -7,7 +7,9 @@ use std::arch::asm; //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn f() { - asm!("", options(noreturn)); + unsafe { + asm!("", options(noreturn)); + } } struct S; @@ -17,7 +19,9 @@ impl S { //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn g() { - asm!("", options(noreturn)); + unsafe { + asm!("", options(noreturn)); + } } } diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr index 3f7d0df42a00a..04c5c649d7fd8 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr @@ -5,7 +5,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0736]: cannot use `#[track_caller]` with `#[naked]` - --> $DIR/error-with-naked.rs:16:5 + --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/error-with-naked.rs:16:5 + --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr index 7ec018a95cc72..eb6abbf80451c 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr @@ -4,7 +4,7 @@ error[E0277]: `NotDebug` doesn't implement `Debug` LL | let _: NotDebug = dbg!(NotDebug); | ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `NotDebug` + = help: the trait `Debug` is not implemented for `NotDebug`, which is required by `&NotDebug: Debug` = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug` = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NotDebug` with `#[derive(Debug)]` diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs index 1374ad935a388..a032a2ca05232 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -12,7 +12,7 @@ fn call(f: impl Fn()) { f() } -fn call_mut(f: impl FnMut()) { +fn call_mut(mut f: impl FnMut()) { f() } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 100f2048269dc..67bfaa4c98c79 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -27,10 +27,10 @@ LL | call_mut(foo); = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:21 + --> $DIR/fn-traits.rs:15:25 | -LL | fn call_mut(f: impl FnMut()) { - | ^^^^^^^ required by this bound in `call_mut` +LL | fn call_mut(mut f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `fn() {foo}` --> $DIR/fn-traits.rs:26:15 @@ -80,10 +80,10 @@ LL | call_mut(foo_unsafe); = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:21 + --> $DIR/fn-traits.rs:15:25 | -LL | fn call_mut(f: impl FnMut()) { - | ^^^^^^^ required by this bound in `call_mut` +LL | fn call_mut(mut f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:32:15 diff --git a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr index 6af1d4533b7c2..99d318a793364 100644 --- a/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr +++ b/tests/ui/rfcs/rfc-2397-do-not-recommend/feature-gate-do_not_recommend.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `u8: Foo` is not satisfied --> $DIR/feature-gate-do_not_recommend.rs:19:11 | LL | stuff(1u8); - | ----- ^^^ the trait `Foo` is not implemented for `u8` + | ----- ^^^ the trait `Foo` is not implemented for `u8`, which is required by `u8: Bar` | | | required by a bound introduced by this call | diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index d70b0d66177eb..14c41f3e01d6f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -4,5 +4,19 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn need_const_closure i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method-fail.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index 1642de78692b7..8fe11fffbf9f8 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -4,5 +4,19 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn need_const_closure i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn need_const_closure i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr index 2e448c64d7a40..b66b27ad2bdd5 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr @@ -22,5 +22,45 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn answer u8>(f: &F) -> u8 { | ^^^^^^^^^^ -error: aborting due to 4 previous errors +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:12:5 + | +LL | f() * 7 + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>, + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:5 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:11 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn answer u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error: aborting due to 7 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs index b3977e6cede0f..2468d51cfdd17 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs @@ -30,8 +30,7 @@ fn non_const_context() { #[unstable(feature = "none", issue = "none")] const fn const_context() { Unstable::func(); - // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is - // not const-stable. + //[stable]~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn // ^ fails, because the `foo` feature is not active @@ -42,8 +41,7 @@ const fn const_context() { pub const fn const_context_not_const_stable() { //[stable]~^ ERROR function has missing const stability attribute Unstable::func(); - // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is - // not const-stable. + //[stable]~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn // ^ fails, because the `foo` feature is not active @@ -53,7 +51,7 @@ pub const fn const_context_not_const_stable() { #[rustc_const_stable(feature = "cheese", since = "1.0.0")] const fn stable_const_context() { Unstable::func(); - //[unstable]~^ ERROR not yet stable as a const fn + //~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn const_context_not_const_stable() diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr index a1aca762ef479..9512953977003 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -10,16 +10,40 @@ LL | | } = note: see issue #67792 for more information error: function has missing const stability attribute - --> $DIR/staged-api.rs:42:1 + --> $DIR/staged-api.rs:41:1 | LL | / pub const fn const_context_not_const_stable() { LL | | LL | | Unstable::func(); -LL | | // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is +LL | | ... | LL | | // ^ fails, because the `foo` feature is not active LL | | } | |_^ -error: aborting due to 2 previous errors +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:32:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:43:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:53:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr index c38d1a81ae77b..c9ca15d5b565f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -1,5 +1,5 @@ error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:35:5 + --> $DIR/staged-api.rs:34:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:47:5 + --> $DIR/staged-api.rs:45:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:55:5 + --> $DIR/staged-api.rs:53:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | Unstable::func(); = help: const-stable functions can only call other const-stable functions error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:57:5 + --> $DIR/staged-api.rs:55:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | Foo::func(); = help: const-stable functions can only call other const-stable functions error: `const_context_not_const_stable` is not yet stable as a const fn - --> $DIR/staged-api.rs:59:5 + --> $DIR/staged-api.rs:57:5 | LL | const_context_not_const_stable() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr index bf53b995bb673..e51ff1483390c 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr @@ -4,6 +4,16 @@ error[E0635]: unknown feature `const_default_impls` LL | #![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const fn ` as Default>::default` in constant functions + --> $DIR/std-impl-gate.rs:13:5 + | +LL | Default::default() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr index d57f5702a6382..92a9c347a075e 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr @@ -272,11 +272,11 @@ LL | type Type = (); = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/tilde-const-invalid-places.rs:11:19 | LL | struct UnitStruct; - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/rust-2018/issue-51008-1.rs b/tests/ui/rust-2018/issue-51008-1.rs index da7b8ef65c566..67dfbf6460133 100644 --- a/tests/ui/rust-2018/issue-51008-1.rs +++ b/tests/ui/rust-2018/issue-51008-1.rs @@ -2,7 +2,7 @@ // being incorrectly considered part of the "elided lifetimes" from // the impl. // -// run-pass +// check-pass trait A { diff --git a/tests/ui/rust-2018/issue-51008.rs b/tests/ui/rust-2018/issue-51008.rs index 56517b9adee65..f9e4bc14ec82c 100644 --- a/tests/ui/rust-2018/issue-51008.rs +++ b/tests/ui/rust-2018/issue-51008.rs @@ -2,7 +2,7 @@ // being incorrectly considered part of the "elided lifetimes" from // the impl. // -// run-pass +// check-pass trait A { diff --git a/tests/ui/rust-2018/issue-54006.rs b/tests/ui/rust-2018/issue-54006.rs index a7a4770fc02f9..6f929731c7674 100644 --- a/tests/ui/rust-2018/issue-54006.rs +++ b/tests/ui/rust-2018/issue-54006.rs @@ -8,6 +8,5 @@ use alloc::vec; pub fn foo() { let mut xs = vec![]; - //~^ ERROR cannot determine resolution for the macro `vec` xs.push(0); } diff --git a/tests/ui/rust-2018/issue-54006.stderr b/tests/ui/rust-2018/issue-54006.stderr index 1978138a68878..35d4c17d2c7f1 100644 --- a/tests/ui/rust-2018/issue-54006.stderr +++ b/tests/ui/rust-2018/issue-54006.stderr @@ -4,14 +4,6 @@ error[E0432]: unresolved import `alloc` LL | use alloc::vec; | ^^^^^ help: a similar path exists: `core::alloc` -error: cannot determine resolution for the macro `vec` - --> $DIR/issue-54006.rs:10:18 - | -LL | let mut xs = vec![]; - | ^^^ - | - = note: import resolution is stuck, try simplifying macro imports - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr index fed853a7e1fd8..4909a9cdc7f5c 100644 --- a/tests/ui/self/self_type_keyword.stderr +++ b/tests/ui/self/self_type_keyword.stderr @@ -72,11 +72,11 @@ note: unit struct `foo::Self` exists but is inaccessible LL | struct Self; | ^^^^^^^^^^^^ not accessible -error[E0392]: parameter `'Self` is never used +error[E0392]: lifetime parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12 | LL | struct Bar<'Self>; - | ^^^^^ unused parameter + | ^^^^^ unused lifetime parameter | = help: consider removing `'Self`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/sized/coinductive-2.rs b/tests/ui/sized/coinductive-2.rs index 212274d2e4b6c..43a5a28f710a7 100644 --- a/tests/ui/sized/coinductive-2.rs +++ b/tests/ui/sized/coinductive-2.rs @@ -11,7 +11,7 @@ impl CollectionFactory for Vec<()> { type Collection = Vec; } -trait Collection: Sized { +trait Collection: Sized { //~ WARN trait `Collection` is never used fn push(&mut self, v: T); } diff --git a/tests/ui/sized/coinductive-2.stderr b/tests/ui/sized/coinductive-2.stderr new file mode 100644 index 0000000000000..1390b1f8d7bf1 --- /dev/null +++ b/tests/ui/sized/coinductive-2.stderr @@ -0,0 +1,10 @@ +warning: trait `Collection` is never used + --> $DIR/coinductive-2.rs:14:7 + | +LL | trait Collection: Sized { + | ^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs index a9d678c1e6aff..66a432be35737 100644 --- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs @@ -9,7 +9,7 @@ impl Numberer { //~^ ERROR `async fn` is not permitted in Rust 2015 interval: Duration, //~^ ERROR cannot find type `Duration` in this scope - ) -> Numberer { //~WARN: changes to closure capture in Rust 2021 + ) -> Numberer { Numberer {} } } diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr index 71e9e7602e8e7..60433e1c28467 100644 --- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr +++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr @@ -18,32 +18,7 @@ help: consider importing this struct LL + use std::time::Duration; | -warning: changes to closure capture in Rust 2021 will affect drop order - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:12:19 - | -LL | interval: Duration, - | -------- in Rust 2018, this causes the closure to capture `interval`, but in Rust 2021, it has no effect -LL | -LL | ) -> Numberer { - | _________________-_^ - | | | - | | in Rust 2018, `interval` is dropped here along with the closure, but in Rust 2021 `interval` is not part of the closure -LL | | Numberer {} -LL | | } - | |_____^ - | - = note: for more information, see -note: the lint level is defined here - --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:1:9 - | -LL | #![warn(rust_2021_incompatible_closure_captures)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: add a dummy let to cause `interval` to be fully captured - | -LL | ) -> Numberer { let _ = &interval; - | ++++++++++++++++++ - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors Some errors have detailed explanations: E0412, E0670. For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/span/issue-23827.rs b/tests/ui/span/issue-23827.rs index 6b065bf6cbff2..81037771389dd 100644 --- a/tests/ui/span/issue-23827.rs +++ b/tests/ui/span/issue-23827.rs @@ -2,6 +2,7 @@ #![feature(fn_traits, unboxed_closures)] +#[derive(Copy, Clone)] pub struct Prototype { pub target: u32 } diff --git a/tests/ui/span/issue-23827.stderr b/tests/ui/span/issue-23827.stderr index fe7c7794c9c7a..56f449ab08bf5 100644 --- a/tests/ui/span/issue-23827.stderr +++ b/tests/ui/span/issue-23827.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `Output` - --> $DIR/issue-23827.rs:26:1 + --> $DIR/issue-23827.rs:27:1 | LL | impl FnOnce<(C,)> for Prototype { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation diff --git a/tests/ui/span/issue-39698.rs b/tests/ui/span/issue-39698.rs index 1079bae2c06ae..9799e67e52137 100644 --- a/tests/ui/span/issue-39698.rs +++ b/tests/ui/span/issue-39698.rs @@ -12,5 +12,6 @@ fn main() { //~| ERROR is not bound in all patterns //~| ERROR is not bound in all patterns //~| ERROR is not bound in all patterns + //~| ERROR `a` is possibly-uninitialized } } diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr index 500080832111b..73fcc5c847755 100644 --- a/tests/ui/span/issue-39698.stderr +++ b/tests/ui/span/issue-39698.stderr @@ -38,6 +38,19 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?} | | variable not in all patterns | variable not in all patterns -error: aborting due to 4 previous errors +error[E0381]: used binding `a` is possibly-uninitialized + --> $DIR/issue-39698.rs:10:79 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | - - ^ `a` used here but it is possibly-uninitialized + | | | + | | binding initialized here in some conditions + | binding initialized here in some conditions + | binding declared here but left uninitialized + | + = 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) + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0381, E0408. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/span/issue-43927-non-ADT-derive.rs b/tests/ui/span/issue-43927-non-ADT-derive.rs index 935bfa001bfc6..e50ee36d7de95 100644 --- a/tests/ui/span/issue-43927-non-ADT-derive.rs +++ b/tests/ui/span/issue-43927-non-ADT-derive.rs @@ -1,6 +1,5 @@ #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! -//~^ ERROR cannot determine resolution for the attribute macro `derive` -//~^^ ERROR `derive` attribute cannot be used at crate level +//~^ ERROR `derive` attribute cannot be used at crate level struct DerivedOn; fn main() {} diff --git a/tests/ui/span/issue-43927-non-ADT-derive.stderr b/tests/ui/span/issue-43927-non-ADT-derive.stderr index a22a4d2b40a8e..27ed561f5be8a 100644 --- a/tests/ui/span/issue-43927-non-ADT-derive.stderr +++ b/tests/ui/span/issue-43927-non-ADT-derive.stderr @@ -1,17 +1,9 @@ -error: cannot determine resolution for the attribute macro `derive` - --> $DIR/issue-43927-non-ADT-derive.rs:1:4 - | -LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! - | ^^^^^^ - | - = note: import resolution is stuck, try simplifying macro imports - error: `derive` attribute cannot be used at crate level --> $DIR/issue-43927-non-ADT-derive.rs:1:1 | LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +LL | LL | struct DerivedOn; | --------- the inner attribute doesn't annotate this struct | @@ -21,5 +13,5 @@ LL - #![derive(Debug, PartialEq, Eq)] // should be an outer attribute! LL + #[derive(Debug, PartialEq, Eq)] // should be an outer attribute! | -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.rs b/tests/ui/specialization/assoc-ty-graph-cycle.rs index fc39b553a61ac..bec8cc187b4ab 100644 --- a/tests/ui/specialization/assoc-ty-graph-cycle.rs +++ b/tests/ui/specialization/assoc-ty-graph-cycle.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Make sure we don't crash with a cycle error during coherence. diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index 913d51875cd70..187049e623cc7 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -16,5 +16,33 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | impl const A for T { | ^^^^^^^ -error: aborting due to 3 previous errors +error[E0015]: cannot call non-const fn `<() as A>::a` in constants + --> $DIR/const_trait_impl.rs:52:23 + | +LL | const _: () = assert!(<()>::a() == 42); + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `::a` in constants + --> $DIR/const_trait_impl.rs:53:23 + | +LL | const _: () = assert!(::a() == 3); + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `::a` in constants + --> $DIR/const_trait_impl.rs:54:23 + | +LL | const _: () = assert!(::a() == 2); + | ^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/specialization/defaultimpl/out-of-order.rs b/tests/ui/specialization/defaultimpl/out-of-order.rs index 13258ac8c9fe6..94b3905178fa8 100644 --- a/tests/ui/specialization/defaultimpl/out-of-order.rs +++ b/tests/ui/specialization/defaultimpl/out-of-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that you can list the more specific impl before the more general one. diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.rs b/tests/ui/specialization/defaultimpl/overlap-projection.rs index 0add4d5516c7b..46f54c466a831 100644 --- a/tests/ui/specialization/defaultimpl/overlap-projection.rs +++ b/tests/ui/specialization/defaultimpl/overlap-projection.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is diff --git a/tests/ui/specialization/min_specialization/issue-79224.stderr b/tests/ui/specialization/min_specialization/issue-79224.stderr index 37ced4cf267fe..da19ed44ce6f1 100644 --- a/tests/ui/specialization/min_specialization/issue-79224.stderr +++ b/tests/ui/specialization/min_specialization/issue-79224.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/issue-79224.rs:18:29 | LL | impl Display for Cow<'_, B> { - | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | ^^^^^^^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound @@ -14,7 +14,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/issue-79224.rs:20:5 | LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound @@ -26,7 +26,7 @@ error[E0277]: the trait bound `B: Clone` is not satisfied --> $DIR/issue-79224.rs:20:13 | LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - | ^^^^ the trait `Clone` is not implemented for `B` + | ^^^^ the trait `Clone` is not implemented for `B`, which is required by `B: ToOwned` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index e9498a003179b..78d77a78e0eef 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -7,6 +7,13 @@ LL | impl Overlap for u32 { LL | impl Overlap for ::Id { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/specialization-default-items-drop-coherence.rs:18:23 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `::Id` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0282. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index 37903c210714e..87eb5d90def70 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -11,25 +11,25 @@ #![allow(incomplete_features)] trait Default { - type Id; + type Id; } impl Default for T { - default type Id = T; + default type Id = T; //[next]~ ERROR type annotations needed } trait Overlap { - type Assoc; + type Assoc; } impl Overlap for u32 { - type Assoc = usize; + type Assoc = usize; } impl Overlap for ::Id { - //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` - //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` - type Assoc = Box; + //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` + //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` + type Assoc = Box; } fn main() {} diff --git a/tests/ui/specialization/specialization-out-of-order.rs b/tests/ui/specialization/specialization-out-of-order.rs index cb7563e2760c2..66e6c3c9eab31 100644 --- a/tests/ui/specialization/specialization-out-of-order.rs +++ b/tests/ui/specialization/specialization-out-of-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that you can list the more specific impl before the more general one. diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index b07efb2a5c1cd..cd21eab24c0b7 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is diff --git a/tests/ui/specialization/specialization-supertraits.rs b/tests/ui/specialization/specialization-supertraits.rs index fb85d8019218a..d0c9dbb1d4014 100644 --- a/tests/ui/specialization/specialization-supertraits.rs +++ b/tests/ui/specialization/specialization-supertraits.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(specialization)] //~ WARN the feature `specialization` is incomplete diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs index 6d6d793c62b76..4089ec7288526 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs @@ -14,3 +14,4 @@ pub const fn foobar() -> u32 { } const VAR: u32 = foobar(); +//~^ ERROR: `foobar` is not yet stable as a const fn diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr index 232de41c769e2..918d6ebf99226 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr @@ -4,5 +4,13 @@ error: feature `const_bar` implying `const_foobar` does not exist LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: `foobar` is not yet stable as a const fn + --> $DIR/const-stability-attribute-implies-missing.rs:16:18 + | +LL | const VAR: u32 = foobar(); + | ^^^^^^^^ + | + = help: add `#![feature(const_foobar)]` to the crate attributes to enable + +error: aborting due to 2 previous errors diff --git a/tests/ui/static/static-drop-scope.rs b/tests/ui/static/static-drop-scope.rs index 34afa9873a388..74b224c9be085 100644 --- a/tests/ui/static/static-drop-scope.rs +++ b/tests/ui/static/static-drop-scope.rs @@ -6,11 +6,9 @@ impl Drop for WithDtor { static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR destructor of -//~| ERROR temporary value dropped while borrowed const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR destructor of -//~| ERROR temporary value dropped while borrowed static EARLY_DROP_S: i32 = (WithDtor, 0).1; //~^ ERROR destructor of diff --git a/tests/ui/static/static-drop-scope.stderr b/tests/ui/static/static-drop-scope.stderr index cedcb7367949f..2c55161628fb8 100644 --- a/tests/ui/static/static-drop-scope.stderr +++ b/tests/ui/static/static-drop-scope.stderr @@ -6,36 +6,16 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | | | the destructor for this type cannot be evaluated in statics -error[E0716]: temporary value dropped while borrowed - --> $DIR/static-drop-scope.rs:7:60 - | -LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); - | ------^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a static requires that borrow lasts for `'static` - error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:11:59 + --> $DIR/static-drop-scope.rs:10:59 | LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | ^^^^^^^^- value is dropped here | | | the destructor for this type cannot be evaluated in constants -error[E0716]: temporary value dropped while borrowed - --> $DIR/static-drop-scope.rs:11:59 - | -LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); - | ------^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a constant requires that borrow lasts for `'static` - error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:15:28 + --> $DIR/static-drop-scope.rs:13:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -43,7 +23,7 @@ LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in statics error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:18:27 + --> $DIR/static-drop-scope.rs:16:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -51,7 +31,7 @@ LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:21:24 + --> $DIR/static-drop-scope.rs:19:24 | LL | const fn const_drop(_: T) {} | ^ - value is dropped here @@ -59,7 +39,7 @@ LL | const fn const_drop(_: T) {} | the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:25:5 + --> $DIR/static-drop-scope.rs:23:5 | LL | (x, ()).1 | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -68,7 +48,7 @@ LL | } | - value is dropped here error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:29:34 + --> $DIR/static-drop-scope.rs:27:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | ^^^^^^^^^^^^^^^^^^^ - value is dropped here @@ -76,14 +56,13 @@ LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:34:43 + --> $DIR/static-drop-scope.rs:32:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; | ^^^^^^^^^^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constants -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/statics/static-impl.rs b/tests/ui/statics/static-impl.rs index e7bdb38ee62c9..9e2db7e0caf50 100644 --- a/tests/ui/statics/static-impl.rs +++ b/tests/ui/statics/static-impl.rs @@ -35,7 +35,7 @@ impl uint_utils for usize { trait vec_utils { fn length_(&self, ) -> usize; - fn iter_(&self, f: F) where F: FnMut(&T); + fn iter_(&self, f: F) where F: FnMut(&T); //~ WARN method `iter_` is never used fn map_(&self, f: F) -> Vec where F: FnMut(&T) -> U; } diff --git a/tests/ui/statics/static-impl.stderr b/tests/ui/statics/static-impl.stderr new file mode 100644 index 0000000000000..83c3ffbefe1f2 --- /dev/null +++ b/tests/ui/statics/static-impl.stderr @@ -0,0 +1,13 @@ +warning: method `iter_` is never used + --> $DIR/static-impl.rs:38:8 + | +LL | trait vec_utils { + | --------- method in this trait +LL | fn length_(&self, ) -> usize; +LL | fn iter_(&self, f: F) where F: FnMut(&T); + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index 8b9ec30db63f4..2c21c25d7c77e 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -5,8 +5,8 @@ ast-stats-1 GenericArgs 40 ( 0.6%) 1 40 ast-stats-1 - AngleBracketed 40 ( 0.6%) 1 ast-stats-1 Crate 40 ( 0.6%) 1 40 ast-stats-1 ExprField 48 ( 0.7%) 1 48 -ast-stats-1 WherePredicate 56 ( 0.9%) 1 56 -ast-stats-1 - BoundPredicate 56 ( 0.9%) 1 +ast-stats-1 WherePredicate 56 ( 0.8%) 1 56 +ast-stats-1 - BoundPredicate 56 ( 0.8%) 1 ast-stats-1 Attribute 64 ( 1.0%) 2 32 ast-stats-1 - Normal 32 ( 0.5%) 1 ast-stats-1 - DocComment 32 ( 0.5%) 1 @@ -22,38 +22,38 @@ ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.5%) 3 ast-stats-1 Param 160 ( 2.4%) 4 40 ast-stats-1 Block 192 ( 2.9%) 6 32 -ast-stats-1 Variant 208 ( 3.2%) 2 104 -ast-stats-1 GenericBound 288 ( 4.4%) 4 72 -ast-stats-1 - Trait 288 ( 4.4%) 4 -ast-stats-1 AssocItem 352 ( 5.4%) 4 88 +ast-stats-1 Variant 208 ( 3.1%) 2 104 +ast-stats-1 GenericBound 352 ( 5.3%) 4 88 +ast-stats-1 - Trait 352 ( 5.3%) 4 +ast-stats-1 AssocItem 352 ( 5.3%) 4 88 ast-stats-1 - Type 176 ( 2.7%) 2 ast-stats-1 - Fn 176 ( 2.7%) 2 ast-stats-1 GenericParam 480 ( 7.3%) 5 96 -ast-stats-1 Pat 504 ( 7.7%) 7 72 +ast-stats-1 Pat 504 ( 7.6%) 7 72 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Wild 72 ( 1.1%) 1 -ast-stats-1 - Ident 360 ( 5.5%) 5 -ast-stats-1 Expr 576 ( 8.8%) 8 72 +ast-stats-1 - Ident 360 ( 5.4%) 5 +ast-stats-1 Expr 576 ( 8.7%) 8 72 ast-stats-1 - Path 72 ( 1.1%) 1 ast-stats-1 - Match 72 ( 1.1%) 1 ast-stats-1 - Struct 72 ( 1.1%) 1 ast-stats-1 - Lit 144 ( 2.2%) 2 ast-stats-1 - Block 216 ( 3.3%) 3 -ast-stats-1 PathSegment 720 (11.0%) 30 24 -ast-stats-1 Ty 896 (13.7%) 14 64 +ast-stats-1 PathSegment 720 (10.9%) 30 24 +ast-stats-1 Ty 896 (13.5%) 14 64 ast-stats-1 - Ptr 64 ( 1.0%) 1 ast-stats-1 - Ref 64 ( 1.0%) 1 -ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2 -ast-stats-1 - Path 640 ( 9.8%) 10 -ast-stats-1 Item 1_224 (18.7%) 9 136 +ast-stats-1 - ImplicitSelf 128 ( 1.9%) 2 +ast-stats-1 - Path 640 ( 9.7%) 10 +ast-stats-1 Item 1_224 (18.5%) 9 136 ast-stats-1 - Trait 136 ( 2.1%) 1 ast-stats-1 - Enum 136 ( 2.1%) 1 ast-stats-1 - ForeignMod 136 ( 2.1%) 1 ast-stats-1 - Impl 136 ( 2.1%) 1 -ast-stats-1 - Fn 272 ( 4.2%) 2 +ast-stats-1 - Fn 272 ( 4.1%) 2 ast-stats-1 - Use 408 ( 6.2%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 6_552 +ast-stats-1 Total 6_616 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size @@ -81,39 +81,39 @@ ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Param 160 ( 2.2%) 4 40 ast-stats-2 Block 192 ( 2.7%) 6 32 ast-stats-2 Variant 208 ( 2.9%) 2 104 -ast-stats-2 GenericBound 288 ( 4.0%) 4 72 -ast-stats-2 - Trait 288 ( 4.0%) 4 +ast-stats-2 GenericBound 352 ( 4.9%) 4 88 +ast-stats-2 - Trait 352 ( 4.9%) 4 ast-stats-2 AssocItem 352 ( 4.9%) 4 88 -ast-stats-2 - Type 176 ( 2.5%) 2 -ast-stats-2 - Fn 176 ( 2.5%) 2 +ast-stats-2 - Type 176 ( 2.4%) 2 +ast-stats-2 - Fn 176 ( 2.4%) 2 ast-stats-2 GenericParam 480 ( 6.7%) 5 96 ast-stats-2 Pat 504 ( 7.0%) 7 72 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - Wild 72 ( 1.0%) 1 ast-stats-2 - Ident 360 ( 5.0%) 5 -ast-stats-2 Expr 648 ( 9.1%) 9 72 +ast-stats-2 Expr 648 ( 9.0%) 9 72 ast-stats-2 - Path 72 ( 1.0%) 1 ast-stats-2 - Match 72 ( 1.0%) 1 ast-stats-2 - Struct 72 ( 1.0%) 1 ast-stats-2 - InlineAsm 72 ( 1.0%) 1 ast-stats-2 - Lit 144 ( 2.0%) 2 ast-stats-2 - Block 216 ( 3.0%) 3 -ast-stats-2 PathSegment 792 (11.1%) 33 24 -ast-stats-2 Ty 896 (12.5%) 14 64 +ast-stats-2 PathSegment 792 (11.0%) 33 24 +ast-stats-2 Ty 896 (12.4%) 14 64 ast-stats-2 - Ptr 64 ( 0.9%) 1 ast-stats-2 - Ref 64 ( 0.9%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2 ast-stats-2 - Path 640 ( 8.9%) 10 -ast-stats-2 Item 1_496 (20.9%) 11 136 +ast-stats-2 Item 1_496 (20.7%) 11 136 ast-stats-2 - Trait 136 ( 1.9%) 1 ast-stats-2 - Enum 136 ( 1.9%) 1 ast-stats-2 - ExternCrate 136 ( 1.9%) 1 ast-stats-2 - ForeignMod 136 ( 1.9%) 1 ast-stats-2 - Impl 136 ( 1.9%) 1 ast-stats-2 - Fn 272 ( 3.8%) 2 -ast-stats-2 - Use 544 ( 7.6%) 4 +ast-stats-2 - Use 544 ( 7.5%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 7_152 +ast-stats-2 Total 7_216 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size diff --git a/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs index 0f535523dcc06..4a8289cb24284 100644 --- a/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs +++ b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs @@ -32,7 +32,7 @@ fn assert_inorder(a: &[T]) { } } -trait Foo { fn foo(&self) -> usize; } +trait Foo { fn foo(&self) -> usize; } //~ WARN method `foo` is never used impl Foo for T { fn foo(&self) -> usize { mem::size_of::() diff --git a/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr b/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr new file mode 100644 index 0000000000000..670fa5bb9224b --- /dev/null +++ b/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/raw-fat-ptr.rs:35:16 + | +LL | trait Foo { fn foo(&self) -> usize; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr index e8bbb8058faf3..84806cbea0dea 100644 --- a/tests/ui/str/str-idx.stderr +++ b/tests/ui/str/str-idx.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` LL | let _: u8 = s[4]; | ^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `{integer}` + = help: the trait `SliceIndex` is not implemented for `{integer}`, which is required by `str: Index<_>` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: = help: the trait `SliceIndex<[_]>` is implemented for `usize` @@ -49,7 +49,7 @@ error[E0277]: the type `str` cannot be indexed by `char` LL | let _: u8 = s['c']; | ^^^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `char` + = help: the trait `SliceIndex` is not implemented for `char`, which is required by `str: Index<_>` = note: required for `str` to implement `Index` error: aborting due to 4 previous errors diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index e6835bb54fb3d..679f783126ff4 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -2,14 +2,14 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t --> $DIR/str-mut-idx.rs:4:15 | LL | s[1..2] = bot(); - | ^^^ doesn't have a size known at compile-time + | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` -note: required by a bound in `bot` +note: required by an implicit `Sized` bound in `bot` --> $DIR/str-mut-idx.rs:1:8 | LL | fn bot() -> T { loop {} } - | ^ required by this bound in `bot` + | ^ required by the implicit `Sized` requirement on this type parameter in `bot` help: consider relaxing the implicit `Sized` restriction | LL | fn bot() -> T { loop {} } @@ -30,7 +30,7 @@ error[E0277]: the type `str` cannot be indexed by `usize` LL | s[1usize] = bot(); | ^^^^^^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `usize`, which is required by `str: Index<_>` = help: the trait `SliceIndex<[_]>` is implemented for `usize` = help: for that trait implementation, expected `[_]`, found `str` = note: required for `str` to implement `Index` @@ -73,7 +73,7 @@ error[E0277]: the type `str` cannot be indexed by `char` LL | s['c']; | ^^^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `char` + = help: the trait `SliceIndex` is not implemented for `char`, which is required by `str: Index<_>` = note: required for `str` to implement `Index` error: aborting due to 6 previous errors diff --git a/tests/ui/structs-enums/enum-null-pointer-opt.rs b/tests/ui/structs-enums/enum-null-pointer-opt.rs index 356f8a6dd36f6..21564eeec29e3 100644 --- a/tests/ui/structs-enums/enum-null-pointer-opt.rs +++ b/tests/ui/structs-enums/enum-null-pointer-opt.rs @@ -7,7 +7,7 @@ use std::ptr::NonNull; use std::rc::Rc; use std::sync::Arc; -trait Trait { fn dummy(&self) { } } +trait Trait { fn dummy(&self) { } } //~ WARN method `dummy` is never used trait Mirror { type Image; } impl Mirror for T { type Image = T; } struct ParamTypeStruct(#[allow(dead_code)] T); diff --git a/tests/ui/structs-enums/enum-null-pointer-opt.stderr b/tests/ui/structs-enums/enum-null-pointer-opt.stderr new file mode 100644 index 0000000000000..64e93ffaffd60 --- /dev/null +++ b/tests/ui/structs-enums/enum-null-pointer-opt.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/enum-null-pointer-opt.rs:10:18 + | +LL | trait Trait { fn dummy(&self) { } } + | ----- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs index b7e49873da81a..20231dc83db91 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs @@ -1,7 +1,10 @@ +// ignore-macos: cycle error does not appear on apple + use std::sync::Mutex; enum Foo { X(Mutex>) } //~^ ERROR recursive type `Foo` has infinite size +//~| ERROR cycle detected impl Foo { fn bar(self) {} } diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr index e34eb04bc04fa..22f8519d0ef84 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-6.rs:3:1 + --> $DIR/issue-17431-6.rs:5:1 | LL | enum Foo { X(Mutex>) } | ^^^^^^^^ --- recursive without indirection @@ -9,6 +9,17 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum Foo { X(Mutex>>) } | ++++ + -error: aborting due to 1 previous error +error[E0391]: cycle detected when computing when `Foo` needs drop + --> $DIR/issue-17431-6.rs:5:1 + | +LL | enum Foo { X(Mutex>) } + | ^^^^^^^^ + | + = note: ...which immediately requires computing when `Foo` needs drop again + = note: cycle used when computing whether `Foo` needs drop + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr index d136f5ff6543f..6da6f8e23b4f4 100644 --- a/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr +++ b/tests/ui/suggestions/adt-param-with-implicit-sized-bound.stderr @@ -6,11 +6,11 @@ LL | struct Struct5{ LL | _t: X, | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `X` +note: required by an implicit `Sized` bound in `X` --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 | LL | struct X(T); - | ^ required by this bound in `X` + | ^ required by the implicit `Sized` requirement on this type parameter in `X` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/adt-param-with-implicit-sized-bound.rs:18:10 | @@ -30,11 +30,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func1() -> Struct1; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct1` +note: required by an implicit `Sized` bound in `Struct1` --> $DIR/adt-param-with-implicit-sized-bound.rs:8:16 | LL | struct Struct1{ - | ^ required by this bound in `Struct1` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct1` help: consider further restricting `Self` | LL | fn func1() -> Struct1 where Self: Sized; @@ -50,11 +50,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func2<'a>() -> Struct2<'a, Self>; | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct2` +note: required by an implicit `Sized` bound in `Struct2` --> $DIR/adt-param-with-implicit-sized-bound.rs:11:20 | LL | struct Struct2<'a, T>{ - | ^ required by this bound in `Struct2` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct2` help: consider further restricting `Self` | LL | fn func2<'a>() -> Struct2<'a, Self> where Self: Sized; @@ -70,11 +70,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func3() -> Struct3; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct3` +note: required by an implicit `Sized` bound in `Struct3` --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 | LL | struct Struct3{ - | ^ required by this bound in `Struct3` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct3` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/adt-param-with-implicit-sized-bound.rs:14:16 | @@ -93,11 +93,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | fn func4() -> Struct4; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Struct4` +note: required by an implicit `Sized` bound in `Struct4` --> $DIR/adt-param-with-implicit-sized-bound.rs:20:16 | LL | struct Struct4{ - | ^ required by this bound in `Struct4` + | ^ required by the implicit `Sized` requirement on this type parameter in `Struct4` help: consider further restricting `Self` | LL | fn func4() -> Struct4 where Self: Sized; diff --git a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 3065f83ea3d1b..dc4ec5d3ee28b 100644 --- a/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -18,25 +18,21 @@ help: use parentheses to call this function LL | bar(foo()); | ++ -error[E0277]: `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future +error[E0277]: `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9 | LL | bar(async_closure); - | --- ^^^^^^^^^^^^^ `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future + | --- ^^^^^^^^^^^^^ `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for closure `{closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` - = note: {closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited + = help: the trait `Future` is not implemented for `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` + = note: {coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 | LL | fn bar(f: impl Future) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `bar` -help: use parentheses to call this closure - | -LL | bar(async_closure()); - | ++ error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/bound-suggestions.fixed b/tests/ui/suggestions/bound-suggestions.fixed index 17a019c69849f..ef61fb9ad325f 100644 --- a/tests/ui/suggestions/bound-suggestions.fixed +++ b/tests/ui/suggestions/bound-suggestions.fixed @@ -40,26 +40,31 @@ fn test_many_bounds_where(x: X) where X: Sized + std::fmt::Debug, X: Sized { //~^ ERROR doesn't implement } +#[allow(dead_code)] trait Foo: Sized { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bar: std::fmt::Display + Sized { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Baz: Sized where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Qux: Sized where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bat: std::fmt::Display + Sized { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time diff --git a/tests/ui/suggestions/bound-suggestions.rs b/tests/ui/suggestions/bound-suggestions.rs index 86f708d42f5e7..6d17fae6a088e 100644 --- a/tests/ui/suggestions/bound-suggestions.rs +++ b/tests/ui/suggestions/bound-suggestions.rs @@ -40,26 +40,31 @@ fn test_many_bounds_where(x: X) where X: Sized, X: Sized { //~^ ERROR doesn't implement } +#[allow(dead_code)] trait Foo { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bar: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Baz where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Qux where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bat: std::fmt::Display { const SIZE: usize = core::mem::size_of::(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr index cd27947f02fad..4965e7439f849 100644 --- a/tests/ui/suggestions/bound-suggestions.stderr +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -71,12 +71,12 @@ LL | fn test_many_bounds_where(x: X) where X: Sized + std::fmt::Debug, X: Siz | +++++++++++++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:44:46 + --> $DIR/bound-suggestions.rs:45:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -84,12 +84,12 @@ LL | trait Foo: Sized { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:49:46 + --> $DIR/bound-suggestions.rs:51:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -97,12 +97,12 @@ LL | trait Bar: std::fmt::Display + Sized { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:54:46 + --> $DIR/bound-suggestions.rs:57:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -110,12 +110,12 @@ LL | trait Baz: Sized where Self: std::fmt::Display { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:59:46 + --> $DIR/bound-suggestions.rs:63:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | @@ -123,12 +123,12 @@ LL | trait Qux: Sized where Self: std::fmt::Display { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:64:46 + --> $DIR/bound-suggestions.rs:69:46 | LL | const SIZE: usize = core::mem::size_of::(); | ^^^^ doesn't have a size known at compile-time | -note: required by a bound in `std::mem::size_of` +note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider further restricting `Self` | diff --git a/tests/ui/suggestions/constrain-trait.fixed b/tests/ui/suggestions/constrain-trait.fixed index f292f27f0f342..f7360efe4c527 100644 --- a/tests/ui/suggestions/constrain-trait.fixed +++ b/tests/ui/suggestions/constrain-trait.fixed @@ -1,5 +1,6 @@ // run-rustfix // check-only +#![allow(dead_code)] #[derive(Debug)] struct Demo { diff --git a/tests/ui/suggestions/constrain-trait.rs b/tests/ui/suggestions/constrain-trait.rs index 99ccf7a7f3bdf..799100669b654 100644 --- a/tests/ui/suggestions/constrain-trait.rs +++ b/tests/ui/suggestions/constrain-trait.rs @@ -1,5 +1,6 @@ // run-rustfix // check-only +#![allow(dead_code)] #[derive(Debug)] struct Demo { diff --git a/tests/ui/suggestions/constrain-trait.stderr b/tests/ui/suggestions/constrain-trait.stderr index a26f86917bc1f..b28972ecde041 100644 --- a/tests/ui/suggestions/constrain-trait.stderr +++ b/tests/ui/suggestions/constrain-trait.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `get_a` found for reference `&Self` in the current scope - --> $DIR/constrain-trait.rs:15:31 + --> $DIR/constrain-trait.rs:16:31 | LL | println!("{:?}", self.get_a()); | ^^^^^ method not found in `&Self` @@ -11,7 +11,7 @@ LL | trait UseString: std::fmt::Debug + GetString { | +++++++++++ error[E0599]: no method named `get_a` found for reference `&Self` in the current scope - --> $DIR/constrain-trait.rs:21:31 + --> $DIR/constrain-trait.rs:22:31 | LL | println!("{:?}", self.get_a()); | ^^^^^ method not found in `&Self` diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index 680890e880ca6..6fae6e1316df0 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied --> $DIR/derive-clone-for-eq.rs:4:17 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | ^^ the trait `Clone` is not implemented for `T`, which is required by `Struct: PartialEq` | note: required for `Struct` to implement `PartialEq` --> $DIR/derive-clone-for-eq.rs:7:19 diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr index bffcb1af487e9..5da85a9d0619c 100644 --- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -6,7 +6,7 @@ LL | #[derive(Debug)] LL | struct Outer(Inner); | ^^^^^^^^ `a::Inner` cannot be formatted using `{:?}` | - = help: the trait `Debug` is not implemented for `a::Inner` + = help: the trait `Debug` is not implemented for `a::Inner`, which is required by `&a::Inner: Debug` = note: add `#[derive(Debug)]` to `a::Inner` or manually `impl Debug for a::Inner` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `a::Inner` with `#[derive(Debug)]` @@ -25,7 +25,7 @@ error[E0277]: the trait bound `T: c::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `c::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `c::Trait` is not implemented for `T`, which is required by `&c::Inner: Debug` | note: required for `c::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:34:28 @@ -49,7 +49,7 @@ error[E0277]: the trait bound `T: d::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `d::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `d::Trait` is not implemented for `T`, which is required by `&d::Inner: Debug` | note: required for `d::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:49:13 @@ -71,7 +71,7 @@ error[E0277]: the trait bound `T: e::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `e::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `e::Trait` is not implemented for `T`, which is required by `&e::Inner: Debug` | note: required for `e::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:64:13 @@ -93,7 +93,7 @@ error[E0277]: the trait bound `T: f::Trait` is not satisfied LL | #[derive(Debug)] | ----- in this derive macro expansion LL | struct Outer(Inner); - | ^^^^^^^^ the trait `f::Trait` is not implemented for `T` + | ^^^^^^^^ the trait `f::Trait` is not implemented for `T`, which is required by `&f::Inner: Debug` | note: required for `f::Inner` to implement `Debug` --> $DIR/derive-macro-missing-bounds.rs:79:20 diff --git a/tests/ui/suggestions/derive-trait-for-method-call.rs b/tests/ui/suggestions/derive-trait-for-method-call.rs index 25043da52aa01..b5ce0078c9bc8 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.rs +++ b/tests/ui/suggestions/derive-trait-for-method-call.rs @@ -19,7 +19,7 @@ struct CloneStruct { struct Foo (X, Y); impl Foo { fn test(&self) -> (X, Y) { - (self.0, self.1) + (self.0.clone(), self.1.clone()) } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs index 255cab06070c6..c24672816acdb 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -64,6 +64,8 @@ mod bay { fn use_it<'a>(val: Box + 'a>) -> &'a () { val.use_self() + //~^ ERROR: cannot return value referencing function parameter `val` + //~| ERROR: borrowed data escapes outside of function } } @@ -86,6 +88,7 @@ mod bax { fn use_it<'a>(val: Box + 'a>) -> &'a () { val.use_self() + //~^ ERROR: cannot return value referencing function parameter `val` } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index a7e03f491b9e6..505765d2b41f6 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -17,7 +17,7 @@ LL | val.use_self() | `val` is borrowed here error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:112:9 | LL | val.use_self() | ---^^^^^^^^^^^ @@ -25,6 +25,50 @@ LL | val.use_self() | returns a value referencing data owned by the current function | `val` is borrowed here -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30 + | +LL | impl MyTrait for Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box + '_> { + | ++++ + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:90:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0515`. +Some errors have detailed explanations: E0515, E0521. +For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index ae3cd315c83ec..574aea9cc6e63 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -36,6 +36,7 @@ mod bar { fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { val.use_self() + //~^ ERROR: borrowed data escapes } } @@ -53,6 +54,7 @@ mod baz { fn use_it<'a>(val: &'a Box) -> &'a () { val.use_self() + //~^ ERROR: borrowed data escapes } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index da72c8ebf19b6..6effaf61099ec 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -24,7 +24,7 @@ LL | impl MyTrait for dyn ObjectTrait + '_ { | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:70:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:72:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | -- --- `val` is a reference that is only valid in the function body @@ -37,7 +37,7 @@ LL | val.use_self() | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:65:14 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:14 | LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement @@ -49,7 +49,7 @@ LL | impl dyn ObjectTrait + '_ { | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:90:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:92:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | -- --- `val` is a reference that is only valid in the function body @@ -62,7 +62,7 @@ LL | val.use_self() | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:26 | LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement @@ -75,7 +75,7 @@ LL | impl MyTrait for dyn ObjectTrait + '_ {} | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:110:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:112:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | -- --- `val` is a reference that is only valid in the function body @@ -88,7 +88,7 @@ LL | MyTrait::use_self(val) | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:26 | LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement @@ -100,6 +100,56 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for dyn ObjectTrait + '_ {} | ++++ -error: aborting due to 4 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:38:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:26 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:56:9 + | +LL | fn use_it<'a>(val: &'a Box) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:50:30 + | +LL | impl MyTrait for Box { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box { + | ++++ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.rs b/tests/ui/suggestions/impl-trait-missing-lifetime.rs index 6f7c912d707cf..b03d61614936f 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.rs +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.rs @@ -8,6 +8,7 @@ fn f(_: impl Iterator) {} // But that lifetime does not participate in resolution. fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } //~^ ERROR missing lifetime specifier +//~| ERROR lifetime may not live long enough // This is understood as `fn foo<'_1>(_: impl Iterator) {}`. async fn h(_: impl Iterator) {} diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr index c1dbaae0649a0..70998b67c04bf 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -20,7 +20,7 @@ LL + fn g(mut x: impl Iterator) -> Option<()> { x.next() } | error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime.rs:16:60 + --> $DIR/impl-trait-missing-lifetime.rs:17:60 | LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ^^ expected named lifetime parameter @@ -41,13 +41,19 @@ LL + async fn i(mut x: impl Iterator) -> Option<()> { x.next() } | error: lifetime may not live long enough - --> $DIR/impl-trait-missing-lifetime.rs:16:69 + --> $DIR/impl-trait-missing-lifetime.rs:17:69 | LL | async fn i(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } | ----------------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` | | | return type `impl Future>` contains a lifetime `'1` -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime.rs:9:63 + | +LL | fn g(mut x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ----- has type `x` ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/into-str.stderr b/tests/ui/suggestions/into-str.stderr index d6efc8173cb7c..d10a294c7d2dd 100644 --- a/tests/ui/suggestions/into-str.stderr +++ b/tests/ui/suggestions/into-str.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&str: From` is not satisfied --> $DIR/into-str.rs:4:9 | LL | foo(String::new()); - | --- ^^^^^^^^^^^^^ the trait `From` is not implemented for `&str` + | --- ^^^^^^^^^^^^^ the trait `From` is not implemented for `&str`, which is required by `String: Into<&str>` | | | required by a bound introduced by this call | diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr index 2bd745c645a1c..018250c8c1b60 100644 --- a/tests/ui/suggestions/invalid-bin-op.stderr +++ b/tests/ui/suggestions/invalid-bin-op.stderr @@ -16,6 +16,10 @@ help: consider annotating `S` with `#[derive(PartialEq)]` LL + #[derive(PartialEq)] LL | struct S(T); | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub fn foo(s: S, t: S) where S: PartialEq { + | +++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-102892.rs b/tests/ui/suggestions/issue-102892.rs index c1a791d8d857a..ac7f16f8c65b1 100644 --- a/tests/ui/suggestions/issue-102892.rs +++ b/tests/ui/suggestions/issue-102892.rs @@ -9,6 +9,7 @@ struct B; fn process_without_annot(arc: &Arc<(A, B)>) { let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + //~^ ERROR: cannot move out of an `Arc` } fn process_with_annot(arc: &Arc<(A, B)>) { diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr index e64a89ffe3308..38f19b3321887 100644 --- a/tests/ui/suggestions/issue-102892.stderr +++ b/tests/ui/suggestions/issue-102892.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-102892.rs:15:26 + --> $DIR/issue-102892.rs:16:26 | LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too | ------ ^^^^^^ expected `(A, B)`, found `&(A, B)` @@ -19,7 +19,7 @@ LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too | + error[E0308]: mismatched types - --> $DIR/issue-102892.rs:20:32 + --> $DIR/issue-102892.rs:21:32 | LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | ^^^^^^^^^^^^^^ expected `(A, B)`, found `&mut (A, B)` @@ -37,7 +37,7 @@ LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggest | ++++ error[E0308]: mismatched types - --> $DIR/issue-102892.rs:20:48 + --> $DIR/issue-102892.rs:21:48 | LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | ^^^^^^^^^^ expected `A`, found `&A` @@ -52,6 +52,23 @@ help: alternatively, consider changing the type annotation LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | + -error: aborting due to 3 previous errors +error[E0507]: cannot move out of an `Arc` + --> $DIR/issue-102892.rs:11:18 + | +LL | let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + | - - ^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the dereference here + | +LL - let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +LL + let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed! + | + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0507. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-104327.stderr b/tests/ui/suggestions/issue-104327.stderr index 325b6b6eb4b63..1bad82d471e04 100644 --- a/tests/ui/suggestions/issue-104327.stderr +++ b/tests/ui/suggestions/issue-104327.stderr @@ -5,7 +5,7 @@ LL | fn f() {} | --------- `Foo::f` defined here ... LL | Foo::f(); - | ^^^^^^ cannot call associated function of trait + | ^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/suggestions/issue-104328.stderr b/tests/ui/suggestions/issue-104328.stderr index a592621834127..3c5e6f16289e0 100644 --- a/tests/ui/suggestions/issue-104328.stderr +++ b/tests/ui/suggestions/issue-104328.stderr @@ -5,7 +5,7 @@ LL | fn f() {} | --------- `Foo::f` defined here ... LL | Foo::f(); - | ^^^^^^ cannot call associated function of trait + | ^^^^^^^^ cannot call associated function of trait | help: use the fully-qualified path to the only available implementation | diff --git a/tests/ui/suggestions/issue-109195.rs b/tests/ui/suggestions/issue-109195.rs new file mode 100644 index 0000000000000..cc499b0d77618 --- /dev/null +++ b/tests/ui/suggestions/issue-109195.rs @@ -0,0 +1,20 @@ +fn main() { + String::from::utf8; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf8` + String::from::utf8(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf8` + String::from::utf16(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf16` + String::from::method_that_doesnt_exist(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` + str::from::utf8(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` + str::from::utf8_mut(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` +} diff --git a/tests/ui/suggestions/issue-109195.stderr b/tests/ui/suggestions/issue-109195.stderr new file mode 100644 index 0000000000000..10cf9cfd28ca7 --- /dev/null +++ b/tests/ui/suggestions/issue-109195.stderr @@ -0,0 +1,69 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:2:5 + | +LL | String::from::utf8; + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf8` + | +LL | String::from_utf8; + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:5:5 + | +LL | String::from::utf8(); + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf8` + | +LL | String::from_utf8(); + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:8:5 + | +LL | String::from::utf16(); + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf16` + | +LL | String::from_utf16(); + | ~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:11:5 + | +LL | String::from::method_that_doesnt_exist(); + | ^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path + | +LL | ::from::method_that_doesnt_exist(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:14:5 + | +LL | str::from::utf8(); + | ^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path + | +LL | ::from::utf8(); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:17:5 + | +LL | str::from::utf8_mut(); + | ^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path + | +LL | ::from::utf8_mut(); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/suggestions/issue-61963.rs b/tests/ui/suggestions/issue-61963.rs index a27c38452539c..d31ed01b1916b 100644 --- a/tests/ui/suggestions/issue-61963.rs +++ b/tests/ui/suggestions/issue-61963.rs @@ -18,20 +18,10 @@ pub struct Qux(T); pub struct Foo { //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition qux: Qux>, bar: Box, //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition } fn main() {} diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr index adb476ade9a2d..084b0cbeef292 100644 --- a/tests/ui/suggestions/issue-61963.stderr +++ b/tests/ui/suggestions/issue-61963.stderr @@ -1,5 +1,5 @@ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 + --> $DIR/issue-61963.rs:22:14 | LL | bar: Box, | ^^^ @@ -29,75 +29,5 @@ help: if this is an object-safe trait, use `dyn` LL | dyn pub struct Foo { | +++ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 - | -LL | bar: Box, - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | bar: Box, - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 - | -LL | bar: Box, - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | bar: Box, - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: if this is an object-safe trait, use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: aborting due to 7 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index b9b72e0e63f14..0f6bfbeec45f3 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied --> $DIR/issue-71394-no-from-impl.rs:8:25 | LL | let _: &[i8] = data.into(); - | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]` + | ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`, which is required by `&[u8]: Into<_>` | = help: the following other types implement trait `From`: <[bool; N] as From>> diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index e0bdb6949a9c9..8e980997089e6 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -57,10 +57,10 @@ LL | f_sized(*ref_cl); | = help: the trait `Sized` is not implemented for `dyn Fn()` note: required by a bound in `f_sized` - --> $DIR/issue-84973-blacklist.rs:9:12 + --> $DIR/issue-84973-blacklist.rs:9:15 | LL | fn f_sized(t: T) {} - | ^ required by this bound in `f_sized` + | ^^^^^ required by this bound in `f_sized` error[E0277]: `Rc<{integer}>` cannot be sent between threads safely --> $DIR/issue-84973-blacklist.rs:27:12 diff --git a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr index 21b568b02ad25..7dcb2deb06a04 100644 --- a/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr +++ b/tests/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr @@ -5,11 +5,11 @@ LL | struct B(A<[u8]>); | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` -note: required by a bound in `A` +note: required by an implicit `Sized` bound in `A` --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 | LL | struct A(T) where T: Send; - | ^ required by this bound in `A` + | ^ required by the implicit `Sized` requirement on this type parameter in `A` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10 | diff --git a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr index 77e5dcd91a1ea..1cbcfbf84bcf4 100644 --- a/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr +++ b/tests/ui/suggestions/issue-85945-check-where-clause-before-suggesting-unsized.stderr @@ -8,10 +8,10 @@ LL | fn bar() { foo(""); } | = help: the trait `Sized` is not implemented for `str` note: required by a bound in `foo` - --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8 + --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:27 | LL | fn foo(_: &T) where T: Sized {} - | ^ required by this bound in `foo` + | ^^^^^ required by this bound in `foo` error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs index 366787df1b4dd..b1a7e6e966517 100644 --- a/tests/ui/suggestions/issue-86667.rs +++ b/tests/ui/suggestions/issue-86667.rs @@ -4,14 +4,15 @@ // compile-flags: --edition 2018 async fn a(s1: &str, s2: &str) -> &str { -//~^ ERROR: missing lifetime specifier [E0106] + //~^ ERROR: missing lifetime specifier [E0106] s1 -//~^ ERROR: lifetime may not live long enough + //~^ ERROR: lifetime may not live long enough } fn b(s1: &str, s2: &str) -> &str { -//~^ ERROR: missing lifetime specifier [E0106] + //~^ ERROR: missing lifetime specifier [E0106] s1 + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/suggestions/issue-86667.stderr b/tests/ui/suggestions/issue-86667.stderr index 8d611641626e1..e3d673ff23318 100644 --- a/tests/ui/suggestions/issue-86667.stderr +++ b/tests/ui/suggestions/issue-86667.stderr @@ -31,6 +31,15 @@ LL | LL | s1 | ^^ returning this value requires that `'1` must outlive `'static` -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/issue-86667.rs:14:5 + | +LL | fn b(s1: &str, s2: &str) -> &str { + | - let's call the lifetime of this reference `'1` +LL | +LL | s1 + | ^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/issue-88696.stderr b/tests/ui/suggestions/issue-88696.stderr index b4f0793c225ff..a8bc970e055b8 100644 --- a/tests/ui/suggestions/issue-88696.stderr +++ b/tests/ui/suggestions/issue-88696.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Result: From>` is not --> $DIR/issue-88696.rs:9:9 | LL | a().into() - | ^^^^ the trait `From>` is not implemented for `Result` + | ^^^^ the trait `From>` is not implemented for `Result`, which is required by `Result: Into<_>` | = note: required for `Result` to implement `Into>` diff --git a/tests/ui/suggestions/issue-89333.stderr b/tests/ui/suggestions/issue-89333.stderr index 761de7f252184..9df850ec9de08 100644 --- a/tests/ui/suggestions/issue-89333.stderr +++ b/tests/ui/suggestions/issue-89333.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'a> &'a _: Trait` is not satisfied --> $DIR/issue-89333.rs:6:5 | LL | test(&|| 0); - | ^^^^ the trait `for<'a> Trait` is not implemented for `&'a _` + | ^^^^^^^^^^^ the trait `for<'a> Trait` is not implemented for `&'a _` | help: this trait has no implementations, consider adding one --> $DIR/issue-89333.rs:9:1 diff --git a/tests/ui/suggestions/issue-96223.stderr b/tests/ui/suggestions/issue-96223.stderr index a54a4e7b3be4d..4a77b240f3e54 100644 --- a/tests/ui/suggestions/issue-96223.stderr +++ b/tests/ui/suggestions/issue-96223.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'de> EmptyBis<'de>: Foo<'_>` is not satisfied --> $DIR/issue-96223.rs:49:17 | LL | icey_bounds(&p); - | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>` + | ----------- ^^ the trait `for<'de> Foo<'_>` is not implemented for `EmptyBis<'de>`, which is required by `Empty: Dummy` | | | required by a bound introduced by this call | diff --git a/tests/ui/suggestions/issue-96555.stderr b/tests/ui/suggestions/issue-96555.stderr index 1a1e069f09eb4..f77681ae80faa 100644 --- a/tests/ui/suggestions/issue-96555.stderr +++ b/tests/ui/suggestions/issue-96555.stderr @@ -6,7 +6,7 @@ LL | m::f1().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` @@ -27,7 +27,7 @@ LL | m::f2().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` @@ -48,7 +48,7 @@ LL | m::f3().await; | | | this call returns `()` | - = help: the trait `Future` is not implemented for `()` + = help: the trait `Future` is not implemented for `()`, which is required by `(): IntoFuture` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` help: remove the `.await` diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed index 3257ea04c6900..d4a8381fcb146 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed @@ -1,6 +1,7 @@ // Make sure we suggest the bound `T: 'a` in the correct scope: // trait, impl or associated fn. // run-rustfix +#![allow(dead_code)] struct Inv<'a>(#[allow(dead_code)] Option<*mut &'a u8>); diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs index fcc13aad9965e..dc43e2df6ddb0 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs @@ -1,6 +1,7 @@ // Make sure we suggest the bound `T: 'a` in the correct scope: // trait, impl or associated fn. // run-rustfix +#![allow(dead_code)] struct Inv<'a>(#[allow(dead_code)] Option<*mut &'a u8>); diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr index d3ca2cc116228..91054472c04d4 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/type-param-bound-scope.rs:11:9 + --> $DIR/type-param-bound-scope.rs:12:9 | LL | trait Trait1<'a>: Sized { | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... @@ -13,7 +13,7 @@ LL | trait Trait1<'a>: Sized where Self: 'a { | ++++++++++++++ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/type-param-bound-scope.rs:18:9 + --> $DIR/type-param-bound-scope.rs:19:9 | LL | fn foo<'a>(self, lt: Inv<'a>) { | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... @@ -26,7 +26,7 @@ LL | fn foo<'a>(self, lt: Inv<'a>) where Self: 'a { | ++++++++++++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:25:9 + --> $DIR/type-param-bound-scope.rs:26:9 | LL | fn foo<'a>(arg: T, lt: Inv<'a>) { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -39,7 +39,7 @@ LL | fn foo<'a>(arg: T, lt: Inv<'a>) where T: 'a { | +++++++++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:32:9 + --> $DIR/type-param-bound-scope.rs:33:9 | LL | trait Trait4<'a> { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -53,7 +53,7 @@ LL | fn foo(arg: T, lt: Inv<'a>) { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:42:9 + --> $DIR/type-param-bound-scope.rs:43:9 | LL | impl<'a, T> Trait5<'a> for T { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 47b35b412c037..53476ee8c5936 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -8,8 +8,8 @@ pub struct Vector2{ } #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ - pub loc: Vector2, +pub struct AABB{ + pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` pub size: Vector2 } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 771e9105c6211..08c4f344e4ef0 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -9,7 +9,7 @@ pub struct Vector2{ #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB{ - pub loc: Vector2, + pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` pub size: Vector2 } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index ed1bde5f83e53..bfb96b4076b0f 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -18,6 +18,23 @@ help: consider further restricting this bound LL | pub struct AABB{ | +++++++ -error: aborting due to 1 previous error +error[E0277]: `K` doesn't implement `Debug` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:5:23 + | +LL | pub struct Vector2{ + | ^^^^^ required by this bound in `Vector2` +help: consider further restricting this bound + | +LL | pub struct AABB{ + | +++++++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 9c7b7ba099c43..2f1ebc1f133d6 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -9,6 +9,8 @@ pub struct Vector2{ #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB{ pub loc: Vector2, + //~^ ERROR doesn't implement `Debug` + //~| ERROR `K: Copy` is not satisfied pub size: Vector2 } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 03db737fa8761..f3213e1a4c818 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -18,6 +18,39 @@ help: consider restricting type parameter `K` LL | pub struct AABB{ | +++++++ -error: aborting due to 1 previous error +error[E0277]: `K` doesn't implement `Debug` + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:23 + | +LL | pub struct Vector2{ + | ^^^^^ required by this bound in `Vector2` +help: consider restricting type parameter `K` + | +LL | pub struct AABB{ + | +++++++++++++++++ + +error[E0277]: the trait bound `K: Copy` is not satisfied + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2, + | ^^^^^^^^^^ the trait `Copy` is not implemented for `K` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:31 + | +LL | pub struct Vector2{ + | ^^^^ required by this bound in `Vector2` +help: consider restricting type parameter `K` + | +LL | pub struct AABB{ + | +++++++++++++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed index f32c61a99bb8c..90bc10d34c611 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs index d7725f4a3743d..34673852a9b53 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index 6dc512223d1b0..23a75154f2008 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18 + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:17:18 | LL | struct Wrapper(T); | - this field does not implement `Copy` @@ -8,7 +8,7 @@ LL | impl Copy for Wrapper> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the `Copy` impl for `OnlyCopyIfDisplay` requires that `S: std::fmt::Display` - --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19 + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:5:19 | LL | struct Wrapper(T); | ^ diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed index 1139b315313fc..ff84e42c9470b 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs index 19549248efc23..35d0a9dda7914 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index fd38d4c64b44c..c9f277fb3501a 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18 + --> $DIR/missing-bound-in-manual-copy-impl.rs:7:18 | LL | struct Wrapper(T); | - this field does not implement `Copy` diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs index 01dcc94f7476e..85dd6a5635a21 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.rs +++ b/tests/ui/suggestions/missing-lifetime-specifier.rs @@ -1,4 +1,6 @@ // different number of duplicated diagnostics on different targets +// only-x86_64 +// only-linux // compile-flags: -Zdeduplicate-diagnostics=yes #![allow(bare_trait_objects)] @@ -18,21 +20,31 @@ pub union Qux<'t, 'k, I> { trait Tar<'t, 'k, I> {} thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static a: RefCell>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static b: RefCell>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static c: RefCell>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static d: RefCell>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index 7a7ef47c35b70..62eca16214871 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:21:44 + --> $DIR/missing-lifetime-specifier.rs:25:44 | LL | static a: RefCell>>> = RefCell::new(HashMap::new()); | ^^^ expected 2 lifetime parameters @@ -11,9 +11,11 @@ LL | static a: RefCell>>>> = RefC | ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:21:44 + --> $DIR/missing-lifetime-specifier.rs:25:44 | LL | / thread_local! { +LL | | +LL | | LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); | | ^^^ expected 2 lifetime parameters LL | | @@ -24,7 +26,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:26:44 + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); | ^^^^ expected 2 lifetime parameters @@ -38,9 +40,12 @@ LL | static b: RefCell>> | +++++++ ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:26:44 + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | / thread_local! { +LL | | +LL | | +LL | | LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); | | ^^^^ expected 2 lifetime parameters | | | @@ -53,7 +58,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:31:47 + --> $DIR/missing-lifetime-specifier.rs:40:47 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -65,9 +70,11 @@ LL | static c: RefCell>>>> = | +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:31:47 + --> $DIR/missing-lifetime-specifier.rs:40:47 | LL | / thread_local! { +LL | | +LL | | LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); | | ^ expected 2 lifetime parameters LL | | @@ -78,7 +85,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:36:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ ^ expected 2 lifetime parameters @@ -92,9 +99,12 @@ LL | static d: RefCell $DIR/missing-lifetime-specifier.rs:36:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | / thread_local! { +LL | | +LL | | +LL | | LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); | | ^ ^ expected 2 lifetime parameters | | | @@ -107,7 +117,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:46:44 + --> $DIR/missing-lifetime-specifier.rs:58:44 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -119,7 +129,7 @@ LL | static f: RefCell>>>> = | +++++++ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:46:44 + --> $DIR/missing-lifetime-specifier.rs:58:44 | LL | / thread_local! { LL | | static f: RefCell>>>> = RefCell::new(HashMap::new()); @@ -133,7 +143,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:42:44 + --> $DIR/missing-lifetime-specifier.rs:54:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -141,7 +151,7 @@ LL | static e: RefCell>>>> = RefCell: | expected 2 lifetime arguments | note: union defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:14:11 + --> $DIR/missing-lifetime-specifier.rs:16:11 | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- @@ -151,7 +161,7 @@ LL | static e: RefCell>>>> = | +++++++++ error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:46:45 + --> $DIR/missing-lifetime-specifier.rs:58:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -159,7 +169,7 @@ LL | static f: RefCell>>>> = RefCell | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:18:7 + --> $DIR/missing-lifetime-specifier.rs:20:7 | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- @@ -168,7 +178,199 @@ help: add missing lifetime argument LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | +++++++++ -error: aborting due to 12 previous errors +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:22:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:22:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static a: RefCell>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +LL | | static b: RefCell>>> = RefCell::new(HashMap::new()); + | | - let's call the lifetime of this reference `'1` +LL | | +LL | | +LL | | } + | |_^ returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'3` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:37:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:37:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static c: RefCell>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +LL | | static d: RefCell>>>> = RefCell::new(HashMap::new()); + | | - let's call the lifetime of this reference `'1` +LL | | +LL | | +LL | | } + | |_^ returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option>>>>>>` + | returning this value requires that `'3` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: aborting due to 22 previous errors Some errors have detailed explanations: E0106, E0107. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.rs b/tests/ui/suggestions/missing-lt-for-hrtb.rs index 04ea3d831c93a..a48c5665d67a4 100644 --- a/tests/ui/suggestions/missing-lt-for-hrtb.rs +++ b/tests/ui/suggestions/missing-lt-for-hrtb.rs @@ -8,6 +8,8 @@ fn main() { let x = S(&|x| { println!("hi"); x + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough }); x.0(&X(&())); } diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.stderr b/tests/ui/suggestions/missing-lt-for-hrtb.stderr index fa515644431ac..e8c536ac47d50 100644 --- a/tests/ui/suggestions/missing-lt-for-hrtb.stderr +++ b/tests/ui/suggestions/missing-lt-for-hrtb.stderr @@ -31,6 +31,28 @@ help: consider using one of the available lifetimes here LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>); | +++++++++ +++++++++++ -error: aborting due to 2 previous errors +error: lifetime may not live long enough + --> $DIR/missing-lt-for-hrtb.rs:10:9 + | +LL | let x = S(&|x| { + | -- return type of closure is &'2 X<'_> + | | + | has type `&'1 X<'_>` +LL | println!("hi"); +LL | x + | ^ returning this value requires that `'1` must outlive `'2` + +error: lifetime may not live long enough + --> $DIR/missing-lt-for-hrtb.rs:10:9 + | +LL | let x = S(&|x| { + | -- return type of closure is &X<'4> + | | + | has type `&X<'3>` +LL | println!("hi"); +LL | x + | ^ returning this value requires that `'3` must outlive `'4` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-trait-item.fixed b/tests/ui/suggestions/missing-trait-item.fixed index a1cf359ec9124..ded4ec1976067 100644 --- a/tests/ui/suggestions/missing-trait-item.fixed +++ b/tests/ui/suggestions/missing-trait-item.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait T { unsafe fn foo(a: &usize, b: &usize) -> usize; diff --git a/tests/ui/suggestions/missing-trait-item.rs b/tests/ui/suggestions/missing-trait-item.rs index b4fca25ba2f11..de8974037ac99 100644 --- a/tests/ui/suggestions/missing-trait-item.rs +++ b/tests/ui/suggestions/missing-trait-item.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait T { unsafe fn foo(a: &usize, b: &usize) -> usize; diff --git a/tests/ui/suggestions/missing-trait-item.stderr b/tests/ui/suggestions/missing-trait-item.stderr index 4a9d7b472c93a..298d0d16438be 100644 --- a/tests/ui/suggestions/missing-trait-item.stderr +++ b/tests/ui/suggestions/missing-trait-item.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar` - --> $DIR/missing-trait-item.rs:10:5 + --> $DIR/missing-trait-item.rs:11:5 | LL | unsafe fn foo(a: &usize, b: &usize) -> usize; | --------------------------------------------- `foo` from trait @@ -10,7 +10,7 @@ LL | impl T for () {} | ^^^^^^^^^^^^^ missing `foo`, `bar` in implementation error[E0046]: not all trait items implemented, missing: `foo`, `bar` - --> $DIR/missing-trait-item.rs:12:5 + --> $DIR/missing-trait-item.rs:13:5 | LL | unsafe fn foo(a: &usize, b: &usize) -> usize; | --------------------------------------------- `foo` from trait diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.fixed b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.fixed new file mode 100644 index 0000000000000..570d91d949bfc --- /dev/null +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.fixed @@ -0,0 +1,16 @@ +// run-rustfix +use std::io::stdin; + +fn get_name() -> String { + let mut your_name = String::new(); + stdin() + .read_line(&mut your_name) + .expect("Failed to read the line for some reason"); + your_name.trim().to_string() //~ ERROR E0308 +} + +fn main() { + println!("Hello, What is your name? "); + let your_name = get_name(); + println!("Hello, {}", your_name) +} diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs new file mode 100644 index 0000000000000..93e8c0af0323e --- /dev/null +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.rs @@ -0,0 +1,16 @@ +// run-rustfix +use std::io::stdin; + +fn get_name() -> String { + let mut your_name = String::new(); + stdin() + .read_line(&mut your_name) + .expect("Failed to read the line for some reason"); + your_name.trim() //~ ERROR E0308 +} + +fn main() { + println!("Hello, What is your name? "); + let your_name = get_name(); + println!("Hello, {}", your_name) +} diff --git a/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr new file mode 100644 index 0000000000000..c721ceb11463f --- /dev/null +++ b/tests/ui/suggestions/only-suggest-removal-of-conversion-method-calls.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/only-suggest-removal-of-conversion-method-calls.rs:9:5 + | +LL | fn get_name() -> String { + | ------ expected `String` because of return type +... +LL | your_name.trim() + | ^^^^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()` + | | + | expected `String`, found `&str` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/path-by-value.stderr b/tests/ui/suggestions/path-by-value.stderr index 567d9d5b9e7a4..46002d4e257e6 100644 --- a/tests/ui/suggestions/path-by-value.stderr +++ b/tests/ui/suggestions/path-by-value.stderr @@ -4,7 +4,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation LL | fn f(p: Path) { } | ^ doesn't have a size known at compile-time | - = help: within `Path`, the trait `Sized` is not implemented for `[u8]` + = help: within `Path`, the trait `Sized` is not implemented for `[u8]`, which is required by `Path: Sized` note: required because it appears within the type `Path` --> $SRC_DIR/std/src/path.rs:LL:COL = help: unsized fn params are gated as an unstable feature diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr index 46d0b35825bca..f9159c450301b 100644 --- a/tests/ui/suggestions/path-display.stderr +++ b/tests/ui/suggestions/path-display.stderr @@ -4,7 +4,7 @@ error[E0277]: `Path` doesn't implement `std::fmt::Display` LL | println!("{}", path); | ^^^^ `Path` cannot be formatted with the default formatter; call `.display()` on it | - = help: the trait `std::fmt::Display` is not implemented for `Path` + = help: the trait `std::fmt::Display` is not implemented for `Path`, which is required by `&Path: std::fmt::Display` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data = 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) diff --git a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr index eb74679d66049..dcab4d7c4fcb3 100644 --- a/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr +++ b/tests/ui/suggestions/removal-of-multiline-trait-bound-in-where-clause.stderr @@ -6,11 +6,11 @@ LL | fn foo(foo: Wrapper) | | | this type parameter needs to be `Sized` | -note: required by a bound in `Wrapper` +note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | @@ -35,11 +35,11 @@ LL | fn bar(foo: Wrapper) | | | this type parameter needs to be `Sized` | -note: required by a bound in `Wrapper` +note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | @@ -60,11 +60,11 @@ LL | fn qux(foo: Wrapper) | | | this type parameter needs to be `Sized` | -note: required by a bound in `Wrapper` +note: required by an implicit `Sized` bound in `Wrapper` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | LL | struct Wrapper(T); - | ^ required by this bound in `Wrapper` + | ^ required by the implicit `Sized` requirement on this type parameter in `Wrapper` help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box` --> $DIR/removal-of-multiline-trait-bound-in-where-clause.rs:1:16 | diff --git a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr index 125a8b44f2f0a..485015a98f2a7 100644 --- a/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr +++ b/tests/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&mut usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9 | LL | foo(Default::default()); - | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize` + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize` | help: consider mutably borrowing here | @@ -13,7 +13,7 @@ error[E0277]: the trait bound `&usize: Default` is not satisfied --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9 | LL | bar(Default::default()); - | ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize` + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize` | help: consider borrowing here | diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index 2316acbe9da28..86487cdcc444a 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -4,7 +4,7 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `&usize` LL | let one_item_please: i32 = [1, 2, 3][i]; | ^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`, which is required by `[{integer}; 3]: Index<_>` = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` = help: for that trait implementation, expected `usize`, found `&usize` = note: required for `[{integer}]` to implement `Index<&usize>` diff --git a/tests/ui/suggestions/suggest-pin-macro.stderr b/tests/ui/suggestions/suggest-pin-macro.stderr index a761a454ad5a3..68f4099a976d0 100644 --- a/tests/ui/suggestions/suggest-pin-macro.stderr +++ b/tests/ui/suggestions/suggest-pin-macro.stderr @@ -2,7 +2,7 @@ error[E0277]: `PhantomPinned` cannot be unpinned --> $DIR/suggest-pin-macro.rs:22:17 | LL | dummy(test1.get_mut()); - | ^^^^^^^ within `Test`, the trait `Unpin` is not implemented for `PhantomPinned` + | ^^^^^^^ within `Test`, the trait `Unpin` is not implemented for `PhantomPinned`, which is required by `Test: Unpin` | = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope diff --git a/tests/ui/suggestions/suggest-remove-refs-1.stderr b/tests/ui/suggestions/suggest-remove-refs-1.stderr index 523f78dffcc67..171184bf77d30 100644 --- a/tests/ui/suggestions/suggest-remove-refs-1.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-1.stderr @@ -4,7 +4,7 @@ error[E0277]: `&Enumerate>` is not an iterator LL | for (i, _) in &v.iter().enumerate() { | ^^^^^^^^^^^^^^^^^^^^^ `&Enumerate>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&Enumerate>` + = help: the trait `Iterator` is not implemented for `&Enumerate>`, which is required by `&Enumerate>: IntoIterator` = note: required for `&Enumerate>` to implement `IntoIterator` help: consider removing the leading `&`-reference | diff --git a/tests/ui/suggestions/suggest-remove-refs-2.stderr b/tests/ui/suggestions/suggest-remove-refs-2.stderr index bbe3261e14869..4e1994523dc2b 100644 --- a/tests/ui/suggestions/suggest-remove-refs-2.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-2.stderr @@ -4,7 +4,7 @@ error[E0277]: `&&&&&Enumerate>` is not an iterat LL | for (i, _) in & & & & &v.iter().enumerate() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&&&&&Enumerate>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>`, which is required by `&&&&&Enumerate>: IntoIterator` = note: required for `&&&&&Enumerate>` to implement `IntoIterator` help: consider removing 5 leading `&`-references | diff --git a/tests/ui/suggestions/suggest-remove-refs-3.stderr b/tests/ui/suggestions/suggest-remove-refs-3.stderr index a3e142563ff84..1d180f9d8be24 100644 --- a/tests/ui/suggestions/suggest-remove-refs-3.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-3.stderr @@ -8,7 +8,7 @@ LL | | .iter() LL | | .enumerate() { | |____________________^ `&&&&&Enumerate>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>` + = help: the trait `Iterator` is not implemented for `&&&&&Enumerate>`, which is required by `&&&&&Enumerate>: IntoIterator` = note: required for `&&&&&Enumerate>` to implement `IntoIterator` help: consider removing 5 leading `&`-references | diff --git a/tests/ui/suggestions/suggest-remove-refs-4.stderr b/tests/ui/suggestions/suggest-remove-refs-4.stderr index ed9fc2dd2568b..7ab34c4af511c 100644 --- a/tests/ui/suggestions/suggest-remove-refs-4.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-4.stderr @@ -4,7 +4,7 @@ error[E0277]: `&&std::slice::Iter<'_, {integer}>` is not an iterator LL | for _i in &foo {} | ^^^^ `&&std::slice::Iter<'_, {integer}>` is not an iterator | - = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>` + = help: the trait `Iterator` is not implemented for `&&std::slice::Iter<'_, {integer}>`, which is required by `&&std::slice::Iter<'_, {integer}>: IntoIterator` = note: required for `&&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` help: consider removing 2 leading `&`-references | diff --git a/tests/ui/suggestions/suggest-remove-refs-5.stderr b/tests/ui/suggestions/suggest-remove-refs-5.stderr index 7de84d6122b58..6b2f330e1a36d 100644 --- a/tests/ui/suggestions/suggest-remove-refs-5.stderr +++ b/tests/ui/suggestions/suggest-remove-refs-5.stderr @@ -4,7 +4,7 @@ error[E0277]: `Vec` is not an iterator LL | for _ in &mut &mut v {} | ^^^^^^^^^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` | - = help: the trait `Iterator` is not implemented for `Vec` + = help: the trait `Iterator` is not implemented for `Vec`, which is required by `&mut &mut &mut &mut Vec: IntoIterator` = note: required for `&mut Vec` to implement `Iterator` = note: 3 redundant requirements hidden = note: required for `&mut &mut &mut &mut Vec` to implement `Iterator` @@ -21,7 +21,7 @@ error[E0277]: `[u8; 1]` is not an iterator LL | for _ in &mut v {} | ^^^^^^ `[u8; 1]` is not an iterator; try calling `.into_iter()` or `.iter()` | - = help: the trait `Iterator` is not implemented for `[u8; 1]` + = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` = note: required for `&mut [u8; 1]` to implement `Iterator` = note: 2 redundant requirements hidden = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index 61d27ec69f4d2..c1cbefac828d6 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h9308686d0228fa1dE) +error: symbol-name(_ZN5basic4main17h6fc0c8d27b1a289fE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h9308686d0228fa1d) +error: demangling(basic::main::h6fc0c8d27b1a289f) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index eb65f3b58fff8..7dd68e6e3a8e2 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h84ab5dafbd2a1508E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hab58a402db4ebf3aE) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h84ab5dafbd2a1508) +error: demangling(issue_60925::foo::Foo::foo::hab58a402db4ebf3a) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/sync/mutexguard-sync.stderr b/tests/ui/sync/mutexguard-sync.stderr index 1501a793d5e8b..6b686741d1f82 100644 --- a/tests/ui/sync/mutexguard-sync.stderr +++ b/tests/ui/sync/mutexguard-sync.stderr @@ -6,7 +6,7 @@ LL | test_sync(guard); | | | required by a bound introduced by this call | - = help: the trait `Sync` is not implemented for `Cell` + = help: the trait `Sync` is not implemented for `Cell`, which is required by `MutexGuard<'_, Cell>: Sync` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead = note: required for `MutexGuard<'_, Cell>` to implement `Sync` note: required by a bound in `test_sync` diff --git a/tests/ui/tag-type-args.stderr b/tests/ui/tag-type-args.stderr index 80ffd3a2f0500..a1136f61cc52f 100644 --- a/tests/ui/tag-type-args.stderr +++ b/tests/ui/tag-type-args.stderr @@ -14,14 +14,14 @@ help: add missing generic argument LL | fn foo(c: Quux) { assert!((false)); } | +++ -error[E0392]: parameter `T` is never used +error[E0392]: type parameter `T` is never used --> $DIR/tag-type-args.rs:1:11 | LL | enum Quux { Bar } - | ^ unused parameter + | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = help: if you intended `T` to be a const parameter, use `const T: usize` instead + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error: aborting due to 2 previous errors diff --git a/tests/ui/tag-variant-cast-non-nullary.stderr b/tests/ui/tag-variant-cast-non-nullary.stderr index 560dd7e8164f1..2e1dde27d0f98 100644 --- a/tests/ui/tag-variant-cast-non-nullary.stderr +++ b/tests/ui/tag-variant-cast-non-nullary.stderr @@ -4,7 +4,8 @@ error[E0605]: non-primitive cast: `NonNullary` as `isize` LL | let val = v as isize; | ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)` | - = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + = note: an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information error: aborting due to 1 previous error diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.rs b/tests/ui/test-attrs/test-panic-abort-nocapture.rs index af530cc1a0b8f..c7415818e10f5 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.rs +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.rs @@ -6,6 +6,7 @@ // exec-env:RUST_BACKTRACE=0 // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-android #120567 // ignore-wasm no panic or subprocess support // ignore-emscripten no panic or subprocess support // ignore-sgx no subprocess support diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr index 6997833834df6..16001b3eecd4d 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr @@ -1,9 +1,9 @@ -thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:33:5: +thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:34:5: assertion `left == right` failed left: 2 right: 4 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:27:5: +thread 'main' panicked at $DIR/test-panic-abort-nocapture.rs:28:5: assertion `left == right` failed left: 2 right: 4 diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs index 08e5242af66f9..d80e2435614dc 100644 --- a/tests/ui/test-attrs/test-panic-abort.rs +++ b/tests/ui/test-attrs/test-panic-abort.rs @@ -6,6 +6,7 @@ // exec-env:RUST_BACKTRACE=0 // normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// ignore-android #120567 // ignore-wasm no panic or subprocess support // ignore-emscripten no panic or subprocess support // ignore-sgx no subprocess support diff --git a/tests/ui/test-attrs/test-panic-abort.run.stdout b/tests/ui/test-attrs/test-panic-abort.run.stdout index 0e27f6fb655b0..f5d14e77da963 100644 --- a/tests/ui/test-attrs/test-panic-abort.run.stdout +++ b/tests/ui/test-attrs/test-panic-abort.run.stdout @@ -17,7 +17,7 @@ hello, world testing123 ---- it_fails stderr ---- testing321 -thread 'main' panicked at $DIR/test-panic-abort.rs:38:5: +thread 'main' panicked at $DIR/test-panic-abort.rs:39:5: assertion `left == right` failed left: 2 right: 5 diff --git a/tests/ui/threads-sendsync/sync-send-atomics.rs b/tests/ui/threads-sendsync/sync-send-atomics.rs index 0466f4f0e9ddc..6b260311a50a7 100644 --- a/tests/ui/threads-sendsync/sync-send-atomics.rs +++ b/tests/ui/threads-sendsync/sync-send-atomics.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 diff --git a/tests/ui/trait-bounds/unsized-bound.stderr b/tests/ui/trait-bounds/unsized-bound.stderr index 4d45bffabce5e..c8049ebee1173 100644 --- a/tests/ui/trait-bounds/unsized-bound.stderr +++ b/tests/ui/trait-bounds/unsized-bound.stderr @@ -7,11 +7,11 @@ LL | impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} | this type parameter needs to be `Sized` | = note: required because it appears within the type `(A, B)` -note: required by a bound in `Trait` +note: required by an implicit `Sized` bound in `Trait` --> $DIR/unsized-bound.rs:1:13 | LL | trait Trait {} - | ^ required by this bound in `Trait` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait<(A, B)> for (A, B) where A: ?Sized, B: ?Sized, {} @@ -46,11 +46,11 @@ LL | impl Trait<(A, B, C)> for (A, B, C) where A: ?Size | this type parameter needs to be `Sized` | = note: required because it appears within the type `(A, B, C)` -note: required by a bound in `Trait` +note: required by an implicit `Sized` bound in `Trait` --> $DIR/unsized-bound.rs:1:13 | LL | trait Trait {} - | ^ required by this bound in `Trait` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait<(A, B, C)> for (A, B, C) where A: ?Sized, {} @@ -96,11 +96,11 @@ LL | impl Trait2<(A, B)> for (A, B) {} | this type parameter needs to be `Sized` | = note: required because it appears within the type `(A, B)` -note: required by a bound in `Trait2` +note: required by an implicit `Sized` bound in `Trait2` --> $DIR/unsized-bound.rs:9:14 | LL | trait Trait2 {} - | ^ required by this bound in `Trait2` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait2` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait2<(A, B)> for (A, B) {} @@ -134,11 +134,11 @@ LL | impl Trait3 for A where A: ?Sized {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait3` +note: required by an implicit `Sized` bound in `Trait3` --> $DIR/unsized-bound.rs:13:14 | LL | trait Trait3 {} - | ^ required by this bound in `Trait3` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait3` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait3 for A where A: ?Sized {} @@ -157,11 +157,11 @@ LL | impl Trait4 for A {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait4` +note: required by an implicit `Sized` bound in `Trait4` --> $DIR/unsized-bound.rs:16:14 | LL | trait Trait4 {} - | ^ required by this bound in `Trait4` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait4` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait4 for A {} @@ -180,11 +180,11 @@ LL | impl Trait5 for X where X: ?Sized {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait5` +note: required by an implicit `Sized` bound in `Trait5` --> $DIR/unsized-bound.rs:19:14 | LL | trait Trait5 {} - | ^ required by this bound in `Trait5` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait5` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait5 for X where X: ?Sized {} @@ -203,11 +203,11 @@ LL | impl Trait6 for X {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait6` +note: required by an implicit `Sized` bound in `Trait6` --> $DIR/unsized-bound.rs:22:14 | LL | trait Trait6 {} - | ^ required by this bound in `Trait6` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait6` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait6 for X {} @@ -226,11 +226,11 @@ LL | impl Trait7 for X where Y: ?Sized {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait7` +note: required by an implicit `Sized` bound in `Trait7` --> $DIR/unsized-bound.rs:25:17 | LL | trait Trait7 {} - | ^ required by this bound in `Trait7` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait7` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait7 for X where Y: ?Sized {} @@ -249,11 +249,11 @@ LL | impl Trait8 for X {} | | | this type parameter needs to be `Sized` | -note: required by a bound in `Trait8` +note: required by an implicit `Sized` bound in `Trait8` --> $DIR/unsized-bound.rs:28:17 | LL | trait Trait8 {} - | ^ required by this bound in `Trait8` + | ^ required by the implicit `Sized` requirement on this type parameter in `Trait8` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - impl Trait8 for X {} diff --git a/tests/ui/traits/alias/bounds.rs b/tests/ui/traits/alias/bounds.rs index b97eb38c5af8d..7b1920bc8f27c 100644 --- a/tests/ui/traits/alias/bounds.rs +++ b/tests/ui/traits/alias/bounds.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; -trait Empty {} +trait Empty {} //~ WARN trait `Empty` is never used trait EmptyAlias = Empty; trait CloneDefault = Clone + Default; trait SendSyncAlias = Send + Sync; diff --git a/tests/ui/traits/alias/bounds.stderr b/tests/ui/traits/alias/bounds.stderr new file mode 100644 index 0000000000000..7fb8e918da36d --- /dev/null +++ b/tests/ui/traits/alias/bounds.stderr @@ -0,0 +1,10 @@ +warning: trait `Empty` is never used + --> $DIR/bounds.rs:7:7 + | +LL | trait Empty {} + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/alias/cross-crate.stderr b/tests/ui/traits/alias/cross-crate.stderr index ae9d7d0a9b4a4..fd614b4bcd58a 100644 --- a/tests/ui/traits/alias/cross-crate.stderr +++ b/tests/ui/traits/alias/cross-crate.stderr @@ -4,7 +4,7 @@ error[E0277]: `Rc` cannot be sent between threads safely LL | use_alias::>(); | ^^^^^^^ `Rc` cannot be sent between threads safely | - = help: the trait `Send` is not implemented for `Rc` + = help: the trait `Send` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 @@ -18,7 +18,7 @@ error[E0277]: `Rc` cannot be shared between threads safely LL | use_alias::>(); | ^^^^^^^ `Rc` cannot be shared between threads safely | - = help: the trait `Sync` is not implemented for `Rc` + = help: the trait `Sync` is not implemented for `Rc`, which is required by `Rc: SendSync` = note: required for `Rc` to implement `SendSync` note: required by a bound in `use_alias` --> $DIR/cross-crate.rs:10:17 diff --git a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr index 968ad2667a210..1e4f4cb70463c 100644 --- a/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr +++ b/tests/ui/traits/alias/issue-108072-unmet-trait-alias-bound.stderr @@ -6,7 +6,7 @@ LL | f(()) | | | required by a bound introduced by this call | - = help: the trait `Iterator` is not implemented for `()` + = help: the trait `Iterator` is not implemented for `()`, which is required by `(): IteratorAlias` = note: required for `()` to implement `IteratorAlias` note: required by a bound in `f` --> $DIR/issue-108072-unmet-trait-alias-bound.rs:7:14 diff --git a/tests/ui/traits/alias/syntax.rs b/tests/ui/traits/alias/syntax.rs index 17557a51aa723..50c77d33c6bce 100644 --- a/tests/ui/traits/alias/syntax.rs +++ b/tests/ui/traits/alias/syntax.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr index fb9900bc57bbc..4c1835dfed085 100644 --- a/tests/ui/traits/bad-sized.stderr +++ b/tests/ui/traits/bad-sized.stderr @@ -16,14 +16,14 @@ LL | let x: Vec = Vec::new(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:37 | LL | let x: Vec = Vec::new(); - | ^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` note: required by a bound in `Vec::::new` @@ -36,7 +36,7 @@ LL | let x: Vec = Vec::new(); | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Trait` -note: required by a bound in `Vec` +note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error: aborting due to 4 previous errors diff --git a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr index c8631ed3677e8..bd9838bc62354 100644 --- a/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr +++ b/tests/ui/traits/bound/assoc-fn-bound-root-obligation.stderr @@ -4,7 +4,7 @@ error[E0277]: expected a `FnMut(char)` closure, found `u8` LL | s.strip_suffix(b'\n').unwrap_or(s) | ^^^^^^^^^^^^ expected an `FnMut(char)` closure, found `u8` | - = help: the trait `FnMut<(char,)>` is not implemented for `u8` + = help: the trait `FnMut<(char,)>` is not implemented for `u8`, which is required by `u8: Pattern<'_>` = help: the following other types implement trait `Pattern<'a>`: char [char; N] diff --git a/tests/ui/traits/bound/impl-comparison-duplicates.rs b/tests/ui/traits/bound/impl-comparison-duplicates.rs index de6c2afa2bbe1..a59662c2797ff 100644 --- a/tests/ui/traits/bound/impl-comparison-duplicates.rs +++ b/tests/ui/traits/bound/impl-comparison-duplicates.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Tests that type parameter bounds on an implementation need not match the // trait exactly, as long as the implementation doesn't demand *more* bounds // than the trait. diff --git a/tests/ui/traits/bound/recursion.rs b/tests/ui/traits/bound/recursion.rs index 0023ff654e84c..767040dff3f73 100644 --- a/tests/ui/traits/bound/recursion.rs +++ b/tests/ui/traits/bound/recursion.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait I { fn i(&self) -> Self; } diff --git a/tests/ui/traits/composition-trivial.rs b/tests/ui/traits/composition-trivial.rs index 90e5dcd68e8c4..41e6a55607449 100644 --- a/tests/ui/traits/composition-trivial.rs +++ b/tests/ui/traits/composition-trivial.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/traits/copy-impl-cannot-normalize.stderr b/tests/ui/traits/copy-impl-cannot-normalize.stderr index 3bdb8b70172c4..a98bb47f54fc1 100644 --- a/tests/ui/traits/copy-impl-cannot-normalize.stderr +++ b/tests/ui/traits/copy-impl-cannot-normalize.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: TraitFoo` is not satisfied --> $DIR/copy-impl-cannot-normalize.rs:22:18 | LL | impl Copy for Foo {} - | ^^^^^^ the trait `TraitFoo` is not implemented for `T` + | ^^^^^^ the trait `TraitFoo` is not implemented for `T`, which is required by `Foo: Clone` | note: required for `Foo` to implement `Clone` --> $DIR/copy-impl-cannot-normalize.rs:12:9 diff --git a/tests/ui/traits/cycle-generic-bound.rs b/tests/ui/traits/cycle-generic-bound.rs index 9241f3789d72a..77685c26da242 100644 --- a/tests/ui/traits/cycle-generic-bound.rs +++ b/tests/ui/traits/cycle-generic-bound.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Regression test for #15477. This test just needs to compile. // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/default-method/bound-subst4.rs b/tests/ui/traits/default-method/bound-subst4.rs index ef13306458255..6bc4cf0ef805c 100644 --- a/tests/ui/traits/default-method/bound-subst4.rs +++ b/tests/ui/traits/default-method/bound-subst4.rs @@ -4,7 +4,7 @@ trait A { fn g(&self, x: usize) -> usize { x } - fn h(&self, x: T) { } + fn h(&self, x: T) { } //~ WARN method `h` is never used } impl A for isize { } diff --git a/tests/ui/traits/default-method/bound-subst4.stderr b/tests/ui/traits/default-method/bound-subst4.stderr new file mode 100644 index 0000000000000..548c46f123322 --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst4.stderr @@ -0,0 +1,13 @@ +warning: method `h` is never used + --> $DIR/bound-subst4.rs:7:8 + | +LL | trait A { + | - method in this trait +LL | fn g(&self, x: usize) -> usize { x } +LL | fn h(&self, x: T) { } + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/default-method/mut.rs b/tests/ui/traits/default-method/mut.rs index 5f8e983b09cfb..3294b96561fd1 100644 --- a/tests/ui/traits/default-method/mut.rs +++ b/tests/ui/traits/default-method/mut.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_assignments)] // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr index a5d0e6ab09569..fecb05cade758 100644 --- a/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr +++ b/tests/ui/traits/dont-autoderef-ty-with-escaping-var.stderr @@ -8,7 +8,7 @@ error[E0277]: the trait bound `for<'a> &'a mut Vec<&'a u32>: Foo<'static, i32>` --> $DIR/dont-autoderef-ty-with-escaping-var.rs:17:6 | LL | >::ref_foo(unknown); - | ^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>` + | ^^^ the trait `for<'a> Foo<'static, i32>` is not implemented for `&'a mut Vec<&'a u32>`, which is required by `i32: RefFoo` | help: this trait has no implementations, consider adding one --> $DIR/dont-autoderef-ty-with-escaping-var.rs:3:1 diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.rs b/tests/ui/traits/impl-inherent-prefer-over-trait.rs index 82760788897a5..f03e730d091eb 100644 --- a/tests/ui/traits/impl-inherent-prefer-over-trait.rs +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.rs @@ -3,7 +3,7 @@ struct Foo; trait Trait { - fn bar(&self); + fn bar(&self); //~ WARN method `bar` is never used } // Inherent impls should be preferred over trait ones. diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.stderr b/tests/ui/traits/impl-inherent-prefer-over-trait.stderr new file mode 100644 index 0000000000000..f0bb21402d873 --- /dev/null +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.stderr @@ -0,0 +1,12 @@ +warning: method `bar` is never used + --> $DIR/impl-inherent-prefer-over-trait.rs:6:8 + | +LL | trait Trait { + | ----- method in this trait +LL | fn bar(&self); + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.rs b/tests/ui/traits/impl-object-overlap-issue-23853.rs index e490967b69047..c0d3af11443d4 100644 --- a/tests/ui/traits/impl-object-overlap-issue-23853.rs +++ b/tests/ui/traits/impl-object-overlap-issue-23853.rs @@ -5,7 +5,7 @@ // including `Bar`, but the object type `Bar` also implicitly supplies // this context. -trait Foo { fn dummy(&self) { } } +trait Foo { fn dummy(&self) { } } //~ WARN method `dummy` is never used trait Bar: Foo { } diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.stderr b/tests/ui/traits/impl-object-overlap-issue-23853.stderr new file mode 100644 index 0000000000000..9fa7a36816e4d --- /dev/null +++ b/tests/ui/traits/impl-object-overlap-issue-23853.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/impl-object-overlap-issue-23853.rs:8:16 + | +LL | trait Foo { fn dummy(&self) { } } + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs index f512d91ebeb4a..7bec1b6c9ff4f 100644 --- a/tests/ui/traits/impl.rs +++ b/tests/ui/traits/impl.rs @@ -9,7 +9,7 @@ use traitimpl::Bar; static mut COUNT: usize = 1; trait T { - fn t(&self) {} + fn t(&self) {} //~ WARN method `t` is never used } impl<'a> dyn T+'a { diff --git a/tests/ui/traits/impl.stderr b/tests/ui/traits/impl.stderr new file mode 100644 index 0000000000000..98b6fb03d836f --- /dev/null +++ b/tests/ui/traits/impl.stderr @@ -0,0 +1,12 @@ +warning: method `t` is never used + --> $DIR/impl.rs:12:8 + | +LL | trait T { + | - method in this trait +LL | fn t(&self) {} + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/inductive-overflow/lifetime.stderr b/tests/ui/traits/inductive-overflow/lifetime.stderr index b34bb0361f1e4..406f4d25dce3f 100644 --- a/tests/ui/traits/inductive-overflow/lifetime.stderr +++ b/tests/ui/traits/inductive-overflow/lifetime.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `Box>>: NotAuto` --> $DIR/lifetime.rs:29:5 | LL | is_send::>>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required for `X>` to implement `NotAuto` --> $DIR/lifetime.rs:19:12 diff --git a/tests/ui/traits/inductive-overflow/simultaneous.stderr b/tests/ui/traits/inductive-overflow/simultaneous.stderr index b9a746e44ba01..29456d88b1bfc 100644 --- a/tests/ui/traits/inductive-overflow/simultaneous.stderr +++ b/tests/ui/traits/inductive-overflow/simultaneous.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum` --> $DIR/simultaneous.rs:18:5 | LL | is_ee(4); - | ^^^^^ + | ^^^^^^^^ | note: required for `{integer}` to implement `Combo` --> $DIR/simultaneous.rs:11:34 diff --git a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr index e723c7c51814a..629ccac49c56a 100644 --- a/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait-auto-trait.stderr @@ -10,7 +10,7 @@ error[E0277]: the trait bound `NoClone: Copy` is not satisfied --> $DIR/supertrait-auto-trait.rs:16:23 | LL | let (a, b) = copy(NoClone); - | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone` + | ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`, which is required by `NoClone: Magic` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/inductive-overflow/supertrait.stderr b/tests/ui/traits/inductive-overflow/supertrait.stderr index f2dccbbbb2cb6..99e9c8f93b8a4 100644 --- a/tests/ui/traits/inductive-overflow/supertrait.stderr +++ b/tests/ui/traits/inductive-overflow/supertrait.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `NoClone: Magic` --> $DIR/supertrait.rs:13:18 | LL | let (a, b) = copy(NoClone); - | ^^^^ + | ^^^^^^^^^^^^^ | note: required for `NoClone` to implement `Magic` --> $DIR/supertrait.rs:5:16 diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr index 0d0bf88616c86..6092c194a8757 100644 --- a/tests/ui/traits/inductive-overflow/two-traits.stderr +++ b/tests/ui/traits/inductive-overflow/two-traits.stderr @@ -18,7 +18,7 @@ error[E0275]: overflow evaluating the requirement `*mut (): Magic` --> $DIR/two-traits.rs:20:5 | LL | wizard::<*mut ()>(); - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `wizard` --> $DIR/two-traits.rs:17:14 diff --git a/tests/ui/traits/invalid_operator_trait.rs b/tests/ui/traits/invalid_operator_trait.rs deleted file mode 100644 index 7ea3b0d5bac76..0000000000000 --- a/tests/ui/traits/invalid_operator_trait.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![crate_type = "lib"] -#![feature(lang_items)] -#![feature(no_core)] -#![no_core] - -#[lang="sized"] -pub trait Sized { - // Empty. -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, _: RHS) -> Self::Output; - //~^ ERROR `add` must not have any generic parameters -} - -#[allow(unreachable_code)] -fn ice(a: usize) { - let r = loop {}; - r = r + a; -} diff --git a/tests/ui/traits/invalid_operator_trait.stderr b/tests/ui/traits/invalid_operator_trait.stderr deleted file mode 100644 index f2e5e9080b16e..0000000000000 --- a/tests/ui/traits/invalid_operator_trait.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `add` must not have any generic parameters - --> $DIR/invalid_operator_trait.rs:15:5 - | -LL | fn add(self, _: RHS) -> Self::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/traits/issue-102989.rs b/tests/ui/traits/issue-102989.rs deleted file mode 100644 index f1ecee0a552a7..0000000000000 --- a/tests/ui/traits/issue-102989.rs +++ /dev/null @@ -1,15 +0,0 @@ -// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib" - -#![feature(lang_items)] -#[lang="sized"] -trait Sized { } //~ ERROR found duplicate lang item `sized` - -fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - //~^ ERROR `self` parameter is only allowed in associated functions - //~| ERROR cannot find type `Struct` in this scope - //~| ERROR mismatched types - let x = x << 1; - //~^ ERROR cannot find value `x` in this scope -} - -fn main() {} diff --git a/tests/ui/traits/issue-102989.stderr b/tests/ui/traits/issue-102989.stderr deleted file mode 100644 index 40e49df2b2d96..0000000000000 --- a/tests/ui/traits/issue-102989.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: `self` parameter is only allowed in associated functions - --> $DIR/issue-102989.rs:7:15 - | -LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - | ^^^^ not semantically valid as function parameter - | - = note: associated functions are those in `impl` or `trait` definitions - -error[E0412]: cannot find type `Struct` in this scope - --> $DIR/issue-102989.rs:7:22 - | -LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - | ^^^^^^ not found in this scope - -error[E0425]: cannot find value `x` in this scope - --> $DIR/issue-102989.rs:11:13 - | -LL | let x = x << 1; - | ^ help: a local variable with a similar name exists: `f` - -error[E0152]: found duplicate lang item `sized` - --> $DIR/issue-102989.rs:5:1 - | -LL | trait Sized { } - | ^^^^^^^^^^^^^^^ - | - = note: the lang item is first defined in crate `core` (which `std` depends on) - = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib - = note: second definition in the local crate (`issue_102989`) - -error[E0308]: mismatched types - --> $DIR/issue-102989.rs:7:42 - | -LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { - | ---------- ^^^^ expected `&u32`, found `()` - | | - | implicitly returns `()` as its body has no tail or `return` expression - | -help: consider returning the local binding `f` - | -LL ~ let x = x << 1; -LL + f - | - -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0152, E0308, E0412, E0425. -For more information about an error, try `rustc --explain E0152`. diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index 96e8aaee23d56..adba5830b10e1 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -25,11 +25,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | pub trait Bar: Foo { | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/issue-28576.rs:1:15 | LL | pub trait Foo { - | ^^^^^^^^ required by this bound in `Foo` + | ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: consider further restricting `Self` | LL | pub trait Bar: Foo + Sized { @@ -45,11 +45,11 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation LL | pub trait Bar: Foo { | ^^^^^^^^^^^^^ doesn't have a size known at compile-time | -note: required by a bound in `Foo` +note: required by an implicit `Sized` bound in `Foo` --> $DIR/issue-28576.rs:1:15 | LL | pub trait Foo { - | ^^^^^^^^ required by this bound in `Foo` + | ^^^^^^^^ required by the implicit `Sized` requirement on this type parameter in `Foo` help: consider further restricting `Self` | LL | ) where Self: Sized; diff --git a/tests/ui/issues/issue-33096.rs b/tests/ui/traits/issue-33096.rs similarity index 100% rename from tests/ui/issues/issue-33096.rs rename to tests/ui/traits/issue-33096.rs diff --git a/tests/ui/traits/issue-38033.rs b/tests/ui/traits/issue-38033.rs index 16b867ec88f17..4d76df1e8d5bc 100644 --- a/tests/ui/traits/issue-38033.rs +++ b/tests/ui/traits/issue-38033.rs @@ -19,7 +19,7 @@ trait IntoFuture { type Item; type Error; - fn into_future(self) -> Self::Future; + fn into_future(self) -> Self::Future; //~ WARN method `into_future` is never used } impl IntoFuture for F { diff --git a/tests/ui/traits/issue-38033.stderr b/tests/ui/traits/issue-38033.stderr new file mode 100644 index 0000000000000..05385e8cf4d9d --- /dev/null +++ b/tests/ui/traits/issue-38033.stderr @@ -0,0 +1,13 @@ +warning: method `into_future` is never used + --> $DIR/issue-38033.rs:22:8 + | +LL | trait IntoFuture { + | ---------- method in this trait +... +LL | fn into_future(self) -> Self::Future; + | ^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-40085.rs b/tests/ui/traits/issue-40085.rs similarity index 100% rename from tests/ui/issues/issue-40085.rs rename to tests/ui/traits/issue-40085.rs diff --git a/tests/ui/traits/issue-43784-supertrait.stderr b/tests/ui/traits/issue-43784-supertrait.stderr index 2bf365745a6bd..4c565c3fa1db5 100644 --- a/tests/ui/traits/issue-43784-supertrait.stderr +++ b/tests/ui/traits/issue-43784-supertrait.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied --> $DIR/issue-43784-supertrait.rs:8:22 | LL | impl Complete for T {} - | ^ the trait `Copy` is not implemented for `T` + | ^ the trait `Copy` is not implemented for `T`, which is required by `T: Partial` | note: required for `T` to implement `Partial` --> $DIR/issue-43784-supertrait.rs:1:11 diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index 683a85a32c1c6..cc7ea32eb3a5c 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -5,11 +5,13 @@ struct Foo(N, NotDefined, ::Item, Vec, String); //~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR cannot find type `N` in this scope +//~| ERROR `i32` is not an iterator #[derive(Clone, Copy)] //~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(T, N, NotDefined, ::Item, Vec, String); //~^ ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope +//~| ERROR `i32` is not an iterator fn main() {} diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 4f72db60a1647..68d3d5c80d0d2 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -38,7 +38,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, St | ++++++++++++ error[E0412]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:11:18 + --> $DIR/issue-50480.rs:12:18 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | - ^ @@ -55,7 +55,7 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, Strin | +++ error[E0412]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:11:21 + --> $DIR/issue-50480.rs:12:21 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope @@ -74,7 +74,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:9:17 + --> $DIR/issue-50480.rs:10:17 | LL | #[derive(Clone, Copy)] | ^^^^ @@ -86,7 +86,25 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 8 previous errors +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:3:27 + | +LL | struct Foo(N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:12:33 + | +LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0204, E0412. +Some errors have detailed explanations: E0204, E0277, E0412. For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/issue-56488.rs b/tests/ui/traits/issue-56488.rs index e2f3996927b7f..8b68f314c04dd 100644 --- a/tests/ui/traits/issue-56488.rs +++ b/tests/ui/traits/issue-56488.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] diff --git a/tests/ui/issues/issue-58344.rs b/tests/ui/traits/issue-58344.rs similarity index 100% rename from tests/ui/issues/issue-58344.rs rename to tests/ui/traits/issue-58344.rs diff --git a/tests/ui/traits/issue-59029-2.rs b/tests/ui/traits/issue-59029-2.rs index 2bdb128d8c4c8..fca9f1f13c9de 100644 --- a/tests/ui/traits/issue-59029-2.rs +++ b/tests/ui/traits/issue-59029-2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] trait Svc { type Res; } diff --git a/tests/ui/traits/issue-6128.rs b/tests/ui/traits/issue-6128.rs index 07d92f8f8a016..f5fa0de809a19 100644 --- a/tests/ui/traits/issue-6128.rs +++ b/tests/ui/traits/issue-6128.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; trait Graph { - fn f(&self, _: Edge); + fn f(&self, _: Edge); //~ WARN methods `f` and `g` are never used fn g(&self, _: Node); } diff --git a/tests/ui/traits/issue-6128.stderr b/tests/ui/traits/issue-6128.stderr new file mode 100644 index 0000000000000..c9518ea41ea70 --- /dev/null +++ b/tests/ui/traits/issue-6128.stderr @@ -0,0 +1,14 @@ +warning: methods `f` and `g` are never used + --> $DIR/issue-6128.rs:6:8 + | +LL | trait Graph { + | ----- methods in this trait +LL | fn f(&self, _: Edge); + | ^ +LL | fn g(&self, _: Node); + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr index 1749366317286..5067c7d7dd7d7 100644 --- a/tests/ui/traits/issue-7013.stderr +++ b/tests/ui/traits/issue-7013.stderr @@ -4,7 +4,7 @@ error[E0277]: `Rc>` cannot be sent between threads safely LL | let a = A {v: Box::new(B{v: None}) as Box}; | ^^^^^^^^^^^^^^^^^^^^ `Rc>` cannot be sent between threads safely | - = help: within `B`, the trait `Send` is not implemented for `Rc>` + = help: within `B`, the trait `Send` is not implemented for `Rc>`, which is required by `B: Send` note: required because it appears within the type `Option>>` --> $SRC_DIR/core/src/option.rs:LL:COL note: required because it appears within the type `B` diff --git a/tests/ui/traits/issue-71036.stderr b/tests/ui/traits/issue-71036.stderr index 2452731f19f16..35d543eb0177a 100644 --- a/tests/ui/traits/issue-71036.stderr +++ b/tests/ui/traits/issue-71036.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'a T: Unsize<&'a U>` is not satisfied --> $DIR/issue-71036.rs:11:1 | LL | impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`, which is required by `&'a &'a T: DispatchFromDyn<&'a &'a U>` | = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>` diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr index 2c03c6bf08ed8..d37ad8ae34d0d 100644 --- a/tests/ui/traits/issue-71136.stderr +++ b/tests/ui/traits/issue-71136.stderr @@ -5,7 +5,7 @@ LL | #[derive(Clone)] | ----- in this derive macro expansion LL | struct FooHolster { LL | the_foos: Vec, - | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`, which is required by `Vec: Clone` | = note: required for `Vec` to implement `Clone` = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs index 92f9f4b467a97..143325c097c13 100644 --- a/tests/ui/traits/issue-78372.rs +++ b/tests/ui/traits/issue-78372.rs @@ -6,8 +6,9 @@ impl DispatchFromDyn> for T {} //~ ERROR cannot find type `U` //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures trait Foo: X {} trait X { - fn foo(self: Smaht); + fn foo(self: Smaht); //~ ERROR: invalid `self` } trait Marker {} impl Marker for dyn Foo {} +//~^ ERROR cannot be made into an object fn main() {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 44a62988daf37..edb07957c445c 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -61,7 +61,34 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion LL | impl DispatchFromDyn> for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/issue-78372.rs:12:17 + | +LL | fn foo(self: Smaht); + | -------------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | impl Marker for dyn Foo {} + | ^^^^^^^ `Foo` 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 + --> $DIR/issue-78372.rs:9:18 + | +LL | trait Foo: X {} + | --- this trait cannot be made into an object... +LL | trait X { +LL | fn foo(self: Smaht); + | ^^^^^^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on -Some errors have detailed explanations: E0378, E0412, E0658. -For more information about an error, try `rustc --explain E0378`. +error[E0307]: invalid `self` parameter type: Smaht + --> $DIR/issue-78372.rs:9:18 + | +LL | fn foo(self: Smaht); + | ^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin