diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 382f0539f7678..e91ab584bcf47 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -22,7 +22,7 @@ use crate::diagnostics::{ use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser}; use crate::session_diagnostics::{ DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel, - DocAttributeNotAttribute, DocKeywordNotKeyword, + DocAttributeNotAttribute, DocKeywordNotKeyword, UnusedDuplicate, }; fn check_keyword(cx: &mut AcceptContext<'_, '_>, keyword: Symbol, span: Span) -> bool { @@ -159,11 +159,7 @@ impl DocParser { let unused_span = path.span(); cx.emit_lint( rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES, - rustc_errors::lints::UnusedDuplicate { - this: unused_span, - other: used_span, - warning: true, - }, + UnusedDuplicate { this: unused_span, other: used_span, warning: true }, unused_span, ); return; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index fb5ca0375900a..2811bc8ff5683 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -71,7 +71,7 @@ use crate::parser::{ }; use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions, - ParsedDescription, + ParsedDescription, UnusedDuplicate, }; use crate::target_checking::AllowedTargets; use crate::{AttrSuggestionStyle, AttributeParser, AttributeTemplate, EmitAttribute}; @@ -436,11 +436,7 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) { self.emit_lint( rustc_session::lint::builtin::UNUSED_ATTRIBUTES, - rustc_errors::lints::UnusedDuplicate { - this: unused_span, - other: used_span, - warning: false, - }, + UnusedDuplicate { this: unused_span, other: used_span, warning: false }, unused_span, ) } @@ -452,11 +448,7 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { ) { self.emit_lint( rustc_session::lint::builtin::UNUSED_ATTRIBUTES, - rustc_errors::lints::UnusedDuplicate { - this: unused_span, - other: used_span, - warning: true, - }, + UnusedDuplicate { this: unused_span, other: used_span, warning: true }, unused_span, ) } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 193ffe195fb6c..d1470d870d130 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1045,3 +1045,16 @@ pub(crate) struct AdditionalCommaSuggestion { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag("unused attribute")] +pub(crate) struct UnusedDuplicate { + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] + pub this: Span, + #[note("attribute also specified here")] + pub other: Span, + #[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" + )] + pub warning: bool, +} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 76cdb10f429c7..e9bb6701c38f1 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -79,7 +79,6 @@ mod diagnostic_impls; pub mod emitter; pub mod formatting; pub mod json; -pub mod lints; mod lock; pub mod markdown; pub mod timings; diff --git a/compiler/rustc_errors/src/lints.rs b/compiler/rustc_errors/src/lints.rs deleted file mode 100644 index 9c93a09bf764c..0000000000000 --- a/compiler/rustc_errors/src/lints.rs +++ /dev/null @@ -1,15 +0,0 @@ -use rustc_macros::Diagnostic; -use rustc_span::Span; - -#[derive(Diagnostic)] -#[diag("unused attribute")] -pub struct UnusedDuplicate { - #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] - pub this: Span, - #[note("attribute also specified here")] - pub other: Span, - #[warning( - "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" - )] - pub warning: bool, -} diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2bee8949c384e..d4a607f984f34 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -606,37 +606,61 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]); impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) { + let def_id = item.owner_id.def_id; + if !cx.effective_visibilities.is_reachable(def_id) { return; } - match item.kind { - hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) => {} + let is_generic = match item.kind { + hir::ItemKind::Struct(_, generics, _) + | hir::ItemKind::Union(_, generics, _) + | hir::ItemKind::Enum(_, generics, _) => !generics.params.is_empty(), _ => return, - } + }; + + let tcx = cx.tcx; // Avoid listing trait impls if the trait is allowed. - if cx.tcx.lint_level_spec_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()).is_allow() { + if tcx.lint_level_spec_at_node(MISSING_DEBUG_IMPLEMENTATIONS, item.hir_id()).is_allow() { return; } - let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else { return }; + let Some(debug) = tcx.get_diagnostic_item(sym::Debug) else { return }; - let has_impl = cx - .tcx - .non_blanket_impls_for_ty( - debug, - cx.tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip(), - ) + let ty = tcx.type_of(item.owner_id); + if tcx + .non_blanket_impls_for_ty(debug, ty.instantiate_identity().skip_norm_wip()) .next() - .is_some(); - if !has_impl { - cx.emit_span_lint( - MISSING_DEBUG_IMPLEMENTATIONS, - item.span, - BuiltinMissingDebugImpl { tcx: cx.tcx, def_id: debug }, - ); + .is_some() + { + return; } + + let infcx = tcx.infer_ctxt().build(cx.typing_mode()); + if is_generic { + let args = infcx.fresh_args_for_item(item.span, def_id.to_def_id()); + if infcx + .type_implements_trait_shallow( + debug, + ty.instantiate(tcx, args).skip_norm_wip(), + cx.param_env, + ) + .is_some() + { + return; + } + } else if infcx + .type_implements_trait(debug, [ty.instantiate_identity().skip_norm_wip()], cx.param_env) + .must_apply_modulo_regions() + { + return; + } + + cx.emit_span_lint( + MISSING_DEBUG_IMPLEMENTATIONS, + item.span, + BuiltinMissingDebugImpl { tcx: cx.tcx, def_id: debug }, + ); } } diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 51c56d777a751..e782414c62a0a 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,6 +1,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![cfg_attr(bootstrap, feature(result_option_map_or_default))] +#![cfg_attr(bootstrap, feature(strip_circumfix))] #![feature(error_iter)] #![feature(file_buffered)] #![feature(gen_blocks)] @@ -8,7 +9,6 @@ #![feature(min_specialization)] #![feature(never_type)] #![feature(proc_macro_internals)] -#![feature(strip_circumfix)] #![feature(trusted_len)] // tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index f85355330d6b8..8734d2cde8152 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -310,7 +310,9 @@ impl<'tcx> InstanceKind<'tcx> { pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { match *self { - InstanceKind::Item(def_id) | InstanceKind::Virtual(def_id, _) => { + InstanceKind::Item(def_id) + | InstanceKind::Virtual(def_id, _) + | InstanceKind::VTableShim(def_id) => { tcx.body_codegen_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) } InstanceKind::ClosureOnceShim { call_once: _, closure: _, track_caller } => { diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 3a726cbce8182..0c850b69ca7f1 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -689,7 +689,7 @@ pub(crate) struct MissingInInForLoop { #[primary_span] pub span: Span, #[subdiagnostic] - pub sub: MissingInInForLoopSub, + pub sub: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e414e10e84169..c81b3dd6ab5c0 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3086,18 +3086,41 @@ impl<'a> Parser<'a> { } fn error_missing_in_for_loop(&mut self) { - let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) { + let (span, sub) = if self.token.is_ident_named(sym::of) { // Possibly using JS syntax (#75311). let span = self.token.span; self.bump(); - (span, errors::MissingInInForLoopSub::InNotOf) + (span, Some(errors::MissingInInForLoopSub::InNotOf(span))) } else if self.eat(exp!(Eq)) { - (self.prev_token.span, errors::MissingInInForLoopSub::InNotEq) + let span = self.prev_token.span; + (span, Some(errors::MissingInInForLoopSub::InNotEq(span))) } else { - (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn) + let span = self.prev_token.span.between(self.token.span); + let sub = (!self.for_loop_head_has_in()) + .then_some(errors::MissingInInForLoopSub::AddIn(span)); + (span, sub) }; - self.dcx().emit_err(errors::MissingInInForLoop { span, sub: sub(span) }); + self.dcx().emit_err(errors::MissingInInForLoop { span, sub }); + } + + /// Whether the `for` loop header already contains an `in` before its body. + /// If it does, the binding is malformed (e.g. `for i i in 0..10`) rather + /// than missing `in`, so suggesting another `in` would just be invalid too. + fn for_loop_head_has_in(&self) -> bool { + let mut dist = 0; + loop { + let (is_in, is_end) = self.look_ahead(dist, |t| { + (t.is_keyword(kw::In), matches!(t.kind, token::OpenBrace | token::Eof)) + }); + if is_in { + return true; + } + if is_end { + return false; + } + dist += 1; + } } /// Parses a `while` or `while let` expression (`while` token already eaten). diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 2f9fa09c322bb..73ce5280f6dc8 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -727,7 +727,25 @@ fn build_options( } if let Some(tmod) = *tmod { let v = value.map_or(String::new(), ToOwned::to_owned); - collected_options.target_modifiers.insert(tmod, v); + + // Accumulate all the -Zsanitizer flags into a single target modifier. + match tmod { + OptionsTargetModifiers::UnstableOptions( + UnstableOptionsTargetModifiers::Sanitizer, + ) => { + collected_options + .target_modifiers + .entry(tmod) + .and_modify(|existing| { + existing.push(','); + existing.push_str(&v); + }) + .or_insert(v); + } + _ => { + collected_options.target_modifiers.insert(tmod, v); + } + } } if let Some(mitigation) = mitigation { collected_options.mitigations.reset_mitigation(*mitigation, index); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 9f1bfc018f3a2..8900687036d41 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,6 +11,7 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(strip_circumfix))] #![feature(associated_type_defaults)] #![feature(default_field_values)] #![feature(deref_patterns)] @@ -18,7 +19,6 @@ #![feature(iter_intersperse)] #![feature(iterator_try_reduce)] #![feature(never_type)] -#![feature(strip_circumfix)] #![feature(try_blocks)] #![feature(unwrap_infallible)] #![feature(yeet_expr)] diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index ae6cc46a22a84..ede5985a4211a 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2744,8 +2744,6 @@ impl [T] { /// # Examples /// /// ``` - /// #![feature(strip_circumfix)] - /// /// let v = &[10, 50, 40, 30]; /// assert_eq!(v.strip_circumfix(&[10], &[30]), Some(&[50, 40][..])); /// assert_eq!(v.strip_circumfix(&[10], &[40, 30]), Some(&[50][..])); @@ -2756,7 +2754,7 @@ impl [T] { /// assert_eq!(v.strip_circumfix(&[10, 50], &[]), Some(&[40, 30][..])); /// ``` #[must_use = "returns the subslice without modifying the original"] - #[unstable(feature = "strip_circumfix", issue = "147946")] + #[stable(feature = "strip_circumfix", since = "CURRENT_RUSTC_VERSION")] pub fn strip_circumfix(&self, prefix: &P, suffix: &S) -> Option<&[T]> where T: PartialEq, diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 9be44cd89de5e..68cdb69059f05 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2510,15 +2510,13 @@ impl str { /// # Examples /// /// ``` - /// #![feature(strip_circumfix)] - /// /// assert_eq!("bar:hello:foo".strip_circumfix("bar:", ":foo"), Some("hello")); /// assert_eq!("bar:foo".strip_circumfix("foo", "foo"), None); /// assert_eq!("foo:bar;".strip_circumfix("foo:", ';'), Some("bar")); /// ``` #[must_use = "this returns the remaining substring as a new slice, \ without modifying the original"] - #[unstable(feature = "strip_circumfix", issue = "147946")] + #[stable(feature = "strip_circumfix", since = "CURRENT_RUSTC_VERSION")] pub fn strip_circumfix(&self, prefix: P, suffix: S) -> Option<&str> where for<'a> S::Searcher<'a>: ReverseSearcher<'a>, diff --git a/tests/codegen-llvm/issues/issue-118306.rs b/tests/codegen-llvm/issues/issue-118306.rs index ea8b24317ff15..19623e17815d0 100644 --- a/tests/codegen-llvm/issues/issue-118306.rs +++ b/tests/codegen-llvm/issues/issue-118306.rs @@ -1,5 +1,8 @@ //@ compile-flags: -Copt-level=3 //@ only-x86_64 +//@ revisions: LLVM22 LLVM23 +//@ [LLVM22] max-llvm-major-version: 22 +//@ [LLVM23] min-llvm-version: 23 // Test for #118306. // Make sure we don't create `br` or `select` instructions. @@ -11,9 +14,13 @@ pub fn branchy(input: u64) -> u64 { // CHECK-LABEL: @branchy( // CHECK-NEXT: start: // CHECK-NEXT: [[_2:%.*]] = and i64 [[INPUT:%.*]], 3 - // CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} {{\[4 x i64\]|i64|\[8 x i8\]}}, ptr @switch.table.branchy{{(, i64 0)?}}, i64 [[_2]] - // CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]] - // CHECK-NEXT: ret i64 [[SWITCH_LOAD]] + // LLVM22-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} {{\[4 x i64\]|i64|\[8 x i8\]}}, ptr @switch.table.branchy{{(, i64 0)?}}, i64 [[_2]] + // LLVM22-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]] + // LLVM22-NEXT: ret i64 [[SWITCH_LOAD]] + // LLVM23-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} i8, ptr @switch.table.branchy, i64 [[_2]] + // LLVM23-NEXT: [[SWITCH_LOAD:%.*]] = load i8, ptr [[SWITCH_GEP]], align 1 + // LLVM23-NEXT: [[SWITCH_EXT:%.*]] = zext i8 [[SWITCH_LOAD]] to i64 + // LLVM23-NEXT: ret i64 [[SWITCH_EXT]] match input % 4 { 1 | 2 => 1, 3 => 2, diff --git a/tests/codegen-llvm/pow_known_base.rs b/tests/codegen-llvm/pow_known_base.rs index ea0e40515f9e4..f7e649ef089ea 100644 --- a/tests/codegen-llvm/pow_known_base.rs +++ b/tests/codegen-llvm/pow_known_base.rs @@ -1,4 +1,7 @@ //@ compile-flags: -Copt-level=3 +//@ revisions: LLVM22 LLVM23 +//@ [LLVM22] max-llvm-major-version: 22 +//@ [LLVM23] min-llvm-version: 23 // Test that `pow` can use a faster implementation when `base` is a // known power of two @@ -21,11 +24,16 @@ pub fn pow2(exp: u32) -> u32 { pub fn pow4(exp: u32) -> u32 { // CHECK: %[[ICMP1:.+]] = icmp slt i32 %exp, 0 // CHECK: %[[SHIFT_AMOUNT:.+]] = shl i32 %exp, 1 - // CHECK: %[[ICMP2:.+]] = icmp ult i32 %[[SHIFT_AMOUNT]], 32 - // CHECK: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] - // CHECK: %[[SEL:.+]] = select i1 %[[ICMP2]], i32 %[[POW]], i32 0 - // CHECK: %[[RET:.+]] = select i1 %[[ICMP1]], i32 0, i32 %[[SEL]] - // CHECK: ret i32 %[[RET]] + // LLVM22: %[[ICMP2:.+]] = icmp ult i32 %[[SHIFT_AMOUNT]], 32 + // LLVM22: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] + // LLVM22: %[[SEL:.+]] = select i1 %[[ICMP2]], i32 %[[POW]], i32 0 + // LLVM22: %[[RET:.+]] = select i1 %[[ICMP1]], i32 0, i32 %[[SEL]] + // LLVM22: ret i32 %[[RET]] + // LLVM23: %[[ICMP2:.+]] = icmp ugt i32 %[[SHIFT_AMOUNT]], 31 + // LLVM23: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] + // LLVM23: %[[COND:.+]] = or i1 %[[ICMP1]], %[[ICMP2]] + // LLVM23: %[[RET:.+]] = select i1 %[[COND]], i32 0, i32 %[[POW]] + // LLVM23: ret i32 %[[RET]] 4u32.pow(exp) } @@ -35,11 +43,16 @@ pub fn pow4(exp: u32) -> u32 { pub fn pow16(exp: u32) -> u32 { // CHECK: %[[ICMP1:.+]] = icmp ugt i32 %exp, 1073741823 // CHECK: %[[SHIFT_AMOUNT:.+]] = shl i32 %exp, 2 - // CHECK: %[[ICMP2:.+]] = icmp ult i32 %[[SHIFT_AMOUNT]], 32 - // CHECK: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] - // CHECK: %[[SEL:.+]] = select i1 %[[ICMP2]], i32 %[[POW]], i32 0 - // CHECK: %[[RET:.+]] = select i1 %[[ICMP1]], i32 0, i32 %[[SEL]] - // CHECK: ret i32 %[[RET]] + // LLVM22: %[[ICMP2:.+]] = icmp ult i32 %[[SHIFT_AMOUNT]], 32 + // LLVM22: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] + // LLVM22: %[[SEL:.+]] = select i1 %[[ICMP2]], i32 %[[POW]], i32 0 + // LLVM22: %[[RET:.+]] = select i1 %[[ICMP1]], i32 0, i32 %[[SEL]] + // LLVM22: ret i32 %[[RET]] + // LLVM23: %[[ICMP2:.+]] = icmp ugt i32 %[[SHIFT_AMOUNT]], 31 + // LLVM23: %[[POW:.+]] = shl nuw i32 1, %[[SHIFT_AMOUNT]] + // LLVM23: %[[COND:.+]] = or i1 %[[ICMP1]], %[[ICMP2]] + // LLVM23: %[[RET:.+]] = select i1 %[[COND]], i32 0, i32 %[[POW]] + // LLVM23: ret i32 %[[RET]] 16u32.pow(exp) } diff --git a/tests/codegen-llvm/sanitizer/multiple-sanitizers.rs b/tests/codegen-llvm/sanitizer/multiple-sanitizers.rs new file mode 100644 index 0000000000000..862999e7ac026 --- /dev/null +++ b/tests/codegen-llvm/sanitizer/multiple-sanitizers.rs @@ -0,0 +1,18 @@ +// Verifies that multiple compatible sanitizers (CFI + SafeStack) can be enabled together +// and their target modifiers accumulate instead of overwriting. +// +//@ only-x86_64 +//@ only-linux +//@ needs-sanitizer-cfi +//@ needs-sanitizer-safestack +//@ compile-flags: -Zsanitizer=cfi -Zsanitizer=safestack -Clto -Ccodegen-units=1 -C unsafe-allow-abi-mismatch=sanitizer + +#![crate_type = "lib"] + +// CHECK: ; Function Attrs:{{.*}}safestack +// CHECK: define{{.*}}foo{{.*}}!type +pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { + f(arg) +} + +// CHECK: attributes #0 = {{.*}}safestack{{.*}} diff --git a/tests/incremental/delegation-ice-155729.rs b/tests/incremental/delegation-ice-155729.rs new file mode 100644 index 0000000000000..5316e7b66cd5b --- /dev/null +++ b/tests/incremental/delegation-ice-155729.rs @@ -0,0 +1,14 @@ +//@ revisions: bpass + +#![feature(fn_delegation)] + +pub mod to_reuse { + pub fn bar() {} +} + +mod a { + use to_reuse; + reuse to_reuse::bar; +} + +fn main() {} diff --git a/tests/ui/lint/missing-debug-implementations-lint/impl-debug-for-alias-type.rs b/tests/ui/lint/missing-debug-implementations-lint/impl-debug-for-alias-type.rs new file mode 100644 index 0000000000000..5222df24b61a6 --- /dev/null +++ b/tests/ui/lint/missing-debug-implementations-lint/impl-debug-for-alias-type.rs @@ -0,0 +1,22 @@ +//@ check-pass + +#![feature(lazy_type_alias)] +#![deny(missing_debug_implementations)] + +pub struct Local; + +pub type Alias = Local; + +impl std::fmt::Debug for Alias { + fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(()) } +} + +pub struct Generic(T); + +pub type GenericAlias = Generic; + +impl std::fmt::Debug for GenericAlias { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(()) } +} + +fn main() {} diff --git a/tests/ui/lint/missing-debug-implementations-lint/impl-debug-for-project.rs b/tests/ui/lint/missing-debug-implementations-lint/impl-debug-for-project.rs new file mode 100644 index 0000000000000..ecdca8c211382 --- /dev/null +++ b/tests/ui/lint/missing-debug-implementations-lint/impl-debug-for-project.rs @@ -0,0 +1,20 @@ +//@ check-pass + +#![deny(missing_debug_implementations)] + +pub struct Local; + +impl std::fmt::Debug for ::Output { + fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(()) } +} + +pub trait Identity { type Output; } +impl Identity for T { type Output = T; } + +pub struct Generic(T); + +impl std::fmt::Debug for as Identity>::Output { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(()) } +} + +fn main() {} diff --git a/tests/ui/lint/missing-debug-implementations-lint.rs b/tests/ui/lint/missing-debug-implementations-lint/missing-debug-implementations-lint.rs similarity index 100% rename from tests/ui/lint/missing-debug-implementations-lint.rs rename to tests/ui/lint/missing-debug-implementations-lint/missing-debug-implementations-lint.rs diff --git a/tests/ui/lint/missing-debug-implementations-lint.stderr b/tests/ui/lint/missing-debug-implementations-lint/missing-debug-implementations-lint.stderr similarity index 100% rename from tests/ui/lint/missing-debug-implementations-lint.stderr rename to tests/ui/lint/missing-debug-implementations-lint/missing-debug-implementations-lint.stderr diff --git a/tests/ui/suggestions/for-loop-no-spurious-in-suggestion.rs b/tests/ui/suggestions/for-loop-no-spurious-in-suggestion.rs new file mode 100644 index 0000000000000..142f925665881 --- /dev/null +++ b/tests/ui/suggestions/for-loop-no-spurious-in-suggestion.rs @@ -0,0 +1,9 @@ +// Regression test for https://github.com/rust-lang/rust/issues/103561: when the +// `for` loop header already contains an `in`, a missing `in` is not the problem, +// so we must not suggest inserting another one (which would not compile). + +fn main() { + for i i in 0..10 {} + //~^ ERROR missing `in` in `for` loop + //~| ERROR expected `{`, found keyword `in` +} diff --git a/tests/ui/suggestions/for-loop-no-spurious-in-suggestion.stderr b/tests/ui/suggestions/for-loop-no-spurious-in-suggestion.stderr new file mode 100644 index 0000000000000..472ee7d9ddca2 --- /dev/null +++ b/tests/ui/suggestions/for-loop-no-spurious-in-suggestion.stderr @@ -0,0 +1,14 @@ +error: missing `in` in `for` loop + --> $DIR/for-loop-no-spurious-in-suggestion.rs:6:10 + | +LL | for i i in 0..10 {} + | ^ + +error: expected `{`, found keyword `in` + --> $DIR/for-loop-no-spurious-in-suggestion.rs:6:13 + | +LL | for i i in 0..10 {} + | ^^ expected `{` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr index 440a91c7707f8..44a2c24b2324e 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_both.stderr @@ -1,5 +1,5 @@ error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` - --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + --> $DIR/sanitizers-safestack-and-kcfi.rs:18:1 | LL | #![feature(no_core)] | ^ diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr index 6cdd7facc3781..e951b36969b78 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_kcfi.stderr @@ -1,5 +1,5 @@ error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` - --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + --> $DIR/sanitizers-safestack-and-kcfi.rs:18:1 | LL | #![feature(no_core)] | ^ diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr index ecfbcace39fe5..9fd2738ef45ab 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.missed_safestack.stderr @@ -1,5 +1,5 @@ error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` - --> $DIR/sanitizers-safestack-and-kcfi.rs:16:1 + --> $DIR/sanitizers-safestack-and-kcfi.rs:18:1 | LL | #![feature(no_core)] | ^ diff --git a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs index 6c3ceb7e91008..eb4b4d6194228 100644 --- a/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs +++ b/tests/ui/target_modifiers/sanitizers-safestack-and-kcfi.rs @@ -4,14 +4,16 @@ //@ aux-build:safestack-and-kcfi.rs //@ compile-flags: -Cpanic=abort -//@ revisions: good good_reverted missed_safestack missed_kcfi missed_both +//@ revisions: good good_reverted good_multiple missed_safestack missed_kcfi missed_both //@[good] compile-flags: -Zsanitizer=safestack,kcfi //@[good_reverted] compile-flags: -Zsanitizer=kcfi,safestack +//@[good_multiple] compile-flags: -Zsanitizer=safestack -Zsanitizer=kcfi //@[missed_safestack] compile-flags: -Zsanitizer=kcfi //@[missed_kcfi] compile-flags: -Zsanitizer=safestack // [missed_both] no additional compile-flags: //@[good] check-pass //@[good_reverted] check-pass +//@[good_multiple] check-pass #![feature(no_core)] //[missed_safestack]~^ ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizers_safestack_and_kcfi` diff --git a/tests/ui/unsized-locals/track-caller-vtable-shim.rs b/tests/ui/unsized-locals/track-caller-vtable-shim.rs new file mode 100644 index 0000000000000..575f48249e331 --- /dev/null +++ b/tests/ui/unsized-locals/track-caller-vtable-shim.rs @@ -0,0 +1,21 @@ +//@ run-pass + +#![feature(unsized_fn_params)] +#![allow(internal_features)] + +trait TrackedByValue { + #[track_caller] + fn consume(self, expected_line: u32); +} + +impl TrackedByValue for u8 { + fn consume(self, expected_line: u32) { + assert_eq!(self, 7); + assert_eq!(std::panic::Location::caller().line(), expected_line); + } +} + +fn main() { + let obj = Box::new(7_u8) as Box; + obj.consume(line!()); +}