From 81a6f189408b71b452a9804818f2cd50d2ed9108 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Wed, 9 Jul 2025 15:24:28 +0500 Subject: added error for invalid char cast --- compiler/rustc_lint/src/lints.rs | 14 +++++++++++ compiler/rustc_lint/src/types/literal.rs | 42 ++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 10 deletions(-) (limited to 'compiler/rustc_lint/src') diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 21148833eaf..19989cbcce6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1746,6 +1746,20 @@ pub(crate) struct OverflowingLiteral<'a> { pub lit: String, } +#[derive(LintDiagnostic)] +#[diag(lint_surrogate_char_cast)] +#[note] +pub(crate) struct SurrogateCharCast { + pub literal: u128, +} + +#[derive(LintDiagnostic)] +#[diag(lint_too_large_char_cast)] +#[note] +pub(crate) struct TooLargeCharCast { + pub literal: u128, +} + #[derive(LintDiagnostic)] #[diag(lint_uses_power_alignment)] pub(crate) struct UsesPowerAlignment; diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index d44f45177bd..2bac58ba23d 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -12,7 +12,7 @@ use crate::context::LintContext; use crate::lints::{ OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, - RangeEndpointOutOfRange, UseInclusiveRange, + RangeEndpointOutOfRange, SurrogateCharCast, TooLargeCharCast, UseInclusiveRange, }; use crate::types::{OVERFLOWING_LITERALS, TypeLimits}; @@ -38,12 +38,18 @@ fn lint_overflowing_range_endpoint<'tcx>( // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. - let Node::ExprField(field) = cx.tcx.parent_hir_node(hir_id) else { return false }; - let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else { return false }; + let Node::ExprField(field) = cx.tcx.parent_hir_node(hir_id) else { + return false; + }; + let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else { + return false; + }; if !is_range_literal(struct_expr) { return false; }; - let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else { return false }; + let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else { + return false; + }; // We can suggest using an inclusive range // (`..=`) instead only if it is the `end` that is @@ -61,7 +67,9 @@ fn lint_overflowing_range_endpoint<'tcx>( }; let sub_sugg = if span.lo() == lit_span.lo() { - let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false }; + let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { + return false; + }; UseInclusiveRange::WithoutParen { sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()), start, @@ -316,11 +324,25 @@ fn lint_uint_literal<'tcx>( match par_e.kind { hir::ExprKind::Cast(..) => { if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() { - cx.emit_span_lint( - OVERFLOWING_LITERALS, - par_e.span, - OnlyCastu8ToChar { span: par_e.span, literal: lit_val }, - ); + if lit_val > 0x10FFFF { + cx.emit_span_lint( + OVERFLOWING_LITERALS, + par_e.span, + TooLargeCharCast { literal: lit_val }, + ); + } else if (0xD800..=0xDFFF).contains(&lit_val) { + cx.emit_span_lint( + OVERFLOWING_LITERALS, + par_e.span, + SurrogateCharCast { literal: lit_val }, + ); + } else { + cx.emit_span_lint( + OVERFLOWING_LITERALS, + par_e.span, + OnlyCastu8ToChar { span: par_e.span, literal: lit_val }, + ); + } return; } } -- cgit 1.4.1-3-g733a5 From 553074431875701f66107049339dc1e67f0cdeba Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 10 Jul 2025 18:36:22 -0400 Subject: Reword mismatched-lifetime-syntaxes text based on feedback Key changes include: - Removal of the word "syntax" from the lint message. More accurately, it could have been something like "syntax group" or "syntax category", but avoiding it completely is easier. - The primary lint message now reflects exactly which mismatch is occurring, instead of trying to be general. A new `help` line is general across the mismatch kinds. - Suggestions have been reduced to be more minimal, no longer also changing non-idiomatic but unrelated aspects. - Suggestion text no longer mentions changes when those changes don't occur in that specific suggestion. --- compiler/rustc_lint/messages.ftl | 53 ++- compiler/rustc_lint/src/lib.rs | 2 +- compiler/rustc_lint/src/lifetime_syntax.rs | 149 ++++-- compiler/rustc_lint/src/lints.rs | 72 ++- src/tools/clippy/tests/ui/ptr_arg.rs | 2 +- src/tools/clippy/tests/ui/ptr_arg.stderr | 11 +- .../type-dependent/issue-71348.full.stderr | 11 +- .../const-generics/type-dependent/issue-71348.rs | 2 +- .../ui/impl-trait/rpit-assoc-pair-with-lifetime.rs | 2 +- .../rpit-assoc-pair-with-lifetime.stderr | 7 +- .../example-from-issue48686.rs | 2 +- .../example-from-issue48686.stderr | 9 +- .../missing-lifetime-kind.rs | 8 +- .../missing-lifetime-kind.stderr | 36 +- .../not-tied-to-crate.rs | 4 +- .../not-tied-to-crate.stderr | 18 +- .../mismatched-lifetime-syntaxes-details/static.rs | 8 +- .../static.stderr | 36 +- tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs | 104 +++-- .../lifetimes/mismatched-lifetime-syntaxes.stderr | 497 ++++++++++++--------- .../self/elision/ignore-non-reference-lifetimes.rs | 4 +- .../elision/ignore-non-reference-lifetimes.stderr | 18 +- tests/ui/self/self_lifetime-async.rs | 4 +- tests/ui/self/self_lifetime-async.stderr | 18 +- tests/ui/self/self_lifetime.rs | 4 +- tests/ui/self/self_lifetime.stderr | 18 +- 26 files changed, 680 insertions(+), 419 deletions(-) (limited to 'compiler/rustc_lint/src') diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 8d9f2385b71..5fece464270 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -508,27 +508,50 @@ lint_metavariable_still_repeating = variable `{$name}` is still repeating at thi lint_metavariable_wrong_operator = meta-variable repeats with different Kleene operator -lint_mismatched_lifetime_syntaxes = - lifetime flowing from input to output with different syntax can be confusing - .label_mismatched_lifetime_syntaxes_inputs = - {$n_inputs -> - [one] this lifetime flows - *[other] these lifetimes flow - } to the output - .label_mismatched_lifetime_syntaxes_outputs = - the {$n_outputs -> - [one] lifetime gets - *[other] lifetimes get - } resolved as `{$lifetime_name}` +lint_mismatched_lifetime_syntaxes_eliding_while_named = + eliding a lifetime that's named elsewhere is confusing + +lint_mismatched_lifetime_syntaxes_help = + the same lifetime is referred to in inconsistent ways, making the signature confusing + +lint_mismatched_lifetime_syntaxes_hiding_and_eliding_while_named = + hiding or eliding a lifetime that's named elsewhere is confusing + +lint_mismatched_lifetime_syntaxes_hiding_while_elided = + hiding a lifetime that's elided elsewhere is confusing + +lint_mismatched_lifetime_syntaxes_hiding_while_named = + hiding a lifetime that's named elsewhere is confusing + +lint_mismatched_lifetime_syntaxes_input_elided = + the lifetime is elided here + +lint_mismatched_lifetime_syntaxes_input_hidden = + the lifetime is hidden here + +lint_mismatched_lifetime_syntaxes_input_named = + the lifetime is named here + +lint_mismatched_lifetime_syntaxes_output_elided = + the same lifetime is elided here + +lint_mismatched_lifetime_syntaxes_output_hidden = + the same lifetime is hidden here + +lint_mismatched_lifetime_syntaxes_output_named = + the same lifetime is named here lint_mismatched_lifetime_syntaxes_suggestion_explicit = - one option is to consistently use `{$lifetime_name}` + consistently use `{$lifetime_name}` lint_mismatched_lifetime_syntaxes_suggestion_implicit = - one option is to consistently remove the lifetime + remove the lifetime name from references lint_mismatched_lifetime_syntaxes_suggestion_mixed = - one option is to remove the lifetime for references and use the anonymous lifetime for paths + remove the lifetime name from references and use `'_` for type paths + +lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths = + use `'_` for type paths lint_missing_unsafe_on_extern = extern blocks should be unsafe .suggestion = needs `unsafe` before the extern keyword diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 419124d5144..f06757b3c23 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -55,7 +55,7 @@ mod invalid_from_utf8; mod late; mod let_underscore; mod levels; -mod lifetime_syntax; +pub mod lifetime_syntax; mod lints; mod macro_expr_fragment_specifier_2024_migration; mod map_unit_fn; diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 5465968e984..2a5a34cdc6e 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -140,43 +140,115 @@ fn report_mismatches<'tcx>( } } -fn lifetimes_use_matched_syntax(input_info: &[Info<'_>], output_info: &[Info<'_>]) -> bool { - // Categorize lifetimes into source/syntax buckets. - let mut n_hidden = 0; - let mut n_elided = 0; - let mut n_named = 0; +#[derive(Debug, Copy, Clone, PartialEq)] +enum LifetimeSyntaxCategory { + Hidden, + Elided, + Named, +} - for info in input_info.iter().chain(output_info) { +impl LifetimeSyntaxCategory { + fn new(syntax_source: (hir::LifetimeSyntax, LifetimeSource)) -> Option { use LifetimeSource::*; use hir::LifetimeSyntax::*; - let syntax_source = (info.lifetime.syntax, info.lifetime.source); - match syntax_source { - // Ignore any other kind of lifetime. - (_, Other) => continue, - // E.g. `&T`. - (Implicit, Reference | OutlivesBound | PreciseCapturing) | + (Implicit, Reference) | // E.g. `&'_ T`. - (ExplicitAnonymous, Reference | OutlivesBound | PreciseCapturing) | + (ExplicitAnonymous, Reference) | // E.g. `ContainsLifetime<'_>`. - (ExplicitAnonymous, Path { .. }) => n_elided += 1, + (ExplicitAnonymous, Path { .. }) | + // E.g. `+ '_`, `+ use<'_>`. + (ExplicitAnonymous, OutlivesBound | PreciseCapturing) => { + Some(Self::Elided) + } // E.g. `ContainsLifetime`. - (Implicit, Path { .. }) => n_hidden += 1, + (Implicit, Path { .. }) => { + Some(Self::Hidden) + } // E.g. `&'a T`. - (ExplicitBound, Reference | OutlivesBound | PreciseCapturing) | + (ExplicitBound, Reference) | // E.g. `ContainsLifetime<'a>`. - (ExplicitBound, Path { .. }) => n_named += 1, - }; + (ExplicitBound, Path { .. }) | + // E.g. `+ 'a`, `+ use<'a>`. + (ExplicitBound, OutlivesBound | PreciseCapturing) => { + Some(Self::Named) + } + + (Implicit, OutlivesBound | PreciseCapturing) | + (_, Other) => { + None + } + } + } +} + +#[derive(Debug, Default)] +pub struct LifetimeSyntaxCategories { + pub hidden: T, + pub elided: T, + pub named: T, +} + +impl LifetimeSyntaxCategories { + fn select(&mut self, category: LifetimeSyntaxCategory) -> &mut T { + use LifetimeSyntaxCategory::*; + + match category { + Elided => &mut self.elided, + Hidden => &mut self.hidden, + Named => &mut self.named, + } + } +} + +impl LifetimeSyntaxCategories> { + pub fn len(&self) -> LifetimeSyntaxCategories { + LifetimeSyntaxCategories { + hidden: self.hidden.len(), + elided: self.elided.len(), + named: self.named.len(), + } + } + + pub fn flatten(&self) -> impl Iterator { + let Self { hidden, elided, named } = self; + [hidden.iter(), elided.iter(), named.iter()].into_iter().flatten() + } +} + +impl std::ops::Add for LifetimeSyntaxCategories { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { + hidden: self.hidden + rhs.hidden, + elided: self.elided + rhs.elided, + named: self.named + rhs.named, + } + } +} + +fn lifetimes_use_matched_syntax(input_info: &[Info<'_>], output_info: &[Info<'_>]) -> bool { + let mut syntax_counts = LifetimeSyntaxCategories::::default(); + + for info in input_info.iter().chain(output_info) { + if let Some(category) = info.lifetime_syntax_category() { + *syntax_counts.select(category) += 1; + } } - let syntax_counts = (n_hidden, n_elided, n_named); tracing::debug!(?syntax_counts); - matches!(syntax_counts, (_, 0, 0) | (0, _, 0) | (0, 0, _)) + matches!( + syntax_counts, + LifetimeSyntaxCategories { hidden: _, elided: 0, named: 0 } + | LifetimeSyntaxCategories { hidden: 0, elided: _, named: 0 } + | LifetimeSyntaxCategories { hidden: 0, elided: 0, named: _ } + ) } fn emit_mismatch_diagnostic<'tcx>( @@ -238,7 +310,7 @@ fn emit_mismatch_diagnostic<'tcx>( use LifetimeSource::*; use hir::LifetimeSyntax::*; - let syntax_source = (info.lifetime.syntax, info.lifetime.source); + let syntax_source = info.syntax_source(); if let (_, Other) = syntax_source { // Ignore any other kind of lifetime. @@ -259,7 +331,6 @@ fn emit_mismatch_diagnostic<'tcx>( // E.g. `&'_ T`. (ExplicitAnonymous, Reference) => { suggest_change_to_implicit.push(info); - suggest_change_to_mixed_implicit.push(info); suggest_change_to_explicit_bound.push(info); } @@ -319,12 +390,22 @@ fn emit_mismatch_diagnostic<'tcx>( } } + let categorize = |infos: &[Info<'_>]| { + let mut categories = LifetimeSyntaxCategories::>::default(); + for info in infos { + if let Some(category) = info.lifetime_syntax_category() { + categories.select(category).push(info.reporting_span()); + } + } + categories + }; + + let inputs = categorize(input_info); + let outputs = categorize(output_info); + let make_implicit_suggestions = |infos: &[&Info<'_>]| infos.iter().map(|i| i.removing_span()).collect::>(); - let inputs = input_info.iter().map(|info| info.reporting_span()).collect(); - let outputs = output_info.iter().map(|info| info.reporting_span()).collect(); - let explicit_bound_suggestion = bound_lifetime.map(|info| { build_mismatch_suggestion(info.lifetime_name(), &suggest_change_to_explicit_bound) }); @@ -399,8 +480,6 @@ fn emit_mismatch_diagnostic<'tcx>( ?explicit_anonymous_suggestion, ); - let lifetime_name = bound_lifetime.map(|info| info.lifetime_name()).unwrap_or("'_").to_owned(); - // We can produce a number of suggestions which may overwhelm // the user. Instead, we order the suggestions based on Rust // idioms. The "best" choice is shown to the user and the @@ -413,8 +492,8 @@ fn emit_mismatch_diagnostic<'tcx>( cx.emit_span_lint( MISMATCHED_LIFETIME_SYNTAXES, - Vec::clone(&inputs), - lints::MismatchedLifetimeSyntaxes { lifetime_name, inputs, outputs, suggestions }, + inputs.flatten().copied().collect::>(), + lints::MismatchedLifetimeSyntaxes { inputs, outputs, suggestions }, ); } @@ -422,12 +501,12 @@ fn build_mismatch_suggestion( lifetime_name: &str, infos: &[&Info<'_>], ) -> lints::MismatchedLifetimeSyntaxesSuggestion { - let lifetime_name_sugg = lifetime_name.to_owned(); + let lifetime_name = lifetime_name.to_owned(); let suggestions = infos.iter().map(|info| info.suggestion(&lifetime_name)).collect(); lints::MismatchedLifetimeSyntaxesSuggestion::Explicit { - lifetime_name_sugg, + lifetime_name, suggestions, tool_only: false, } @@ -441,6 +520,14 @@ struct Info<'tcx> { } impl<'tcx> Info<'tcx> { + fn syntax_source(&self) -> (hir::LifetimeSyntax, LifetimeSource) { + (self.lifetime.syntax, self.lifetime.source) + } + + fn lifetime_syntax_category(&self) -> Option { + LifetimeSyntaxCategory::new(self.syntax_source()) + } + fn lifetime_name(&self) -> &str { self.lifetime.ident.as_str() } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 21148833eaf..ef18b0ac20b 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -21,6 +21,7 @@ use rustc_span::{Ident, MacroRulesNormalizedIdent, Span, Symbol, sym}; use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds}; use crate::errors::{OverruledAttributeSub, RequestedLevel}; +use crate::lifetime_syntax::LifetimeSyntaxCategories; use crate::{LateContext, fluent_generated as fluent}; // array_into_iter.rs @@ -3194,30 +3195,59 @@ pub(crate) struct ReservedMultihash { #[derive(Debug)] pub(crate) struct MismatchedLifetimeSyntaxes { - pub lifetime_name: String, - pub inputs: Vec, - pub outputs: Vec, + pub inputs: LifetimeSyntaxCategories>, + pub outputs: LifetimeSyntaxCategories>, pub suggestions: Vec, } impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSyntaxes { fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>) { - diag.primary_message(fluent::lint_mismatched_lifetime_syntaxes); + let counts = self.inputs.len() + self.outputs.len(); + let message = match counts { + LifetimeSyntaxCategories { hidden: 0, elided: 0, named: 0 } => { + panic!("No lifetime mismatch detected") + } + + LifetimeSyntaxCategories { hidden: _, elided: _, named: 0 } => { + fluent::lint_mismatched_lifetime_syntaxes_hiding_while_elided + } + + LifetimeSyntaxCategories { hidden: _, elided: 0, named: _ } => { + fluent::lint_mismatched_lifetime_syntaxes_hiding_while_named + } + + LifetimeSyntaxCategories { hidden: 0, elided: _, named: _ } => { + fluent::lint_mismatched_lifetime_syntaxes_eliding_while_named + } - diag.arg("lifetime_name", self.lifetime_name); + LifetimeSyntaxCategories { hidden: _, elided: _, named: _ } => { + fluent::lint_mismatched_lifetime_syntaxes_hiding_and_eliding_while_named + } + }; + diag.primary_message(message); - diag.arg("n_inputs", self.inputs.len()); - for input in self.inputs { - let a = diag.eagerly_translate(fluent::lint_label_mismatched_lifetime_syntaxes_inputs); - diag.span_label(input, a); + for s in self.inputs.hidden { + diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_hidden); + } + for s in self.inputs.elided { + diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_elided); + } + for s in self.inputs.named { + diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_input_named); } - diag.arg("n_outputs", self.outputs.len()); - for output in self.outputs { - let a = diag.eagerly_translate(fluent::lint_label_mismatched_lifetime_syntaxes_outputs); - diag.span_label(output, a); + for s in self.outputs.hidden { + diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_hidden); + } + for s in self.outputs.elided { + diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_elided); } + for s in self.outputs.named { + diag.span_label(s, fluent::lint_mismatched_lifetime_syntaxes_output_named); + } + + diag.help(fluent::lint_mismatched_lifetime_syntaxes_help); let mut suggestions = self.suggestions.into_iter(); if let Some(s) = suggestions.next() { @@ -3245,7 +3275,7 @@ pub(crate) enum MismatchedLifetimeSyntaxesSuggestion { }, Explicit { - lifetime_name_sugg: String, + lifetime_name: String, suggestions: Vec<(Span, String)>, tool_only: bool, }, @@ -3285,6 +3315,12 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } Mixed { implicit_suggestions, explicit_anonymous_suggestions, tool_only } => { + let message = if implicit_suggestions.is_empty() { + fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths + } else { + fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed + }; + let implicit_suggestions = implicit_suggestions.into_iter().map(|s| (s, String::new())); @@ -3292,19 +3328,19 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { implicit_suggestions.chain(explicit_anonymous_suggestions).collect(); diag.multipart_suggestion_with_style( - fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed, + message, suggestions, Applicability::MaybeIncorrect, style(tool_only), ); } - Explicit { lifetime_name_sugg, suggestions, tool_only } => { - diag.arg("lifetime_name_sugg", lifetime_name_sugg); + Explicit { lifetime_name, suggestions, tool_only } => { + diag.arg("lifetime_name", lifetime_name); let msg = diag.eagerly_translate( fluent::lint_mismatched_lifetime_syntaxes_suggestion_explicit, ); - diag.remove_arg("lifetime_name_sugg"); + diag.remove_arg("lifetime_name"); diag.multipart_suggestion_with_style( msg, suggestions, diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs index 65f3f05d6cb..578641e910d 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.rs +++ b/src/tools/clippy/tests/ui/ptr_arg.rs @@ -312,7 +312,7 @@ mod issue_9218 { // Inferred to be `&'a str`, afaik. fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { - //~^ ERROR: lifetime flowing from input to output with different syntax + //~^ ERROR: eliding a lifetime that's named elsewhere is confusing todo!() } } diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index 600343754e1..fd9ceddfe11 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -231,18 +231,19 @@ error: writing `&String` instead of `&str` involves a new object where a slice w LL | fn good(v1: &String, v2: &String) { | ^^^^^^^ help: change this to: `&str` -error: lifetime flowing from input to output with different syntax can be confusing +error: eliding a lifetime that's named elsewhere is confusing --> tests/ui/ptr_arg.rs:314:36 | LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { - | ^^ ^^ ---- the lifetime gets resolved as `'a` + | ^^ ^^ ---- the same lifetime is elided here | | | - | | these lifetimes flow to the output - | these lifetimes flow to the output + | | the lifetime is named here + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `-D mismatched-lifetime-syntaxes` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(mismatched_lifetime_syntaxes)]` -help: one option is to consistently use `'a` +help: consistently use `'a` | LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &'a str { | ++ diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index f68fdb3b651..32fa46b92b3 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -1,14 +1,15 @@ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: hiding a lifetime that's named elsewhere is confusing --> $DIR/issue-71348.rs:18:40 | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target - | ^^ -- ------------------------ the lifetimes get resolved as `'a` + | ^^ -- ------------------------ the same lifetime is hidden here | | | - | | the lifetimes get resolved as `'a` - | this lifetime flows to the output + | | the same lifetime is named here + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default -help: one option is to consistently use `'a` +help: consistently use `'a` | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target | +++ diff --git a/tests/ui/const-generics/type-dependent/issue-71348.rs b/tests/ui/const-generics/type-dependent/issue-71348.rs index c6563c80305..9053f362ce4 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.rs +++ b/tests/ui/const-generics/type-dependent/issue-71348.rs @@ -17,7 +17,7 @@ trait Get<'a, const N: &'static str> { impl Foo { fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target //[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter - //[full]~^^ WARNING lifetime flowing from input to output with different syntax + //[full]~^^ WARNING hiding a lifetime that's named elsewhere is confusing where Self: Get<'a, N>, { diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs index 1ac3c593dbe..1b8a5d4ca99 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.rs @@ -1,7 +1,7 @@ //@ check-pass pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing v.into_iter() } diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index b9d8674992c..3651226e0c3 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -1,11 +1,12 @@ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:31 | LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { - | ^^ this lifetime flows to the output ---- the lifetime gets resolved as `'a` + | ^^ the lifetime is named here ---- the same lifetime is elided here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default -help: one option is to consistently use `'a` +help: consistently use `'a` | LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { | ++ diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.rs index 1804003d367..9162a38f510 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.rs +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.rs @@ -4,7 +4,7 @@ struct Foo; impl Foo { pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing unsafe { &mut *(x as *mut _) } } } diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr index 7c7411651d0..5a7a5a6ebf9 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr @@ -1,17 +1,18 @@ -error: lifetime flowing from input to output with different syntax can be confusing +error: eliding a lifetime that's named elsewhere is confusing --> $DIR/example-from-issue48686.rs:6:21 | LL | pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { - | ^^^^^^^ ------- the lifetime gets resolved as `'static` + | ^^^^^^^ ------- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing note: the lint level is defined here --> $DIR/example-from-issue48686.rs:1:9 | LL | #![deny(mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: one option is to consistently use `'static` +help: consistently use `'static` | LL | pub fn get_mut(&'static self, x: &mut u8) -> &'static mut u8 { | +++++++ diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.rs index 3d5aab5c829..ecc790be5a0 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.rs +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.rs @@ -1,26 +1,26 @@ #![deny(mismatched_lifetime_syntaxes)] fn ampersand<'a>(x: &'a u8) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing x } struct Brackets<'a>(&'a u8); fn brackets<'a>(x: &'a u8) -> Brackets { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing Brackets(x) } struct Comma<'a, T>(&'a T); fn comma<'a>(x: &'a u8) -> Comma { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing Comma(x) } fn underscore<'a>(x: &'a u8) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing x } diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr index 681b3c97052..af56a0a0ea5 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr @@ -1,56 +1,60 @@ -error: lifetime flowing from input to output with different syntax can be confusing +error: eliding a lifetime that's named elsewhere is confusing --> $DIR/missing-lifetime-kind.rs:3:22 | LL | fn ampersand<'a>(x: &'a u8) -> &u8 { - | ^^ --- the lifetime gets resolved as `'a` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing note: the lint level is defined here --> $DIR/missing-lifetime-kind.rs:1:9 | LL | #![deny(mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: one option is to consistently use `'a` +help: consistently use `'a` | LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { | ++ -error: lifetime flowing from input to output with different syntax can be confusing +error: hiding a lifetime that's named elsewhere is confusing --> $DIR/missing-lifetime-kind.rs:10:21 | LL | fn brackets<'a>(x: &'a u8) -> Brackets { - | ^^ -------- the lifetime gets resolved as `'a` + | ^^ -------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing +error: hiding a lifetime that's named elsewhere is confusing --> $DIR/missing-lifetime-kind.rs:17:18 | LL | fn comma<'a>(x: &'a u8) -> Comma { - | ^^ --------- the lifetime gets resolved as `'a` + | ^^ --------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { | +++ -error: lifetime flowing from input to output with different syntax can be confusing +error: eliding a lifetime that's named elsewhere is confusing --> $DIR/missing-lifetime-kind.rs:22:23 | LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn underscore<'a>(x: &'a u8) -> &'_ u8 { LL + fn underscore<'a>(x: &'a u8) -> &'a u8 { diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.rs index cc398ab7888..449b2a3c0a8 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.rs +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.rs @@ -6,13 +6,13 @@ #[warn(mismatched_lifetime_syntaxes)] mod foo { fn bar(x: &'static u8) -> &u8 { - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing x } #[deny(mismatched_lifetime_syntaxes)] fn baz(x: &'static u8) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing x } } diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr index da691225c17..cf0a29678fa 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr @@ -1,35 +1,37 @@ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/not-tied-to-crate.rs:8:16 | LL | fn bar(x: &'static u8) -> &u8 { - | ^^^^^^^ --- the lifetime gets resolved as `'static` + | ^^^^^^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing note: the lint level is defined here --> $DIR/not-tied-to-crate.rs:6:8 | LL | #[warn(mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: one option is to consistently use `'static` +help: consistently use `'static` | LL | fn bar(x: &'static u8) -> &'static u8 { | +++++++ -error: lifetime flowing from input to output with different syntax can be confusing +error: eliding a lifetime that's named elsewhere is confusing --> $DIR/not-tied-to-crate.rs:14:16 | LL | fn baz(x: &'static u8) -> &u8 { - | ^^^^^^^ --- the lifetime gets resolved as `'static` + | ^^^^^^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing note: the lint level is defined here --> $DIR/not-tied-to-crate.rs:13:12 | LL | #[deny(mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: one option is to consistently use `'static` +help: consistently use `'static` | LL | fn baz(x: &'static u8) -> &'static u8 { | +++++++ diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.rs index 47ae258f138..c41cf44e1c5 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.rs +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.rs @@ -14,26 +14,26 @@ impl Trait for () { } fn ampersand(x: &'static u8) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing x } struct Brackets<'a>(&'a u8); fn brackets(x: &'static u8) -> Brackets { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing Brackets(x) } struct Comma<'a, T>(&'a T); fn comma(x: &'static u8) -> Comma { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing Comma(x) } fn underscore(x: &'static u8) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing x } diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr index 5b9a986bcbe..d60bec6f7e4 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr @@ -1,56 +1,60 @@ -error: lifetime flowing from input to output with different syntax can be confusing +error: eliding a lifetime that's named elsewhere is confusing --> $DIR/static.rs:16:18 | LL | fn ampersand(x: &'static u8) -> &u8 { - | ^^^^^^^ --- the lifetime gets resolved as `'static` + | ^^^^^^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing note: the lint level is defined here --> $DIR/static.rs:1:9 | LL | #![deny(mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: one option is to consistently use `'static` +help: consistently use `'static` | LL | fn ampersand(x: &'static u8) -> &'static u8 { | +++++++ -error: lifetime flowing from input to output with different syntax can be confusing +error: hiding a lifetime that's named elsewhere is confusing --> $DIR/static.rs:23:17 | LL | fn brackets(x: &'static u8) -> Brackets { - | ^^^^^^^ -------- the lifetime gets resolved as `'static` + | ^^^^^^^ -------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL | fn brackets(x: &'static u8) -> Brackets<'static> { | +++++++++ -error: lifetime flowing from input to output with different syntax can be confusing +error: hiding a lifetime that's named elsewhere is confusing --> $DIR/static.rs:30:14 | LL | fn comma(x: &'static u8) -> Comma { - | ^^^^^^^ --------- the lifetime gets resolved as `'static` + | ^^^^^^^ --------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL | fn comma(x: &'static u8) -> Comma<'static, u8> { | ++++++++ -error: lifetime flowing from input to output with different syntax can be confusing +error: eliding a lifetime that's named elsewhere is confusing --> $DIR/static.rs:35:19 | LL | fn underscore(x: &'static u8) -> &'_ u8 { - | ^^^^^^^ -- the lifetime gets resolved as `'static` + | ^^^^^^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL - fn underscore(x: &'static u8) -> &'_ u8 { LL + fn underscore(x: &'static u8) -> &'static u8 { diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs index b98423afb17..f6260c47202 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs @@ -5,109 +5,111 @@ struct ContainsLifetime<'a>(&'a u8); struct S(u8); +// ref to ref + fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing v } fn explicit_bound_ref_to_explicit_anonymous_ref<'a>(v: &'a u8) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing v } -// --- +// path to path fn implicit_path_to_explicit_anonymous_path(v: ContainsLifetime) -> ContainsLifetime<'_> { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing v } fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing v } fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing v } fn explicit_bound_path_to_explicit_anonymous_path<'a>( v: ContainsLifetime<'a>, - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing ) -> ContainsLifetime<'_> { v } -// --- +// ref to path fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing ContainsLifetime(v) } fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing ContainsLifetime(v) } fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing ContainsLifetime(v) } fn explicit_bound_ref_to_explicit_anonymous_path<'a>(v: &'a u8) -> ContainsLifetime<'_> { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing ContainsLifetime(v) } -// --- +// path to ref fn implicit_path_to_implicit_ref(v: ContainsLifetime) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing v.0 } fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing v.0 } fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing v.0 } fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a>) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing v.0 } impl S { fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing &self.0 } fn method_explicit_bound_ref_to_explicit_anonymous_ref<'a>(&'a self) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing &self.0 } // --- fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing ContainsLifetime(&self.0) } fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing ContainsLifetime(&self.0) } fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -> ContainsLifetime<'_> { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing ContainsLifetime(&self.0) } } @@ -122,43 +124,43 @@ mod static_suggestions { struct S(u8); fn static_ref_to_implicit_ref(v: &'static u8) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing v } fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing v } fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing ContainsLifetime(v) } fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLifetime<'_> { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing ContainsLifetime(v) } impl S { fn static_ref_to_implicit_ref(&'static self) -> &u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing &self.0 } fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'_ u8 { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing &self.0 } fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing ContainsLifetime(&self.0) } fn static_ref_to_explicit_anonymous_path(&'static self) -> ContainsLifetime<'_> { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing ContainsLifetime(&self.0) } } @@ -170,23 +172,23 @@ mod impl_trait { struct ContainsLifetime<'a>(&'a u8); fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce() + '_ { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing move || _ = v } fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> impl FnOnce() + use<'_> { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing move || _ = v } fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl FnOnce() + '_ { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing move || _ = v } fn explicit_bound_path_to_impl_trait_precise_capture<'a>( v: ContainsLifetime<'a>, - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing ) -> impl FnOnce() + use<'_> { move || _ = v } @@ -200,13 +202,13 @@ mod dyn_trait { struct ContainsLifetime<'a>(&'a u8); fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box + '_> { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing Box::new(iter::once(v)) } fn explicit_bound_path_to_dyn_trait_bound<'a>( v: ContainsLifetime<'a>, - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's named elsewhere is confusing ) -> Box + '_> { Box::new(iter::once(v)) } @@ -214,10 +216,28 @@ mod dyn_trait { /// These tests serve to exercise edge cases of the lint formatting mod diagnostic_output { + #[derive(Copy, Clone)] + struct ContainsLifetime<'a>(&'a u8); + + fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &u8 { + //~^ ERROR eliding a lifetime that's named elsewhere is confusing + v.0 + } + fn multiple_outputs<'a>(v: &'a u8) -> (&u8, &u8) { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR eliding a lifetime that's named elsewhere is confusing (v, v) } + + fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&u8, ContainsLifetime) { + //~^ ERROR hiding or eliding a lifetime that's named elsewhere is confusing + (v.0, v) + } + + fn explicit_bound_output<'a>(v: &'a u8) -> (&u8, &'a u8, ContainsLifetime<'a>) { + //~^ ERROR eliding a lifetime that's named elsewhere is confusing + (v, v, ContainsLifetime(v)) + } } /// Trait functions are represented differently in the HIR. Make sure @@ -228,20 +248,20 @@ mod trait_functions { trait TheTrait { fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime; - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing } impl TheTrait for &u8 { fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing ContainsLifetime(v) } fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime { - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing ContainsLifetime(self) } } @@ -255,7 +275,7 @@ mod foreign_functions { extern "Rust" { fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; - //~^ ERROR lifetime flowing from input to output with different syntax + //~^ ERROR hiding a lifetime that's elided elsewhere is confusing } } diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr index 108b3f14169..20b7561c594 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr @@ -1,538 +1,613 @@ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:8:47 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:10:47 | LL | fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &u8 { - | ^^ --- the lifetime gets resolved as `'a` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing note: the lint level is defined here --> $DIR/mismatched-lifetime-syntaxes.rs:1:9 | LL | #![deny(mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: one option is to consistently use `'a` +help: consistently use `'a` | LL | fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &'a u8 { | ++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:13:57 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:15:57 | LL | fn explicit_bound_ref_to_explicit_anonymous_ref<'a>(v: &'a u8) -> &'_ u8 { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn explicit_bound_ref_to_explicit_anonymous_ref<'a>(v: &'a u8) -> &'_ u8 { LL + fn explicit_bound_ref_to_explicit_anonymous_ref<'a>(v: &'a u8) -> &'a u8 { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:20:48 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:22:48 | LL | fn implicit_path_to_explicit_anonymous_path(v: ContainsLifetime) -> ContainsLifetime<'_> { - | ^^^^^^^^^^^^^^^^ -- the lifetime gets resolved as `'_` + | ^^^^^^^^^^^^^^^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is hidden here | -help: one option is to consistently use `'_` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'_` | LL | fn implicit_path_to_explicit_anonymous_path(v: ContainsLifetime<'_>) -> ContainsLifetime<'_> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:25:65 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:27:65 | LL | fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> ContainsLifetime { - | ^^ ---------------- the lifetime gets resolved as `'_` + | ^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to consistently use `'_` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'_` | LL | fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> ContainsLifetime<'_> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:30:65 +error: hiding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:32:65 | LL | fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> ContainsLifetime { - | ^^ ---------------- the lifetime gets resolved as `'a` + | ^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> ContainsLifetime<'a> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:36:25 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:38:25 | LL | v: ContainsLifetime<'a>, - | ^^ this lifetime flows to the output + | ^^ the lifetime is named here LL | LL | ) -> ContainsLifetime<'_> { - | -- the lifetime gets resolved as `'a` + | -- the same lifetime is elided here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - ) -> ContainsLifetime<'_> { LL + ) -> ContainsLifetime<'a> { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:44:37 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:46:37 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { - | ^^^ ---------------- the lifetime gets resolved as `'_` + | ^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:49:48 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:51:48 | LL | fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime { - | ^^ ---------------- the lifetime gets resolved as `'_` + | ^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths - | -LL - fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime { -LL + fn explicit_anonymous_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_> { + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | +LL | fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime<'_> { + | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:54:48 +error: hiding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:56:48 | LL | fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime { - | ^^ ---------------- the lifetime gets resolved as `'a` + | ^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime<'a> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:59:58 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:61:58 | LL | fn explicit_bound_ref_to_explicit_anonymous_path<'a>(v: &'a u8) -> ContainsLifetime<'_> { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn explicit_bound_ref_to_explicit_anonymous_path<'a>(v: &'a u8) -> ContainsLifetime<'_> { LL + fn explicit_bound_ref_to_explicit_anonymous_path<'a>(v: &'a u8) -> ContainsLifetime<'a> { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:66:37 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:68:37 | LL | fn implicit_path_to_implicit_ref(v: ContainsLifetime) -> &u8 { - | ^^^^^^^^^^^^^^^^ --- the lifetime gets resolved as `'_` + | ^^^^^^^^^^^^^^^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is hidden here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | LL | fn implicit_path_to_implicit_ref(v: ContainsLifetime<'_>) -> &u8 { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:71:47 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:73:47 | LL | fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime) -> &'_ u8 { - | ^^^^^^^^^^^^^^^^ -- the lifetime gets resolved as `'_` + | ^^^^^^^^^^^^^^^^ -- the same lifetime is elided here | | - | this lifetime flows to the output - | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + | the lifetime is hidden here | -LL - fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime) -> &'_ u8 { -LL + fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime<'_>) -> &u8 { + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | +LL | fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime<'_>) -> &'_ u8 { + | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:76:64 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:78:64 | LL | fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &u8 { - | ^^ --- the lifetime gets resolved as `'a` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &'a u8 { | ++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:81:74 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:83:74 | LL | fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a>) -> &'_ u8 { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a>) -> &'_ u8 { LL + fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a>) -> &'a u8 { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:87:55 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:89:55 | LL | fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &u8 { - | ^^ --- the lifetime gets resolved as `'a` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &'a u8 { | ++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:92:65 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:94:65 | LL | fn method_explicit_bound_ref_to_explicit_anonymous_ref<'a>(&'a self) -> &'_ u8 { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn method_explicit_bound_ref_to_explicit_anonymous_ref<'a>(&'a self) -> &'_ u8 { LL + fn method_explicit_bound_ref_to_explicit_anonymous_ref<'a>(&'a self) -> &'a u8 { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:99:56 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:101:56 | LL | fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> ContainsLifetime { - | ^^ ---------------- the lifetime gets resolved as `'_` + | ^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths - | -LL - fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> ContainsLifetime { -LL + fn method_explicit_anonymous_ref_to_implicit_path(&self) -> ContainsLifetime<'_> { + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | +LL | fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> ContainsLifetime<'_> { + | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:104:56 +error: hiding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:106:56 | LL | fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> ContainsLifetime { - | ^^ ---------------- the lifetime gets resolved as `'a` + | ^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> ContainsLifetime<'a> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:109:66 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:111:66 | LL | fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -> ContainsLifetime<'_> { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -> ContainsLifetime<'_> { LL + fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -> ContainsLifetime<'a> { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:124:39 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:126:39 | LL | fn static_ref_to_implicit_ref(v: &'static u8) -> &u8 { - | ^^^^^^^ --- the lifetime gets resolved as `'static` + | ^^^^^^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL | fn static_ref_to_implicit_ref(v: &'static u8) -> &'static u8 { | +++++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:129:49 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:131:49 | LL | fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'_ u8 { - | ^^^^^^^ -- the lifetime gets resolved as `'static` + | ^^^^^^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL - fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'_ u8 { LL + fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'static u8 { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:134:40 +error: hiding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:136:40 | LL | fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime { - | ^^^^^^^ ---------------- the lifetime gets resolved as `'static` + | ^^^^^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL | fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime<'static> { | +++++++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:139:50 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:141:50 | LL | fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLifetime<'_> { - | ^^^^^^^ -- the lifetime gets resolved as `'static` + | ^^^^^^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL - fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLifetime<'_> { LL + fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLifetime<'static> { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:145:40 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:147:40 | LL | fn static_ref_to_implicit_ref(&'static self) -> &u8 { - | ^^^^^^^ --- the lifetime gets resolved as `'static` + | ^^^^^^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL | fn static_ref_to_implicit_ref(&'static self) -> &'static u8 { | +++++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:150:50 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:152:50 | LL | fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'_ u8 { - | ^^^^^^^ -- the lifetime gets resolved as `'static` + | ^^^^^^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL - fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'_ u8 { LL + fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'static u8 { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:155:41 +error: hiding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:157:41 | LL | fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime { - | ^^^^^^^ ---------------- the lifetime gets resolved as `'static` + | ^^^^^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL | fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime<'static> { | +++++++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:160:51 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:162:51 | LL | fn static_ref_to_explicit_anonymous_path(&'static self) -> ContainsLifetime<'_> { - | ^^^^^^^ -- the lifetime gets resolved as `'static` + | ^^^^^^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'static` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'static` | LL - fn static_ref_to_explicit_anonymous_path(&'static self) -> ContainsLifetime<'_> { LL + fn static_ref_to_explicit_anonymous_path(&'static self) -> ContainsLifetime<'static> { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:172:55 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:174:55 | LL | fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce() + '_ { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce() + '_ { LL + fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce() + 'a { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:177:65 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:179:65 | LL | fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> impl FnOnce() + use<'_> { - | ^^ -- the lifetime gets resolved as `'a` - | | - | this lifetime flows to the output + | ^^ the lifetime is named here -- the same lifetime is elided here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> impl FnOnce() + use<'_> { LL + fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> impl FnOnce() + use<'a> { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:182:72 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:184:72 | LL | fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl FnOnce() + '_ { - | ^^ -- the lifetime gets resolved as `'a` + | ^^ -- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl FnOnce() + '_ { LL + fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl FnOnce() + 'a { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:188:29 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:190:29 | LL | v: ContainsLifetime<'a>, - | ^^ this lifetime flows to the output + | ^^ the lifetime is named here LL | LL | ) -> impl FnOnce() + use<'_> { - | -- the lifetime gets resolved as `'a` + | -- the same lifetime is elided here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL - ) -> impl FnOnce() + use<'_> { LL + ) -> impl FnOnce() + use<'a> { | -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:202:54 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:204:54 | LL | fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box + '_> { - | ^^ --- -- the lifetimes get resolved as `'a` - | | | - | | the lifetimes get resolved as `'a` - | this lifetime flows to the output + | ^^ the lifetime is named here --- the same lifetime is elided here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box + '_> { | ++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:208:29 +error: hiding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:210:29 | LL | v: ContainsLifetime<'a>, - | ^^ this lifetime flows to the output + | ^^ the lifetime is named here LL | LL | ) -> Box + '_> { - | ---------------- -- the lifetimes get resolved as `'a` - | | - | the lifetimes get resolved as `'a` + | ---------------- the same lifetime is hidden here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | ) -> Box> + '_> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:217:33 +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:222:33 + | +LL | fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &u8 { + | ^^ ^^ --- the same lifetime is elided here + | | | + | | the lifetime is named here + | the lifetime is named here + | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` + | +LL | fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &'a u8 { + | ++ + +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:227:33 | LL | fn multiple_outputs<'a>(v: &'a u8) -> (&u8, &u8) { - | ^^ --- --- the lifetimes get resolved as `'a` + | ^^ --- --- the same lifetime is elided here | | | - | | the lifetimes get resolved as `'a` - | this lifetime flows to the output + | | the same lifetime is elided here + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn multiple_outputs<'a>(v: &'a u8) -> (&'a u8, &'a u8) { | ++ ++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:230:45 +error: hiding or eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:232:53 + | +LL | fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&u8, ContainsLifetime) { + | ^^ --- ---------------- the same lifetime is hidden here + | | | + | | the same lifetime is elided here + | the lifetime is named here + | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` + | +LL | fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&'a u8, ContainsLifetime<'a>) { + | ++ ++++ + +error: eliding a lifetime that's named elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:237:38 + | +LL | fn explicit_bound_output<'a>(v: &'a u8) -> (&u8, &'a u8, ContainsLifetime<'a>) { + | ^^ --- -- -- the same lifetime is named here + | | | | + | | | the same lifetime is named here + | | the same lifetime is elided here + | the lifetime is named here + | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` + | +LL | fn explicit_bound_output<'a>(v: &'a u8) -> (&'a u8, &'a u8, ContainsLifetime<'a>) { + | ++ + +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:250:45 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; - | ^^^ ---------------- the lifetime gets resolved as `'_` + | ^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_>; | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:233:49 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:253:49 | LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime; - | ^^^^^ ---------------- the lifetime gets resolved as `'_` + | ^^^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime<'_>; | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:238:45 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:258:45 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { - | ^^^ ---------------- the lifetime gets resolved as `'_` + | ^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:243:49 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:263:49 | LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime { - | ^^^^^ ---------------- the lifetime gets resolved as `'_` + | ^^^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime<'_> { | ++++ -error: lifetime flowing from input to output with different syntax can be confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:257:45 +error: hiding a lifetime that's elided elsewhere is confusing + --> $DIR/mismatched-lifetime-syntaxes.rs:277:45 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; - | ^^^ ---------------- the lifetime gets resolved as `'_` + | ^^^ ---------------- the same lifetime is hidden here | | - | this lifetime flows to the output + | the lifetime is elided here | -help: one option is to remove the lifetime for references and use the anonymous lifetime for paths + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: use `'_` for type paths | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime<'_>; | ++++ -error: aborting due to 39 previous errors +error: aborting due to 42 previous errors diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs index ecd669059ed..ce2fb8235cc 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.rs +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.rs @@ -4,11 +4,11 @@ struct Foo<'a>(&'a str); impl<'b> Foo<'b> { fn a<'a>(self: Self, a: &'a str) -> &str { - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing a } fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing a } } diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 5351bf3c94c..7108fa1a290 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -1,26 +1,28 @@ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/ignore-non-reference-lifetimes.rs:6:30 | LL | fn a<'a>(self: Self, a: &'a str) -> &str { - | ^^ ---- the lifetime gets resolved as `'a` + | ^^ ---- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default -help: one option is to consistently use `'a` +help: consistently use `'a` | LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { | ++ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/ignore-non-reference-lifetimes.rs:10:33 | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { - | ^^ ---- the lifetime gets resolved as `'a` + | ^^ ---- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &'a str { | ++ diff --git a/tests/ui/self/self_lifetime-async.rs b/tests/ui/self/self_lifetime-async.rs index f839ab03a60..0093971fee4 100644 --- a/tests/ui/self/self_lifetime-async.rs +++ b/tests/ui/self/self_lifetime-async.rs @@ -4,13 +4,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing } type Alias = Foo<'static>; impl Alias { async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing } fn main() {} diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index a9c1be2e808..43dc96abdc2 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -1,26 +1,28 @@ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/self_lifetime-async.rs:6:29 | LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } - | ^^ --- the lifetime gets resolved as `'b` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default -help: one option is to consistently use `'b` +help: consistently use `'b` | LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } | ++ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/self_lifetime-async.rs:12:42 | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } - | ^^ --- the lifetime gets resolved as `'a` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } | ++ diff --git a/tests/ui/self/self_lifetime.rs b/tests/ui/self/self_lifetime.rs index aaa31f85ad5..190809af22f 100644 --- a/tests/ui/self/self_lifetime.rs +++ b/tests/ui/self/self_lifetime.rs @@ -5,13 +5,13 @@ struct Foo<'a>(&'a ()); impl<'a> Foo<'a> { fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing } type Alias = Foo<'static>; impl Alias { fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } - //~^ WARNING lifetime flowing from input to output with different syntax + //~^ WARNING eliding a lifetime that's named elsewhere is confusing } fn main() {} diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index ec676e69cf6..4f9b2fcd2ad 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -1,26 +1,28 @@ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/self_lifetime.rs:7:23 | LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } - | ^^ --- the lifetime gets resolved as `'b` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default -help: one option is to consistently use `'b` +help: consistently use `'b` | LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } | ++ -warning: lifetime flowing from input to output with different syntax can be confusing +warning: eliding a lifetime that's named elsewhere is confusing --> $DIR/self_lifetime.rs:13:36 | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } - | ^^ --- the lifetime gets resolved as `'a` + | ^^ --- the same lifetime is elided here | | - | this lifetime flows to the output + | the lifetime is named here | -help: one option is to consistently use `'a` + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing +help: consistently use `'a` | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &'a () { arg } | ++ -- cgit 1.4.1-3-g733a5 From 8b868fa534a8b660a5b8051a5c883d4c15c5b70e Mon Sep 17 00:00:00 2001 From: David Mládek Date: Sat, 12 Jul 2025 16:44:34 +0200 Subject: Implement resolver warnings about reexporting private dependencies --- compiler/rustc_lint/messages.ftl | 3 ++ compiler/rustc_lint/src/early/diagnostics.rs | 3 ++ compiler/rustc_lint/src/lints.rs | 8 +++++ compiler/rustc_lint_defs/src/lib.rs | 5 +++ compiler/rustc_resolve/src/imports.rs | 25 ++++++++++++-- tests/ui/privacy/pub-priv-dep/pub-priv1.rs | 14 ++++---- tests/ui/privacy/pub-priv-dep/pub-priv1.stderr | 46 +++++++++++++++++++++++--- 7 files changed, 90 insertions(+), 14 deletions(-) (limited to 'compiler/rustc_lint/src') diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 8d9f2385b71..183db43ca76 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -744,6 +744,9 @@ lint_redundant_semicolons_suggestion = remove {$multiple_semicolons -> *[false] this semicolon } +lint_reexport_private_dependency = + {$kind} `{$name}` from private dependency '{$krate}' is re-exported + lint_remove_mut_from_pattern = remove `mut` from the parameter lint_removed_lint = lint `{$name}` has been removed: {$reason} diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 653559009cc..f0fbf5bc81e 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -351,6 +351,9 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } + BuiltinLintDiag::ReexportPrivateDependency { name, kind, krate } => { + lints::ReexportPrivateDependency { name, kind, krate }.decorate_lint(diag); + } BuiltinLintDiag::UnusedQualifications { removal_span } => { lints::UnusedQualifications { removal_span }.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 21148833eaf..fc3c1073259 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3080,6 +3080,14 @@ pub(crate) struct HiddenGlobReexports { pub namespace: String, } +#[derive(LintDiagnostic)] +#[diag(lint_reexport_private_dependency)] +pub(crate) struct ReexportPrivateDependency { + pub name: String, + pub kind: String, + pub krate: Symbol, +} + #[derive(LintDiagnostic)] #[diag(lint_unnecessary_qualification)] pub(crate) struct UnusedQualifications { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index cd402c9234f..fe068d96b74 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -739,6 +739,11 @@ pub enum BuiltinLintDiag { /// The local binding that shadows the glob reexport. private_item_span: Span, }, + ReexportPrivateDependency { + name: String, + kind: String, + krate: Symbol, + }, UnusedQualifications { /// The span of the unnecessarily-qualified path to remove. removal_span: Span, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index b2f6ee6563c..9e8eac75fa1 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -14,8 +14,8 @@ use rustc_middle::metadata::{ModChild, Reexport}; use rustc_middle::{span_bug, ty}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ - AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, - REDUNDANT_IMPORTS, UNUSED_IMPORTS, + AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS, + PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS, }; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; @@ -696,6 +696,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } } + + if let NameBindingKind::Import { import, .. } = binding.kind + && let Some(binding_id) = import.id() + && let import_def_id = self.local_def_id(binding_id) + && self.effective_visibilities.is_exported(import_def_id) + && let Res::Def(reexported_kind, reexported_def_id) = binding.res() + && !matches!(reexported_kind, DefKind::Ctor(..)) + && !reexported_def_id.is_local() + && self.tcx.is_private_dep(reexported_def_id.krate) + { + self.lint_buffer.buffer_lint( + EXPORTED_PRIVATE_DEPENDENCIES, + binding_id, + binding.span, + BuiltinLintDiag::ReexportPrivateDependency { + kind: binding.res().descr().to_string(), + name: key.ident.name.to_string(), + krate: self.tcx.crate_name(reexported_def_id.krate), + }, + ); + } } } } diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs index 877029f3de3..192ca0db8bd 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs @@ -9,10 +9,10 @@ #![deny(exported_private_dependencies)] // This crate is a private dependency -// FIXME: This should trigger. pub extern crate priv_dep; +//~^ ERROR crate `priv_dep` from private dependency 'priv_dep' is re-exported // This crate is a public dependency -extern crate pub_dep; +pub extern crate pub_dep; // This crate is a private dependency extern crate pm; @@ -91,16 +91,16 @@ pub struct AllowedPrivType { pub allowed: OtherType, } -// FIXME: This should trigger. pub use priv_dep::m; -// FIXME: This should trigger. +//~^ ERROR macro `m` from private dependency 'priv_dep' is re-exported pub use pm::fn_like; -// FIXME: This should trigger. +//~^ ERROR macro `fn_like` from private dependency 'pm' is re-exported pub use pm::PmDerive; -// FIXME: This should trigger. +//~^ ERROR macro `PmDerive` from private dependency 'pm' is re-exported pub use pm::pm_attr; +//~^ ERROR macro `pm_attr` from private dependency 'pm' is re-exported -// FIXME: This should trigger. pub use priv_dep::E::V1; +//~^ ERROR variant `V1` from private dependency 'priv_dep' is re-exported fn main() {} diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr index adfe13424cd..9da47827be4 100644 --- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr +++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr @@ -1,8 +1,8 @@ -error: type `OtherType` from private dependency 'priv_dep' in public interface - --> $DIR/pub-priv1.rs:29:5 +error: crate `priv_dep` from private dependency 'priv_dep' is re-exported + --> $DIR/pub-priv1.rs:12:1 | -LL | pub field: OtherType, - | ^^^^^^^^^^^^^^^^^^^^ +LL | pub extern crate priv_dep; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/pub-priv1.rs:9:9 @@ -10,6 +10,42 @@ note: the lint level is defined here LL | #![deny(exported_private_dependencies)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: macro `m` from private dependency 'priv_dep' is re-exported + --> $DIR/pub-priv1.rs:94:9 + | +LL | pub use priv_dep::m; + | ^^^^^^^^^^^ + +error: macro `fn_like` from private dependency 'pm' is re-exported + --> $DIR/pub-priv1.rs:96:9 + | +LL | pub use pm::fn_like; + | ^^^^^^^^^^^ + +error: derive macro `PmDerive` from private dependency 'pm' is re-exported + --> $DIR/pub-priv1.rs:98:9 + | +LL | pub use pm::PmDerive; + | ^^^^^^^^^^^^ + +error: attribute macro `pm_attr` from private dependency 'pm' is re-exported + --> $DIR/pub-priv1.rs:100:9 + | +LL | pub use pm::pm_attr; + | ^^^^^^^^^^^ + +error: variant `V1` from private dependency 'priv_dep' is re-exported + --> $DIR/pub-priv1.rs:103:9 + | +LL | pub use priv_dep::E::V1; + | ^^^^^^^^^^^^^^^ + +error: type `OtherType` from private dependency 'priv_dep' in public interface + --> $DIR/pub-priv1.rs:29:5 + | +LL | pub field: OtherType, + | ^^^^^^^^^^^^^^^^^^^^ + error: type `OtherType` from private dependency 'priv_dep' in public interface --> $DIR/pub-priv1.rs:36:5 | @@ -90,5 +126,5 @@ LL | impl PubTraitOnPrivate for OtherType {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 14 previous errors +error: aborting due to 20 previous errors -- cgit 1.4.1-3-g733a5 From 7356ff7517f4d95583f8fd6d631441893c87dd3f Mon Sep 17 00:00:00 2001 From: tiif Date: Mon, 14 Jul 2025 13:38:19 +0000 Subject: Implement other logics --- .../src/encode_cross_crate.rs | 1 + compiler/rustc_attr_parsing/src/context.rs | 5 ++- compiler/rustc_feature/src/builtin_attrs.rs | 4 +++ compiler/rustc_hir_analysis/src/check/wfcheck.rs | 14 +++++--- .../src/collect/predicates_of.rs | 2 ++ .../src/impl_wf_check/min_specialization.rs | 1 + .../rustc_hir_analysis/src/outlives/explicit.rs | 1 + .../src/fn_ctxt/inspect_obligations.rs | 1 + compiler/rustc_hir_typeck/src/method/probe.rs | 1 + compiler/rustc_lint/src/builtin.rs | 3 +- compiler/rustc_middle/src/ty/context.rs | 1 + compiler/rustc_middle/src/ty/predicate.rs | 3 ++ compiler/rustc_middle/src/ty/print/pretty.rs | 1 + compiler/rustc_privacy/src/lib.rs | 1 + .../rustc_public/src/unstable/convert/stable/ty.rs | 3 ++ compiler/rustc_session/src/parse.rs | 40 ++++++++++++++++++++++ compiler/rustc_span/src/symbol.rs | 1 + .../src/error_reporting/traits/ambiguity.rs | 25 ++++++++++++++ .../error_reporting/traits/fulfillment_errors.rs | 2 ++ .../rustc_trait_selection/src/traits/auto_trait.rs | 1 + .../src/traits/dyn_compatibility.rs | 2 ++ .../rustc_trait_selection/src/traits/fulfill.rs | 3 ++ .../query/type_op/implied_outlives_bounds.rs | 1 + compiler/rustc_trait_selection/src/traits/util.rs | 1 + compiler/rustc_trait_selection/src/traits/wf.rs | 2 ++ .../rustc_traits/src/normalize_erasing_regions.rs | 1 + compiler/rustc_type_ir/src/elaborate.rs | 3 ++ compiler/rustc_type_ir/src/flags.rs | 3 +- compiler/rustc_type_ir/src/interner.rs | 1 + compiler/rustc_type_ir/src/predicate_kind.rs | 10 ++++++ src/librustdoc/clean/mod.rs | 3 +- 31 files changed, 132 insertions(+), 9 deletions(-) (limited to 'compiler/rustc_lint/src') diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 494b570c86c..84c3bd1eb61 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -70,6 +70,7 @@ impl AttributeKind { TrackCaller(..) => Yes, TypeConst(..) => Yes, UnsafeSpecializationMarker(..) => No, + UnstableFeatureBound(..) => No, Used { .. } => No, // tidy-alphabetical-end } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 1f6675b4c5a..390246239ed 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -13,7 +13,9 @@ use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirI use rustc_session::Session; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; -use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; +use crate::attributes::allow_unstable::{ + AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser, +}; use crate::attributes::codegen_attrs::{ ColdParser, ExportNameParser, NakedParser, NoMangleParser, OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser, @@ -133,6 +135,7 @@ attribute_parsers!( Combine, Combine, Combine, + Combine, // tidy-alphabetical-end // tidy-alphabetical-start diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 7d9915d7f68..e2827f227ab 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -683,6 +683,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk, EncodeCrossCrate::Yes ), + ungated!( + unstable_feature_bound, Normal, template!(Word, List: "feat1, feat2, ..."), + DuplicatesOk, EncodeCrossCrate::No, + ), ungated!( rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk, EncodeCrossCrate::Yes diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 607028f4d9a..14ec82ede1c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2212,12 +2212,16 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { let implied_obligations = traits::elaborate(tcx, predicates_with_span); for (pred, obligation_span) in implied_obligations { - // We lower empty bounds like `Vec:` as - // `WellFormed(Vec)`, which will later get checked by - // regular WF checking - if let ty::ClauseKind::WellFormed(..) = pred.kind().skip_binder() { - continue; + match pred.kind().skip_binder() { + // We lower empty bounds like `Vec:` as + // `WellFormed(Vec)`, which will later get checked by + // regular WF checking + ty::ClauseKind::WellFormed(..) + // Unstable feature goals cannot be proven in an empty environment so skip them + | ty::ClauseKind::UnstableFeature(..) => continue, + _ => {} } + // Match the existing behavior. if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) { let pred = self.normalize(span, None, pred); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 60ccc484e00..af78130899e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -778,6 +778,7 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>( ty::ClauseKind::RegionOutlives(_) | ty::ClauseKind::ConstArgHasType(_, _) | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::ConstEvaluatable(_) => { bug!( "unexpected non-`Self` predicate when computing \ @@ -805,6 +806,7 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>( | ty::ClauseKind::ConstArgHasType(_, _) | ty::ClauseKind::WellFormed(_) | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::HostEffect(..) => { bug!( "unexpected non-`Self` predicate when computing \ diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 574d19a5aa5..0043f0c7117 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -499,6 +499,7 @@ fn trait_specialization_kind<'tcx>( | ty::ClauseKind::ConstArgHasType(..) | ty::ClauseKind::WellFormed(_) | ty::ClauseKind::ConstEvaluatable(..) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::HostEffect(..) => None, } } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 2c1d443f951..d3a57a4d8e5 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -54,6 +54,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { | ty::ClauseKind::ConstArgHasType(_, _) | ty::ClauseKind::WellFormed(_) | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::HostEffect(..) => {} } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index e4c62bf027b..367e2b6b372 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -54,6 +54,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::Ambiguous => false, } } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 94c93e73627..3261327a9fd 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -921,6 +921,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::ClauseKind::ConstArgHasType(_, _) | ty::ClauseKind::WellFormed(_) | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::HostEffect(..) => None, } }); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 255ff56f62b..8244f0bed4c 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1519,8 +1519,9 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { ClauseKind::TypeOutlives(..) | ClauseKind::RegionOutlives(..) => "lifetime", + ClauseKind::UnstableFeature(_) // `ConstArgHasType` is never global as `ct` is always a param - ClauseKind::ConstArgHasType(..) + | ClauseKind::ConstArgHasType(..) // Ignore projections, as they can only be global // if the trait bound is global | ClauseKind::Projection(..) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 290213cab5e..915b062417f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -137,6 +137,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type FnInputTys = &'tcx [Ty<'tcx>]; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; + type Symbol = Symbol; type PlaceholderTy = ty::PlaceholderType; type ErrorGuaranteed = ErrorGuaranteed; diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index bc2ac42b6b1..ec2224877a8 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -131,6 +131,7 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::Clause(ClauseKind::TypeOutlives(_)) | PredicateKind::Clause(ClauseKind::Projection(_)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) | PredicateKind::DynCompatible(_) | PredicateKind::Subtype(_) | PredicateKind::Coerce(_) @@ -649,6 +650,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(ClauseKind::Projection(..)) | PredicateKind::Clause(ClauseKind::HostEffect(..)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) | PredicateKind::NormalizesTo(..) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) @@ -670,6 +672,7 @@ impl<'tcx> Predicate<'tcx> { PredicateKind::Clause(ClauseKind::Trait(..)) | PredicateKind::Clause(ClauseKind::HostEffect(..)) | PredicateKind::Clause(ClauseKind::ConstArgHasType(..)) + | PredicateKind::Clause(ClauseKind::UnstableFeature(_)) | PredicateKind::NormalizesTo(..) | PredicateKind::AliasRelate(..) | PredicateKind::Subtype(..) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 7c48a4b0885..b857788b8b7 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3237,6 +3237,7 @@ define_print! { ty::ClauseKind::ConstEvaluatable(ct) => { p!("the constant `", print(ct), "` can be evaluated") } + ty::ClauseKind::UnstableFeature(symbol) => p!("unstable feature: ", write("`{}`", symbol)), } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ab2433234aa..80c13e44d7d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -156,6 +156,7 @@ where } ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self), ty::ClauseKind::WellFormed(term) => term.visit_with(self), + ty::ClauseKind::UnstableFeature(_) => V::Result::output(), } } diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 75c29788787..6b226b8a24d 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -764,6 +764,9 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { ClauseKind::HostEffect(..) => { todo!() } + ClauseKind::UnstableFeature(_) => { + todo!() + } } } } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 0118cdb1fc2..ea7a524efe6 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -205,6 +205,46 @@ pub fn add_feature_diagnostics_for_issue( } } +/// This is only used by unstable_feature_bound as it does not have issue number information for now. +/// This is basically the same as `feature_err_issue` +/// but without the feature issue note. If we can do a lookup for issue number from feature name, +/// then we should directly use `feature_err_issue` for ambiguity error of +/// #[unstable_feature_bound]. +#[track_caller] +pub fn feature_err_unstable_feature_bound( + sess: &Session, + feature: Symbol, + span: impl Into, + explain: impl Into, +) -> Diag<'_> { + let span = span.into(); + + // Cancel an earlier warning for this same error, if it exists. + if let Some(span) = span.primary_span() { + if let Some(err) = sess.dcx().steal_non_err(span, StashKey::EarlySyntaxWarning) { + err.cancel() + } + } + + let mut err = sess.dcx().create_err(FeatureGateError { span, explain: explain.into() }); + + // #23973: do not suggest `#![feature(...)]` if we are in beta/stable + if sess.psess.unstable_features.is_nightly_build() { + err.subdiagnostic(FeatureDiagnosticHelp { feature }); + + if feature == sym::rustc_attrs { + // We're unlikely to stabilize something out of `rustc_attrs` + // without at least renaming it, so pointing out how old + // the compiler is will do little good. + } else if sess.opts.unstable_opts.ui_testing { + err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); + } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { + err.subdiagnostic(suggestion); + } + } + err +} + /// Info about a parsing session. pub struct ParseSess { dcx: DiagCtxt, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8b12edf426c..bd34055f851 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2284,6 +2284,7 @@ symbols! { unsized_locals, unsized_tuple_coercion, unstable, + unstable_feature_bound, unstable_location_reason_default: "this crate is being loaded from the sysroot, an \ unstable location; did you mean to load this crate \ from crates.io via `Cargo.toml` instead?", diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 712e88300ff..98f67257fd1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -12,6 +12,7 @@ use rustc_infer::traits::{ Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation, }; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _}; +use rustc_session::parse::feature_err_unstable_feature_bound; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use tracing::{debug, instrument}; @@ -611,6 +612,30 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) .with_span_label(span, format!("cannot normalize `{alias}`")) } + ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => { + if let Some(e) = self.tainted_by_errors() { + return e; + } + + let mut err; + + if self.tcx.features().staged_api() { + err = self.dcx().struct_span_err( + span, + format!("unstable feature `{sym}` is used without being enabled."), + ); + + err.help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`")); + } else { + err = feature_err_unstable_feature_bound( + &self.tcx.sess, + sym, + span, + format!("use of unstable library feature `{sym}`"), + ); + } + err + } _ => { if let Some(e) = self.tainted_by_errors() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index cd3e6c4bc54..1ac309da101 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -647,6 +647,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ty::PredicateKind::ConstEquate { .. } // Ambiguous predicates should never error | ty::PredicateKind::Ambiguous + // We never return Err when proving UnstableFeature goal. + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature{ .. }) | ty::PredicateKind::NormalizesTo { .. } | ty::PredicateKind::AliasRelate { .. } | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => { diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 3ae908ec16b..759db1d18c0 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -800,6 +800,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // FIXME(generic_const_exprs): you can absolutely add this as a where clauses | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {} ty::PredicateKind::Ambiguous => return false, }; diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 9a4f3887bbb..ea1eed95723 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -238,6 +238,7 @@ fn predicate_references_self<'tcx>( // FIXME(generic_const_exprs): this can mention `Self` | ty::ClauseKind::ConstEvaluatable(..) | ty::ClauseKind::HostEffect(..) + | ty::ClauseKind::UnstableFeature(_) => None, } } @@ -278,6 +279,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { | ty::ClauseKind::ConstArgHasType(_, _) | ty::ClauseKind::WellFormed(_) | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::HostEffect(..) => false, }) } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 3e13e504266..2b5a41ef5a7 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -406,6 +406,9 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ty::PredicateKind::AliasRelate(..) => { bug!("AliasRelate is only used by the new solver") } + ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => { + unreachable!("unexpected higher ranked `UnstableFeature` goal") + } }, Some(pred) => match pred { ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs index e294f7839aa..7540cbe3fd1 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs @@ -110,6 +110,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>( | ty::PredicateKind::ConstEquate(..) | ty::PredicateKind::Ambiguous | ty::PredicateKind::NormalizesTo(..) + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::AliasRelate(..) => {} // We need to search through *all* WellFormed predicates diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 141454bfe37..25cd7787a34 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -80,6 +80,7 @@ pub fn expand_trait_aliases<'tcx>( | ty::ClauseKind::ConstArgHasType(_, _) | ty::ClauseKind::WellFormed(_) | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::HostEffect(..) => {} } } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fed9f254cdf..adce9850b59 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -197,6 +197,7 @@ pub fn clause_obligations<'tcx>( ty::ClauseKind::ConstEvaluatable(ct) => { wf.add_wf_preds_for_term(ct.into()); } + ty::ClauseKind::UnstableFeature(_) => {} } wf.normalize(infcx) @@ -1095,6 +1096,7 @@ pub fn object_region_bounds<'tcx>( | ty::ClauseKind::Projection(_) | ty::ClauseKind::ConstArgHasType(_, _) | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::UnstableFeature(_) | ty::ClauseKind::ConstEvaluatable(_) => None, } }) diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 68ff66bbce7..c1b848a2e79 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -57,6 +57,7 @@ fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::NormalizesTo(..) | ty::PredicateKind::AliasRelate(..) | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 7ffcf7b5d96..38008248757 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -234,6 +234,9 @@ impl> Elaborator { ty::ClauseKind::ConstArgHasType(..) => { // Nothing to elaborate } + ty::ClauseKind::UnstableFeature(_) => { + // Nothing to elaborate + } } } } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 37cc2baa402..a231908f874 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -401,7 +401,6 @@ impl FlagComputation { self.add_const(expected); self.add_const(found); } - ty::PredicateKind::Ambiguous => {} ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => { self.add_alias_term(alias); self.add_term(term); @@ -410,6 +409,8 @@ impl FlagComputation { self.add_term(t1); self.add_term(t2); } + ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_sym)) => {} + ty::PredicateKind::Ambiguous => {} } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index dd3cf1fc181..0ec326d2116 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -106,6 +106,7 @@ pub trait Interner: type ParamTy: ParamLike; type BoundTy: BoundVarLike; type PlaceholderTy: PlaceholderLike; + type Symbol: Copy + Hash + PartialEq + Eq + Debug; // Things stored inside of tys type ErrorGuaranteed: Copy + Debug + Hash + Eq; diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 4e41fd16ffd..8bc15ec4ff5 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -46,6 +46,13 @@ pub enum ClauseKind { /// corresponding trait clause; this just enforces the *constness* of that /// implementation. HostEffect(ty::HostEffectPredicate), + + /// Support marking impl as unstable. + UnstableFeature( + #[type_foldable(identity)] + #[type_visitable(ignore)] + I::Symbol, + ), } #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] @@ -134,6 +141,9 @@ impl fmt::Debug for ClauseKind { ClauseKind::ConstEvaluatable(ct) => { write!(f, "ConstEvaluatable({ct:?})") } + ClauseKind::UnstableFeature(feature_name) => { + write!(f, "UnstableFeature({feature_name:?})") + } } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e7a1f4d8397..3df04091f16 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -390,7 +390,8 @@ pub(crate) fn clean_predicate<'tcx>( ty::ClauseKind::ConstEvaluatable(..) | ty::ClauseKind::WellFormed(..) | ty::ClauseKind::ConstArgHasType(..) - // FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `[const]`. + | ty::ClauseKind::UnstableFeature(..) + // FIXME(const_trait_impl): We can probably use this `HostEffect` pred to render `~const`. | ty::ClauseKind::HostEffect(_) => None, } } -- cgit 1.4.1-3-g733a5 From fad8dec970f51a2d4c23593b059b1684bd85472a Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 16 Jul 2025 15:39:31 +0900 Subject: fix: false positive double_negations when it jumps macro boundary --- compiler/rustc_lint/src/builtin.rs | 2 ++ tests/ui/lint/lint-double-negations-macro.rs | 16 ++++++++++++++++ tests/ui/lint/lint-double-negations-macro.stderr | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 tests/ui/lint/lint-double-negations-macro.rs create mode 100644 tests/ui/lint/lint-double-negations-macro.stderr (limited to 'compiler/rustc_lint/src') diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 255ff56f62b..93df056c43b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1584,6 +1584,8 @@ impl EarlyLintPass for DoubleNegations { if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind && let ExprKind::Unary(UnOp::Neg, ref inner2) = inner.kind && !matches!(inner2.kind, ExprKind::Unary(UnOp::Neg, _)) + // Don't lint if this jumps macro expansion boundary (Issue #143980) + && expr.span.eq_ctxt(inner.span) { cx.emit_span_lint( DOUBLE_NEGATIONS, diff --git a/tests/ui/lint/lint-double-negations-macro.rs b/tests/ui/lint/lint-double-negations-macro.rs new file mode 100644 index 00000000000..a6583271d5a --- /dev/null +++ b/tests/ui/lint/lint-double-negations-macro.rs @@ -0,0 +1,16 @@ +//@ check-pass +macro_rules! neg { + ($e: expr) => { + -$e + }; +} +macro_rules! bad_macro { + ($e: expr) => { + --$e //~ WARN use of a double negation + }; +} + +fn main() { + neg!(-1); + bad_macro!(1); +} diff --git a/tests/ui/lint/lint-double-negations-macro.stderr b/tests/ui/lint/lint-double-negations-macro.stderr new file mode 100644 index 00000000000..d6ac9be48f3 --- /dev/null +++ b/tests/ui/lint/lint-double-negations-macro.stderr @@ -0,0 +1,20 @@ +warning: use of a double negation + --> $DIR/lint-double-negations-macro.rs:9:9 + | +LL | --$e + | ^^^^ +... +LL | bad_macro!(1); + | ------------- in this macro invocation + | + = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages + = note: use `-= 1` if you meant to decrement the value + = note: `#[warn(double_negations)]` on by default + = note: this warning originates in the macro `bad_macro` (in Nightly builds, run with -Z macro-backtrace for more info) +help: add parentheses for clarity + | +LL | -(-$e) + | + + + +warning: 1 warning emitted + -- cgit 1.4.1-3-g733a5 From 69326878eeabb713e2d4a85215b87f18e498313c Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 13 Jul 2025 16:49:19 +0800 Subject: parse `const trait Trait` --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_ast/src/visit.rs | 3 +- compiler/rustc_ast_lowering/src/item.rs | 13 ++++++-- compiler/rustc_ast_passes/messages.ftl | 4 +-- compiler/rustc_ast_passes/src/ast_validation.rs | 38 +++++++++++++--------- compiler/rustc_ast_passes/src/errors.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state/item.rs | 2 ++ .../rustc_attr_parsing/src/attributes/traits.rs | 1 + compiler/rustc_const_eval/src/check_consts/mod.rs | 2 +- .../rustc_const_eval/src/const_eval/machine.rs | 4 +-- compiler/rustc_feature/src/builtin_attrs.rs | 1 + compiler/rustc_hir/src/hir.rs | 19 ++++++++--- compiler/rustc_hir/src/intravisit.rs | 10 +++++- compiler/rustc_hir_analysis/messages.ftl | 12 +++---- compiler/rustc_hir_analysis/src/collect.rs | 13 +++++--- .../src/collect/predicates_of.rs | 4 +-- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_analysis/src/errors.rs | 2 ++ .../src/errors/wrong_number_of_generic_args.rs | 2 +- .../src/hir_ty_lowering/bounds.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 11 ++++++- compiler/rustc_hir_typeck/src/method/suggest.rs | 6 ++-- .../src/multiple_supertrait_upcastable.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 2 +- compiler/rustc_parse/messages.ftl | 1 + compiler/rustc_parse/src/errors.rs | 8 +++++ compiler/rustc_parse/src/parser/item.rs | 28 ++++++++++++---- compiler/rustc_passes/messages.ftl | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- .../src/error_reporting/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 10 +++--- compiler/rustc_trait_selection/src/errors.rs | 2 +- src/doc/rustc-dev-guide/src/effects.md | 9 ++--- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/types.rs | 2 +- .../src/arbitrary_source_item_ordering.rs | 2 +- src/tools/clippy/clippy_lints/src/doc/mod.rs | 2 +- src/tools/clippy/clippy_lints/src/len_zero.rs | 2 +- .../clippy/clippy_lints/src/missing_inline.rs | 2 +- src/tools/clippy/clippy_lints/src/trait_bounds.rs | 4 +-- .../clippy/clippy_lints/src/upper_case_acronyms.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils/mod.rs | 5 ++- .../clippy/clippy_utils/src/check_proc_macro.rs | 4 +-- src/tools/clippy/tests/ui/assign_ops.fixed | 3 +- src/tools/clippy/tests/ui/assign_ops.rs | 3 +- .../ui/missing_const_for_fn/const_trait.fixed | 3 +- .../tests/ui/missing_const_for_fn/const_trait.rs | 3 +- .../ui/missing_const_for_fn/const_trait.stderr | 2 +- .../tests/ui/trait_duplication_in_bounds.fixed | 3 +- .../clippy/tests/ui/trait_duplication_in_bounds.rs | 3 +- .../tests/ui/trait_duplication_in_bounds.stderr | 6 ++-- .../crates/test-utils/src/minicore.rs | 3 +- src/tools/rustfmt/src/items.rs | 4 ++- tests/crashes/117629.rs | 3 +- .../const-super-trait-nightly-disabled.stderr | 10 +++--- .../const-super-trait-nightly-enabled.stderr | 10 +++--- .../const-super-trait-stable-disabled.stderr | 10 +++--- .../const-super-trait-stable-enabled.stderr | 10 +++--- .../run-make/const-trait-stable-toolchain/rmake.rs | 10 ++---- tests/ui/consts/const-try.rs | 4 +-- tests/ui/consts/const-try.stderr | 8 ++--- tests/ui/consts/rustc-impl-const-stability.stderr | 4 +-- tests/ui/specialization/const_trait_impl.stderr | 24 +++++++------- .../stability-attribute/missing-const-stability.rs | 3 +- .../missing-const-stability.stderr | 6 ++-- .../conditionally-const-invalid-places.stderr | 8 ++--- .../const-traits/const-bounds-non-const-trait.rs | 6 ++-- .../const-bounds-non-const-trait.stderr | 12 +++---- .../const-impl-requires-const-trait.rs | 2 +- .../const-impl-requires-const-trait.stderr | 6 ++-- .../const-trait-bounds-trait-objects.rs | 8 ++--- .../const-trait-bounds-trait-objects.stderr | 20 ++++++------ .../const_derives/derive-const-gate.rs | 2 +- .../const_derives/derive-const-gate.stderr | 4 +-- .../derive-const-non-const-type.stderr | 4 +-- .../const-traits/ice-119717-constant-lifetime.rs | 2 +- .../ice-119717-constant-lifetime.stderr | 4 +-- .../const-traits/ice-126148-failed-to-normalize.rs | 4 +-- .../ice-126148-failed-to-normalize.stderr | 8 ++--- tests/ui/traits/const-traits/spec-effectvar-ice.rs | 6 ++-- .../traits/const-traits/spec-effectvar-ice.stderr | 16 ++++----- .../const-traits/super-traits-fail-2.nn.stderr | 14 ++++---- .../const-traits/super-traits-fail-2.ny.stderr | 20 ++++++------ .../ui/traits/const-traits/super-traits-fail-2.rs | 10 +++--- .../const-traits/super-traits-fail-2.yn.stderr | 2 +- .../const-traits/super-traits-fail-3.nnn.stderr | 22 ++++++------- .../const-traits/super-traits-fail-3.nny.stderr | 22 ++++++------- .../ui/traits/const-traits/super-traits-fail-3.rs | 14 ++++---- .../const-traits/super-traits-fail-3.ynn.stderr | 22 ++++++------- .../const-traits/super-traits-fail-3.yny.stderr | 20 ++++++------ .../const-traits/super-traits-fail-3.yyn.stderr | 10 +++--- .../trait-default-body-stability.stderr | 8 ++--- 94 files changed, 365 insertions(+), 299 deletions(-) (limited to 'compiler/rustc_lint/src') diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index fa542a810dc..8c2b521c560 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3690,6 +3690,7 @@ impl Default for FnHeader { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Trait { + pub constness: Const, pub safety: Safety, pub is_auto: IsAuto, pub ident: Ident, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 37fcc0d2167..a344f23c345 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -738,7 +738,8 @@ macro_rules! common_visitor_and_walkers { try_visit!(vis.visit_ty(self_ty)); visit_assoc_items(vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() }) } - ItemKind::Trait(box Trait { safety, is_auto: _, ident, generics, bounds, items }) => { + ItemKind::Trait(box Trait { constness, safety, is_auto: _, ident, generics, bounds, items }) => { + try_visit!(visit_constness(vis, constness)); try_visit!(visit_safety(vis, safety)); try_visit!(vis.visit_ident(ident)); try_visit!(vis.visit_generics(generics)); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9d40a7386f6..abd70c7517c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -417,7 +417,16 @@ impl<'hir> LoweringContext<'_, 'hir> { items: new_impl_items, })) } - ItemKind::Trait(box Trait { is_auto, safety, ident, generics, bounds, items }) => { + ItemKind::Trait(box Trait { + constness, + is_auto, + safety, + ident, + generics, + bounds, + items, + }) => { + let constness = self.lower_constness(*constness); let ident = self.lower_ident(*ident); let (generics, (safety, items, bounds)) = self.lower_generics( generics, @@ -435,7 +444,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (safety, items, bounds) }, ); - hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items) + hir::ItemKind::Trait(constness, *is_auto, safety, ident, generics, bounds, items) } ItemKind::TraitAlias(ident, generics, bounds) => { let ident = self.lower_ident(*ident); diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index c5780c957c9..e419154d65d 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -240,10 +240,10 @@ ast_passes_static_without_body = ast_passes_tilde_const_disallowed = `[const]` is not allowed here .closure = closures cannot have `[const]` trait bounds .function = this function is not `const`, so it cannot have `[const]` trait bounds - .trait = this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds + .trait = this trait is not `const`, so it cannot have `[const]` trait bounds .trait_impl = this impl is not `const`, so it cannot have `[const]` trait bounds .impl = inherent impls cannot have `[const]` trait bounds - .trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `[const]` trait bounds + .trait_assoc_ty = associated types in non-`const` traits cannot have `[const]` trait bounds .trait_impl_assoc_ty = associated types in non-const impls cannot have `[const]` trait bounds .inherent_assoc_ty = inherent associated types cannot have `[const]` trait bounds .object = trait objects cannot have `[const]` trait bounds diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 38889d28151..c69250c0305 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -49,14 +49,14 @@ enum SelfSemantic { } enum TraitOrTraitImpl { - Trait { span: Span, constness_span: Option }, + Trait { span: Span, constness: Const }, TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref_span: Span }, } impl TraitOrTraitImpl { fn constness(&self) -> Option { match self { - Self::Trait { constness_span: Some(span), .. } + Self::Trait { constness: Const::Yes(span), .. } | Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span), _ => None, } @@ -110,15 +110,10 @@ impl<'a> AstValidator<'a> { self.outer_trait_or_trait_impl = old; } - fn with_in_trait( - &mut self, - span: Span, - constness_span: Option, - f: impl FnOnce(&mut Self), - ) { + fn with_in_trait(&mut self, span: Span, constness: Const, f: impl FnOnce(&mut Self)) { let old = mem::replace( &mut self.outer_trait_or_trait_impl, - Some(TraitOrTraitImpl::Trait { span, constness_span }), + Some(TraitOrTraitImpl::Trait { span, constness }), ); f(self); self.outer_trait_or_trait_impl = old; @@ -273,7 +268,7 @@ impl<'a> AstValidator<'a> { }; let make_trait_const_sugg = if const_trait_impl - && let TraitOrTraitImpl::Trait { span, constness_span: None } = parent + && let TraitOrTraitImpl::Trait { span, constness: ast::Const::No } = parent { Some(span.shrink_to_lo()) } else { @@ -1131,10 +1126,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } visit::walk_item(self, item) } - ItemKind::Trait(box Trait { is_auto, generics, ident, bounds, items, .. }) => { + ItemKind::Trait(box Trait { + constness, + is_auto, + generics, + ident, + bounds, + items, + .. + }) => { self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); - let is_const_trait = + // FIXME(const_trait_impl) remove this + let alt_const_trait_span = attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span); + let constness = match (*constness, alt_const_trait_span) { + (Const::Yes(span), _) | (Const::No, Some(span)) => Const::Yes(span), + (Const::No, None) => Const::No, + }; if *is_auto == IsAuto::Yes { // Auto traits cannot have generics, super traits nor contain items. self.deny_generic_params(generics, ident.span); @@ -1145,13 +1153,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound // context for the supertraits. - let disallowed = - is_const_trait.is_none().then(|| TildeConstReason::Trait { span: item.span }); + let disallowed = matches!(constness, ast::Const::No) + .then(|| TildeConstReason::Trait { span: item.span }); self.with_tilde_const(disallowed, |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) }); - self.with_in_trait(item.span, is_const_trait, |this| { + self.with_in_trait(item.span, constness, |this| { walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); }); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 3b2730d4ff9..c1ebd025c7a 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -590,7 +590,7 @@ pub(crate) struct ConstBoundTraitObject { } // FIXME(const_trait_impl): Consider making the note/reason the message of the diagnostic. -// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here). +// FIXME(const_trait_impl): Provide structured suggestions (e.g., add `const` here). #[derive(Diagnostic)] #[diag(ast_passes_tilde_const_disallowed)] pub(crate) struct TildeConstDisallowed { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 6c442553976..11c97a552c6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -357,6 +357,7 @@ impl<'a> State<'a> { self.bclose(item.span, empty, cb); } ast::ItemKind::Trait(box ast::Trait { + constness, safety, is_auto, ident, @@ -366,6 +367,7 @@ impl<'a> State<'a> { }) => { let (cb, ib) = self.head(""); self.print_visibility(&item.vis); + self.print_constness(*constness); self.print_safety(*safety); self.print_is_auto(*is_auto); self.word_nbsp("trait"); diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index d5e088effd5..e69a533699b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -91,6 +91,7 @@ impl NoArgsAttributeParser for DoNotImplementViaObjectParser { const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject; } +// FIXME(const_trait_impl): remove this // Const traits pub(crate) struct ConstTraitParser; diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index 9ab8e0692e1..ebf18c6f2ac 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -93,7 +93,7 @@ pub fn rustc_allow_const_fn_unstable( /// world into two functions: those that are safe to expose on stable (and hence may not use /// unstable features, not even recursively), and those that are not. pub fn is_fn_or_trait_safe_to_expose_on_stable(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - // A default body in a `#[const_trait]` is const-stable when the trait is const-stable. + // A default body in a `const trait` is const-stable when the trait is const-stable. if tcx.is_const_default_method(def_id) { return is_fn_or_trait_safe_to_expose_on_stable(tcx, tcx.parent(def_id)); } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 70ad57b2b11..f24fb18f83b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -363,8 +363,8 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { if let ty::InstanceKind::Item(def) = instance.def { // Execution might have wandered off into other crates, so we cannot do a stability- // sensitive check here. But we can at least rule out functions that are not const at - // all. That said, we have to allow calling functions inside a trait marked with - // #[const_trait]. These *are* const-checked! + // all. That said, we have to allow calling functions inside a `const trait`. These + // *are* const-checked! if !ecx.tcx.is_const_fn(def) || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check) { // We certainly do *not* want to actually call the fn // though, so be sure we return here. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e2827f227ab..74872504b79 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -614,6 +614,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // RFC 2632 + // FIXME(const_trait_impl) remove this gated!( const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl, "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \ diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ace2259aec3..e7898648c2b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4163,6 +4163,7 @@ impl<'hir> Item<'hir> { expect_trait, ( + Constness, IsAuto, Safety, Ident, @@ -4170,8 +4171,8 @@ impl<'hir> Item<'hir> { GenericBounds<'hir>, &'hir [TraitItemId] ), - ItemKind::Trait(is_auto, safety, ident, generics, bounds, items), - (*is_auto, *safety, *ident, generics, bounds, items); + ItemKind::Trait(constness, is_auto, safety, ident, generics, bounds, items), + (*constness, *is_auto, *safety, *ident, generics, bounds, items); expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>), ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds); @@ -4341,7 +4342,15 @@ pub enum ItemKind<'hir> { /// A union definition, e.g., `union Foo {x: A, y: B}`. Union(Ident, &'hir Generics<'hir>, VariantData<'hir>), /// A trait definition. - Trait(IsAuto, Safety, Ident, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemId]), + Trait( + Constness, + IsAuto, + Safety, + Ident, + &'hir Generics<'hir>, + GenericBounds<'hir>, + &'hir [TraitItemId], + ), /// A trait alias. TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>), @@ -4385,7 +4394,7 @@ impl ItemKind<'_> { | ItemKind::Enum(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Union(ident, ..) - | ItemKind::Trait(_, _, ident, ..) + | ItemKind::Trait(_, _, _, ident, ..) | ItemKind::TraitAlias(ident, ..) => Some(ident), ItemKind::Use(_, UseKind::Glob | UseKind::ListStem) @@ -4403,7 +4412,7 @@ impl ItemKind<'_> { | ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _) | ItemKind::Union(_, generics, _) - | ItemKind::Trait(_, _, _, generics, _, _) + | ItemKind::Trait(_, _, _, _, generics, _, _) | ItemKind::TraitAlias(_, generics, _) | ItemKind::Impl(Impl { generics, .. }) => generics, _ => return None, diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3edb94c28da..f33915d5b07 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -618,7 +618,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_variant_data(struct_definition)); } - ItemKind::Trait(_is_auto, _safety, ident, ref generics, bounds, trait_item_refs) => { + ItemKind::Trait( + _constness, + _is_auto, + _safety, + ident, + ref generics, + bounds, + trait_item_refs, + ) => { try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 529d3578985..a20becbe7e8 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -117,15 +117,15 @@ hir_analysis_coercion_between_struct_same_note = expected coercion between the s hir_analysis_coercion_between_struct_single_note = expected a single field to be coerced, none found -hir_analysis_const_bound_for_non_const_trait = `{$modifier}` can only be applied to `#[const_trait]` traits +hir_analysis_const_bound_for_non_const_trait = `{$modifier}` can only be applied to `const` traits .label = can't be applied to `{$trait_name}` - .note = `{$trait_name}` can't be used with `{$modifier}` because it isn't annotated with `#[const_trait]` - .suggestion = {$suggestion_pre}mark `{$trait_name}` as `#[const_trait]` to allow it to have `const` implementations + .note = `{$trait_name}` can't be used with `{$modifier}` because it isn't `const` + .suggestion = {$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations -hir_analysis_const_impl_for_non_const_trait = const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]` +hir_analysis_const_impl_for_non_const_trait = const `impl` for trait `{$trait_name}` which is not `const` .label = this trait is not `const` - .suggestion = {$suggestion_pre}mark `{$trait_name}` as `#[const_trait]` to allow it to have `const` implementations - .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const` + .suggestion = {$suggestion_pre}mark `{$trait_name}` as `const` to allow it to have `const` implementations + .note = marking a trait with `const` ensures all default method bodies are `const` .adding = adding a non-const method body in the future would be a breaking change hir_analysis_const_param_ty_impl_on_non_adt = diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 28a8758178f..0728b24eb14 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -844,15 +844,20 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { let item = tcx.hir_expect_item(def_id); - let (is_alias, is_auto, safety) = match item.kind { - hir::ItemKind::Trait(is_auto, safety, ..) => (false, is_auto == hir::IsAuto::Yes, safety), - hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe), + let (constness, is_alias, is_auto, safety) = match item.kind { + hir::ItemKind::Trait(constness, is_auto, safety, ..) => { + (constness, false, is_auto == hir::IsAuto::Yes, safety) + } + hir::ItemKind::TraitAlias(..) => (hir::Constness::NotConst, true, false, hir::Safety::Safe), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; let attrs = tcx.get_all_attrs(def_id); // Only regular traits can be const. - let constness = if !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_)) { + // FIXME(const_trait_impl): remove this + let constness = if constness == hir::Constness::Const + || !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_)) + { hir::Constness::Const } else { hir::Constness::NotConst diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index af78130899e..f2f1560d8b2 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -163,7 +163,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen .map(|t| ty::Binder::dummy(t.instantiate_identity())); } } - ItemKind::Trait(_, _, _, _, self_bounds, ..) + ItemKind::Trait(_, _, _, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, _, self_bounds) => { is_trait = Some((self_bounds, item.span)); } @@ -1022,7 +1022,7 @@ pub(super) fn const_conditions<'tcx>( Node::Item(item) => match item.kind { hir::ItemKind::Impl(impl_) => (impl_.generics, None, false), hir::ItemKind::Fn { generics, .. } => (generics, None, false), - hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => { + hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => { (generics, Some((item.owner_id.def_id, supertraits)), false) } _ => bug!("const_conditions called on wrong item: {def_id:?}"), 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 8d7ac7db67b..77e63e38c8c 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -634,7 +634,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | hir::ItemKind::Enum(_, generics, _) | hir::ItemKind::Struct(_, generics, _) | hir::ItemKind::Union(_, generics, _) - | hir::ItemKind::Trait(_, _, _, generics, ..) + | hir::ItemKind::Trait(_, _, _, _, generics, ..) | hir::ItemKind::TraitAlias(_, generics, ..) | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index c1c82839212..eb65050c17c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -525,6 +525,7 @@ pub(crate) struct ConstImplForNonConstTrait { pub trait_name: String, #[suggestion( applicability = "machine-applicable", + // FIXME(const_trait_impl) fix this suggestion code = "#[const_trait] ", style = "verbose" )] @@ -548,6 +549,7 @@ pub(crate) struct ConstBoundForNonConstTrait { pub suggestion_pre: &'static str, #[suggestion( applicability = "machine-applicable", + // FIXME(const_trait_impl) fix this suggestion code = "#[const_trait] ", style = "verbose" )] diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 3f928fd056e..2d60c9561a9 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -635,7 +635,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { self.suggest_adding_type_and_const_args(err); } ExcessTypesOrConsts { .. } => { - // this can happen with `[const] T` where T isn't a const_trait. + // this can happen with `[const] T` where T isn't a `const trait`. } _ => unreachable!(), } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 4784cfb5235..9a752aeccdd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -334,7 +334,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; let (trait_generics, trait_bounds) = match parent_trait.kind { - hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => (generics, supertraits), + hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => (generics, supertraits), hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), _ => unreachable!(), }; diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 2c13c9ef438..bda02042aa6 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -735,8 +735,17 @@ impl<'a> State<'a> { } self.bclose(item.span, cb); } - hir::ItemKind::Trait(is_auto, safety, ident, generics, bounds, trait_items) => { + hir::ItemKind::Trait( + constness, + is_auto, + safety, + ident, + generics, + bounds, + trait_items, + ) => { let (cb, ib) = self.head(""); + self.print_constness(constness); self.print_is_auto(is_auto); self.print_safety(safety); self.word_nbsp("trait"); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 2815621ffde..dbfa7e6273c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1189,7 +1189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.1.insert((self_ty.span, "")); } Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..), + kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..), span: item_span, .. })) => { @@ -1201,7 +1201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some( Node::Item(hir::Item { kind: - hir::ItemKind::Trait(_, _, ident, ..) + hir::ItemKind::Trait(_, _, _, ident, ..) | hir::ItemKind::TraitAlias(ident, ..), .. }) @@ -4084,7 +4084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, ident, _, bounds, _), + kind: hir::ItemKind::Trait(_, _, _, ident, _, bounds, _), .. }) => { let (sp, sep, article) = if bounds.is_empty() { diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 3cc55eaa0f2..5513c703f1d 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -39,7 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { let def_id = item.owner_id.to_def_id(); // NOTE(nbdd0121): use `dyn_compatibility_violations` instead of `is_dyn_compatible` because // the latter will report `where_clause_object_safety` lint. - if let hir::ItemKind::Trait(_, _, ident, ..) = item.kind + if let hir::ItemKind::Trait(_, _, _, ident, ..) = item.kind && cx.tcx.is_dyn_compatible(def_id) { let direct_super_traits_iter = cx diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b50453cb0df..5cd98038fc6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1131,7 +1131,7 @@ fn should_encode_mir( && reachable_set.contains(&def_id) && (generics.requires_monomorphization(tcx) || tcx.cross_crate_inlinable(def_id))); - // The function has a `const` modifier or is in a `#[const_trait]`. + // The function has a `const` modifier or is in a `const trait`. let is_const_fn = tcx.is_const_fn(def_id.to_def_id()) || tcx.is_const_default_method(def_id.to_def_id()); (is_const_fn, opt) diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 84710e5e636..42a1e7377f4 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -940,7 +940,7 @@ impl<'tcx> TyCtxt<'tcx> { }) => until_within(*outer_span, ty.span), // With generics and bounds. Node::Item(Item { - kind: ItemKind::Trait(_, _, _, generics, bounds, _), + kind: ItemKind::Trait(_, _, _, _, generics, bounds, _), span: outer_span, .. }) diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index ea25ce65f77..59e2b2a034d 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -20,7 +20,7 @@ pub struct TraitDef { pub safety: hir::Safety, - /// Whether this trait has been annotated with `#[const_trait]`. + /// Whether this trait is `const`. pub constness: hir::Constness, /// If `true`, then this trait had the `#[rustc_paren_sugar]` diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index af9f8735549..859118a4ade 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -855,6 +855,7 @@ parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern .suggestion = remove the `{$token}` parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` +parse_trait_alias_cannot_be_const = trait aliases cannot be `const` parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 7f1b0991f0c..4aaaba01fae 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1961,6 +1961,14 @@ pub(crate) struct TraitAliasCannotBeAuto { pub span: Span, } +#[derive(Diagnostic)] +#[diag(parse_trait_alias_cannot_be_const)] +pub(crate) struct TraitAliasCannotBeConst { + #[primary_span] + #[label(parse_trait_alias_cannot_be_const)] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_trait_alias_cannot_be_unsafe)] pub(crate) struct TraitAliasCannotBeUnsafe { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index d6cc98d505c..b767b0fcf99 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -244,6 +244,9 @@ impl<'a> Parser<'a> { self.bump(); // `static` let mutability = self.parse_mutability(); self.parse_static_item(safety, mutability)? + } else if self.check_keyword(exp!(Trait)) || self.check_trait_front_matter() { + // TRAIT ITEM + self.parse_item_trait(attrs, lo)? } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM if self.token.is_keyword(kw::Impl) { @@ -262,9 +265,6 @@ impl<'a> Parser<'a> { define_opaque: None, })) } - } else if self.check_keyword(exp!(Trait)) || self.check_auto_or_unsafe_trait_item() { - // TRAIT ITEM - self.parse_item_trait(attrs, lo)? } else if self.check_keyword(exp!(Impl)) || self.check_keyword(exp!(Unsafe)) && self.is_keyword_ahead(1, &[kw::Impl]) { @@ -373,7 +373,7 @@ impl<'a> Parser<'a> { pub(super) fn is_path_start_item(&mut self) -> bool { self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }` || self.is_reuse_path_item() - || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` + || self.check_trait_front_matter() // no: `auto::b`, yes: `auto trait X { .. }` || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` || matches!(self.is_macro_rules_item(), IsMacroRulesItem::Yes{..}) // no: `macro_rules::b`, yes: `macro_rules! mac` } @@ -872,16 +872,19 @@ impl<'a> Parser<'a> { } } - /// Is this an `(unsafe auto? | auto) trait` item? - fn check_auto_or_unsafe_trait_item(&mut self) -> bool { + /// Is this an `(const unsafe? auto?| unsafe auto? | auto) trait` item? + fn check_trait_front_matter(&mut self) -> bool { // auto trait self.check_keyword(exp!(Auto)) && self.is_keyword_ahead(1, &[kw::Trait]) // unsafe auto trait || self.check_keyword(exp!(Unsafe)) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) + || self.check_keyword(exp!(Const)) && ((self.is_keyword_ahead(1, &[kw::Trait]) || self.is_keyword_ahead(1, &[kw::Auto]) && self.is_keyword_ahead(2, &[kw::Trait])) + || self.is_keyword_ahead(1, &[kw::Unsafe]) && self.is_keyword_ahead(2, &[kw::Trait, kw::Auto])) } /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemKind> { + let constness = self.parse_constness(Case::Sensitive); let safety = self.parse_safety(Case::Sensitive); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(exp!(Auto)) { @@ -913,6 +916,9 @@ impl<'a> Parser<'a> { self.expect_semi()?; let whole_span = lo.to(self.prev_token.span); + if let Const::Yes(_) = constness { + self.dcx().emit_err(errors::TraitAliasCannotBeConst { span: whole_span }); + } if is_auto == IsAuto::Yes { self.dcx().emit_err(errors::TraitAliasCannotBeAuto { span: whole_span }); } @@ -927,7 +933,15 @@ impl<'a> Parser<'a> { // It's a normal trait. generics.where_clause = self.parse_where_clause()?; let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?; - Ok(ItemKind::Trait(Box::new(Trait { is_auto, safety, ident, generics, bounds, items }))) + Ok(ItemKind::Trait(Box::new(Trait { + constness, + is_auto, + safety, + ident, + generics, + bounds, + items, + }))) } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 500b4279588..d1b856ca415 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -784,7 +784,7 @@ passes_unused_capture_maybe_capture_ref = value captured by `{$name}` is never r .help = did you mean to capture by reference instead? passes_unused_default_method_body_const_note = - `default_method_body_is_const` has been replaced with `#[const_trait]` on traits + `default_method_body_is_const` has been replaced with `const` on traits passes_unused_duplicate = unused attribute diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1285e0ddf8e..d8ffcedeb88 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1160,7 +1160,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match item.kind { ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _) if generics.params.len() != 0 => {} - ItemKind::Trait(_, _, _, generics, _, items) + ItemKind::Trait(_, _, _, _, generics, _, items) if generics.params.len() != 0 || items.iter().any(|item| { matches!(self.tcx.def_kind(item.owner_id), DefKind::AssocTy) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index d4cc1ceb280..1d8b934cef3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -453,7 +453,7 @@ pub fn report_dyn_incompatibility<'tcx>( let trait_str = tcx.def_path_str(trait_def_id); let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node { hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(_, _, ident, ..) | hir::ItemKind::TraitAlias(ident, _, _) => { + hir::ItemKind::Trait(_, _, _, ident, ..) | hir::ItemKind::TraitAlias(ident, _, _) => { Some(ident.span) } _ => unreachable!(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index bd1d29826e6..cbbfad663db 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -267,7 +267,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let node = self.tcx.hir_node_by_def_id(body_id); match node { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, ident, generics, bounds, _), + kind: hir::ItemKind::Trait(_, _, _, ident, generics, bounds, _), .. }) if self_ty == self.tcx.types.self_param => { assert!(param_ty); @@ -330,7 +330,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } hir::Node::Item(hir::Item { kind: - hir::ItemKind::Trait(_, _, _, generics, ..) + hir::ItemKind::Trait(_, _, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }), .. }) if projection.is_some() => { @@ -354,7 +354,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { hir::ItemKind::Struct(_, generics, _) | hir::ItemKind::Enum(_, generics, _) | hir::ItemKind::Union(_, generics, _) - | hir::ItemKind::Trait(_, _, _, generics, ..) + | hir::ItemKind::Trait(_, _, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Fn { generics, .. } | hir::ItemKind::TyAlias(_, generics, _) @@ -414,7 +414,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { hir::ItemKind::Struct(_, generics, _) | hir::ItemKind::Enum(_, generics, _) | hir::ItemKind::Union(_, generics, _) - | hir::ItemKind::Trait(_, _, _, generics, ..) + | hir::ItemKind::Trait(_, _, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Fn { generics, .. } | hir::ItemKind::TyAlias(_, generics, _) @@ -3436,7 +3436,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut is_auto_trait = false; match tcx.hir_get_if_local(data.impl_or_alias_def_id) { Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(is_auto, _, ident, ..), + kind: hir::ItemKind::Trait(_, is_auto, _, ident, ..), .. })) => { // FIXME: we should do something else so that it works even on crate foreign diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 90cdf75265d..7901d52dffb 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -534,7 +534,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope)) { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, _, generics, ..), + kind: hir::ItemKind::Trait(_, _, _, _, generics, ..), .. }) | hir::Node::Item(hir::Item { diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index c7aa2714668..87b0103a7bc 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -67,10 +67,8 @@ in [`wfcheck::check_impl`]. Here's an example: ```rust -#[const_trait] -trait Bar {} -#[const_trait] -trait Foo: ~const Bar {} +const trait Bar {} +const trait Foo: ~const Bar {} // `const_conditions` contains `HostEffect(Self: Bar, maybe)` impl const Bar for () {} @@ -85,8 +83,7 @@ predicates of the trait method, and we attempt to prove the predicates of the impl method. We do the same for `const_conditions`: ```rust -#[const_trait] -trait Foo { +const trait Foo { fn hi(); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3df04091f16..1265a39d27b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2865,7 +2865,7 @@ fn clean_maybe_renamed_item<'tcx>( ItemKind::Fn { ref sig, generics, body: body_id, .. } => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } - ItemKind::Trait(_, _, _, generics, bounds, item_ids) => { + ItemKind::Trait(_, _, _, _, generics, bounds, item_ids) => { let items = item_ids .iter() .map(|&ti| clean_trait_item(cx.tcx.hir_trait_item(ti), cx)) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 20babc6168b..09647492d93 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -648,7 +648,7 @@ impl Item { let sig = tcx.fn_sig(def_id).skip_binder(); let constness = if tcx.is_const_fn(def_id) { // rustc's `is_const_fn` returns `true` for associated functions that have an `impl const` parent - // or that have a `#[const_trait]` parent. Do not display those as `const` in rustdoc because we + // or that have a `const trait` parent. Do not display those as `const` in rustdoc because we // won't be printing correct syntax plus the syntax is unstable. match tcx.opt_associated_item(def_id) { Some(ty::AssocItem { diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index 07df893ae3c..a9d3015ce5c 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -306,7 +306,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { cur_f = Some(field); } }, - ItemKind::Trait(is_auto, _safety, _ident, _generics, _generic_bounds, item_ref) + ItemKind::Trait(_constness, is_auto, _safety, _ident, _generics, _generic_bounds, item_ref) if self.enable_ordering_for_trait && *is_auto == IsAuto::No => { let mut cur_t: Option<(TraitItemId, Ident)> = None; diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 2bf52216b83..22b781b8929 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -740,7 +740,7 @@ impl<'tcx> LateLintPass<'tcx> for Documentation { ); } }, - ItemKind::Trait(_, unsafety, ..) => match (headers.safety, unsafety) { + ItemKind::Trait(_, _, unsafety, ..) => match (headers.safety, unsafety) { (false, Safety::Unsafe) => span_lint( cx, MISSING_SAFETY_DOC, diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index d32017a8b41..1bf03480c82 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -125,7 +125,7 @@ declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMP impl<'tcx> LateLintPass<'tcx> for LenZero { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Trait(_, _, ident, _, _, trait_items) = item.kind + if let ItemKind::Trait(_, _, _, ident, _, _, trait_items) = item.kind && !item.span.from_expansion() { check_trait_items(cx, item, ident, trait_items); diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 329f7193437..c4a3d10299b 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let attrs = cx.tcx.hir_attrs(it.hir_id()); check_missing_inline_attrs(cx, attrs, it.span, desc); }, - hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _ident, _generics, _bounds, trait_items) => { + hir::ItemKind::Trait(ref _constness, ref _is_auto, ref _unsafe, _ident, _generics, _bounds, trait_items) => { // note: we need to check if the trait is exported so we can't use // `LateLintPass::check_trait_item` here. for &tit in trait_items { diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 45e54302e32..9182a55081f 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // special handling for self trait bounds as these are not considered generics // ie. trait Foo: Display {} if let Item { - kind: ItemKind::Trait(_, _, _, _, bounds, ..), + kind: ItemKind::Trait(_, _, _, _, _, bounds, ..), .. } = item { @@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { .. }) = segments.first() && let Some(Node::Item(Item { - kind: ItemKind::Trait(_, _, _, _, self_bounds, _), + kind: ItemKind::Trait(_, _, _, _, _, self_bounds, _), .. })) = cx.tcx.hir_get_if_local(*def_id) { diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 02281b9e922..944cd91a7fd 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -131,7 +131,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms { return; } match it.kind { - ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, ident, ..) => { + ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, _, ident, ..) => { check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive); }, ItemKind::Enum(ident, _, ref enumdef) => { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 42254ec8e92..96f0273c439 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -444,6 +444,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { }, ( Trait(box ast::Trait { + constness: lc, is_auto: la, safety: lu, ident: li, @@ -452,6 +453,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { items: lis, }), Trait(box ast::Trait { + constness: rc, is_auto: ra, safety: ru, ident: ri, @@ -460,7 +462,8 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { items: ris, }), ) => { - la == ra + matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) + && la == ra && matches!(lu, Safety::Default) == matches!(ru, Safety::Default) && eq_id(*li, *ri) && eq_generics(lg, rg) diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index ce61fffe0de..dc31ed08fb7 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -252,11 +252,11 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { ItemKind::Struct(_, _, VariantData::Struct { .. }) => (Pat::Str("struct"), Pat::Str("}")), ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")), ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), - ItemKind::Trait(_, Safety::Unsafe, ..) + ItemKind::Trait(_, _, Safety::Unsafe, ..) | ItemKind::Impl(Impl { safety: Safety::Unsafe, .. }) => (Pat::Str("unsafe"), Pat::Str("}")), - ItemKind::Trait(IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")), + ItemKind::Trait(_, IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")), ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")), ItemKind::Impl(_) => (Pat::Str("impl"), Pat::Str("}")), _ => return (Pat::Str(""), Pat::Str("")), diff --git a/src/tools/clippy/tests/ui/assign_ops.fixed b/src/tools/clippy/tests/ui/assign_ops.fixed index 99beea850a2..eee61f949e7 100644 --- a/src/tools/clippy/tests/ui/assign_ops.fixed +++ b/src/tools/clippy/tests/ui/assign_ops.fixed @@ -84,8 +84,7 @@ mod issue14871 { const ONE: Self; } - #[const_trait] - pub trait NumberConstants { + pub const trait NumberConstants { fn constant(value: usize) -> Self; } diff --git a/src/tools/clippy/tests/ui/assign_ops.rs b/src/tools/clippy/tests/ui/assign_ops.rs index 900d5ad38e0..13ffcee0a3c 100644 --- a/src/tools/clippy/tests/ui/assign_ops.rs +++ b/src/tools/clippy/tests/ui/assign_ops.rs @@ -84,8 +84,7 @@ mod issue14871 { const ONE: Self; } - #[const_trait] - pub trait NumberConstants { + pub const trait NumberConstants { fn constant(value: usize) -> Self; } diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.fixed b/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.fixed index f1d5579a723..c113c1caaa6 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.fixed +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.fixed @@ -3,8 +3,7 @@ // Reduced test case from https://github.com/rust-lang/rust-clippy/issues/14658 -#[const_trait] -trait ConstTrait { +const trait ConstTrait { fn method(self); } diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.rs index d495759526d..69248bc52d5 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.rs @@ -3,8 +3,7 @@ // Reduced test case from https://github.com/rust-lang/rust-clippy/issues/14658 -#[const_trait] -trait ConstTrait { +const trait ConstTrait { fn method(self); } diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.stderr index b994b88fac6..7ea009cfc9b 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.stderr +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/const_trait.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/const_trait.rs:24:1 + --> tests/ui/missing_const_for_fn/const_trait.rs:23:1 | LL | / fn can_be_const() { LL | | 0u64.method(); diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed index cf52ecf2f03..88ba5f810b4 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed @@ -167,8 +167,7 @@ where } // #13476 -#[const_trait] -trait ConstTrait {} +const trait ConstTrait {} const fn const_trait_bounds_good() {} const fn const_trait_bounds_bad() {} diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs index 955562f08dc..19a4e70e294 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs @@ -167,8 +167,7 @@ where } // #13476 -#[const_trait] -trait ConstTrait {} +const trait ConstTrait {} const fn const_trait_bounds_good() {} const fn const_trait_bounds_bad() {} diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr index ab31721ef51..a56a683de97 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr @@ -59,19 +59,19 @@ LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) { | ^^^^^^^^^^^^^^^^^ help: try: `Any + Send` error: these bounds contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:174:36 + --> tests/ui/trait_duplication_in_bounds.rs:173:36 | LL | const fn const_trait_bounds_bad() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[const] ConstTrait` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:181:8 + --> tests/ui/trait_duplication_in_bounds.rs:180:8 | LL | T: IntoIterator + IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `IntoIterator` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:203:8 + --> tests/ui/trait_duplication_in_bounds.rs:202:8 | LL | T: AssocConstTrait + AssocConstTrait, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait` 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 dc1eba1a1ab..e5d8f78d948 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -1011,8 +1011,7 @@ pub mod ops { } #[lang = "add_assign"] - #[const_trait] - pub trait AddAssign { + pub const trait AddAssign { fn add_assign(&mut self, rhs: Rhs); } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 1a3897b51cb..7084639aca9 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1172,6 +1172,7 @@ pub(crate) fn format_trait( unreachable!(); }; let ast::Trait { + constness, is_auto, safety, ident, @@ -1182,7 +1183,8 @@ pub(crate) fn format_trait( let mut result = String::with_capacity(128); let header = format!( - "{}{}{}trait ", + "{}{}{}{}trait ", + format_constness(constness), format_visibility(context, &item.vis), format_safety(safety), format_auto(is_auto), diff --git a/tests/crashes/117629.rs b/tests/crashes/117629.rs index d8b5f328545..f63365395c6 100644 --- a/tests/crashes/117629.rs +++ b/tests/crashes/117629.rs @@ -3,8 +3,7 @@ #![feature(const_trait_impl)] -#[const_trait] -trait Tr { +const trait Tr { async fn ft1() {} } diff --git a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr index 5ce815b9aed..464208f989e 100644 --- a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr +++ b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-disabled.stderr @@ -4,7 +4,7 @@ error: `[const]` is not allowed here LL | trait Bar: ~const Foo {} | ^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> const-super-trait.rs:7:1 | LL | trait Bar: ~const Foo {} @@ -30,24 +30,24 @@ LL | const fn foo(x: &T) { = help: add `#![feature(const_trait_impl)]` 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: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:7:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ can't be applied to `Foo` | -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:9:17 | LL | const fn foo(x: &T) { | ^^^^^^ can't be applied to `Bar` | -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: ~const Foo {} | ++++++++++++++ diff --git a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr index ef764a62b06..569e559186f 100644 --- a/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr +++ b/tests/run-make/const-trait-stable-toolchain/const-super-trait-nightly-enabled.stderr @@ -4,30 +4,30 @@ error: `[const]` is not allowed here LL | trait Bar: ~const Foo {} | ^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> const-super-trait.rs:7:1 | LL | trait Bar: ~const Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:7:12 | LL | trait Bar: ~const Foo {} | ^^^^^^ can't be applied to `Foo` | -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:9:17 | LL | const fn foo(x: &T) { | ^^^^^^ can't be applied to `Bar` | -help: mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: ~const Foo {} | ++++++++++++++ diff --git a/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-disabled.stderr b/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-disabled.stderr index 3dc147e076f..694e06fb6ea 100644 --- a/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-disabled.stderr +++ b/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-disabled.stderr @@ -4,7 +4,7 @@ error: `[const]` is not allowed here 7 | trait Bar: ~const Foo {} | ^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> const-super-trait.rs:7:1 | 7 | trait Bar: ~const Foo {} @@ -26,25 +26,25 @@ error[E0658]: const trait impls are experimental | = note: see issue #143874 for more information -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:7:12 | 7 | trait Bar: ~const Foo {} | ^^^^^^ can't be applied to `Foo` | -note: `Foo` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Foo` can't be used with `[const]` because it isn't `const` --> const-super-trait.rs:3:1 | 3 | trait Foo { | ^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:9:17 | 9 | const fn foo(x: &T) { | ^^^^^^ can't be applied to `Bar` | -note: `Bar` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Bar` can't be used with `[const]` because it isn't `const` --> const-super-trait.rs:7:1 | 7 | trait Bar: ~const Foo {} diff --git a/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-enabled.stderr b/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-enabled.stderr index 2cdeb277ca4..2109f0deb72 100644 --- a/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-enabled.stderr +++ b/tests/run-make/const-trait-stable-toolchain/const-super-trait-stable-enabled.stderr @@ -4,7 +4,7 @@ error: `[const]` is not allowed here 7 | trait Bar: ~const Foo {} | ^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> const-super-trait.rs:7:1 | 7 | trait Bar: ~const Foo {} @@ -16,25 +16,25 @@ error[E0554]: `#![feature]` may not be used on the NIGHTLY release channel 1 | #![cfg_attr(feature_enabled, feature(const_trait_impl))] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:7:12 | 7 | trait Bar: ~const Foo {} | ^^^^^^ can't be applied to `Foo` | -note: `Foo` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Foo` can't be used with `[const]` because it isn't `const` --> const-super-trait.rs:3:1 | 3 | trait Foo { | ^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> const-super-trait.rs:9:17 | 9 | const fn foo(x: &T) { | ^^^^^^ can't be applied to `Bar` | -note: `Bar` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Bar` can't be used with `[const]` because it isn't `const` --> const-super-trait.rs:7:1 | 7 | trait Bar: ~const Foo {} diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index 09a7c27a106..729b71457e9 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -11,9 +11,7 @@ fn main() { .env("RUSTC_BOOTSTRAP", "-1") .cfg("feature_enabled") .run_fail() - .assert_stderr_not_contains( - "as `#[const_trait]` to allow it to have `const` implementations", - ) + .assert_stderr_not_contains("as `const` to allow it to have `const` implementations") .stderr_utf8(); diff() .expected_file("const-super-trait-stable-enabled.stderr") @@ -29,7 +27,7 @@ fn main() { .ui_testing() .run_fail() .assert_stderr_not_contains("enable `#![feature(const_trait_impl)]` in your crate and mark") - .assert_stderr_contains("as `#[const_trait]` to allow it to have `const` implementations") + .assert_stderr_contains("as `const` to allow it to have `const` implementations") .stderr_utf8(); diff() .expected_file("const-super-trait-nightly-enabled.stderr") @@ -40,9 +38,7 @@ fn main() { .env("RUSTC_BOOTSTRAP", "-1") .run_fail() .assert_stderr_not_contains("enable `#![feature(const_trait_impl)]` in your crate and mark") - .assert_stderr_not_contains( - "as `#[const_trait]` to allow it to have `const` implementations", - ) + .assert_stderr_not_contains("as `const` to allow it to have `const` implementations") .stderr_utf8(); diff() .expected_file("const-super-trait-stable-disabled.stderr") diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs index 26aa9230a39..e13fad78441 100644 --- a/tests/ui/consts/const-try.rs +++ b/tests/ui/consts/const-try.rs @@ -13,14 +13,14 @@ struct TryMe; struct Error; impl const FromResidual for TryMe { - //~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + //~^ ERROR const `impl` for trait `FromResidual` which is not `const` fn from_residual(residual: Error) -> Self { TryMe } } impl const Try for TryMe { - //~^ ERROR const `impl` for trait `Try` which is not marked with `#[const_trait]` + //~^ ERROR const `impl` for trait `Try` which is not `const` type Output = (); type Residual = Error; fn from_output(output: Self::Output) -> Self { diff --git a/tests/ui/consts/const-try.stderr b/tests/ui/consts/const-try.stderr index 4209ca1d526..7004ea3e6db 100644 --- a/tests/ui/consts/const-try.stderr +++ b/tests/ui/consts/const-try.stderr @@ -1,19 +1,19 @@ -error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` +error: const `impl` for trait `FromResidual` which is not `const` --> $DIR/const-try.rs:15:12 | LL | impl const FromResidual for TryMe { | ^^^^^^^^^^^^^^^^^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: const `impl` for trait `Try` which is not marked with `#[const_trait]` +error: const `impl` for trait `Try` which is not `const` --> $DIR/const-try.rs:22:12 | LL | impl const Try for TryMe { | ^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error[E0015]: `?` is not allowed on `TryMe` in constant functions diff --git a/tests/ui/consts/rustc-impl-const-stability.stderr b/tests/ui/consts/rustc-impl-const-stability.stderr index a3ef4031a13..55c08539688 100644 --- a/tests/ui/consts/rustc-impl-const-stability.stderr +++ b/tests/ui/consts/rustc-impl-const-stability.stderr @@ -1,10 +1,10 @@ -error: const `impl` for trait `Debug` which is not marked with `#[const_trait]` +error: const `impl` for trait `Debug` which is not `const` --> $DIR/rustc-impl-const-stability.rs:15:12 | LL | impl const std::fmt::Debug for Data { | ^^^^^^^^^^^^^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error: aborting due to 1 previous error diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index b9c768812c8..a21a48997ee 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -1,57 +1,57 @@ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const_trait_impl.rs:36:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` | -note: `Debug` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const_trait_impl.rs:42:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` | -note: `Debug` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const_trait_impl.rs:48:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` | -note: `Debug` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const_trait_impl.rs:42:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` | -note: `Debug` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const_trait_impl.rs:36:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` | -note: `Debug` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const_trait_impl.rs:48:9 | LL | impl const A for T { | ^^^^^^^ can't be applied to `Debug` | -note: `Debug` can't be used with `[const]` because it isn't annotated with `#[const_trait]` +note: `Debug` can't be used with `[const]` because it isn't `const` --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs index c3e72e83948..8a37f19ffb0 100644 --- a/tests/ui/stability-attribute/missing-const-stability.rs +++ b/tests/ui/stability-attribute/missing-const-stability.rs @@ -20,8 +20,7 @@ impl Foo { } #[stable(feature = "stable", since = "1.0.0")] -#[const_trait] -pub trait Bar { +pub const trait Bar { //~^ ERROR trait has missing const stability attribute #[stable(feature = "stable", since = "1.0.0")] fn fun(); diff --git a/tests/ui/stability-attribute/missing-const-stability.stderr b/tests/ui/stability-attribute/missing-const-stability.stderr index 09461e6fb54..70a2450c53a 100644 --- a/tests/ui/stability-attribute/missing-const-stability.stderr +++ b/tests/ui/stability-attribute/missing-const-stability.stderr @@ -5,9 +5,9 @@ LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ error: trait has missing const stability attribute - --> $DIR/missing-const-stability.rs:24:1 + --> $DIR/missing-const-stability.rs:23:1 | -LL | / pub trait Bar { +LL | / pub const trait Bar { LL | | LL | | #[stable(feature = "stable", since = "1.0.0")] LL | | fn fun(); @@ -15,7 +15,7 @@ LL | | } | |_^ error: function has missing const stability attribute - --> $DIR/missing-const-stability.rs:37:1 + --> $DIR/missing-const-stability.rs:36:1 | LL | pub const unsafe fn size_of_val(x: *const T) -> usize { 42 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr b/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr index d0dd9502915..010b1584643 100644 --- a/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr +++ b/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr @@ -72,7 +72,7 @@ error: `[const]` is not allowed here LL | type Type: [const] Trait; | ^^^^^^^ | -note: associated types in non-`#[const_trait]` traits cannot have `[const]` trait bounds +note: associated types in non-`const` traits cannot have `[const]` trait bounds --> $DIR/conditionally-const-invalid-places.rs:25:5 | LL | type Type: [const] Trait; @@ -84,7 +84,7 @@ error: `[const]` is not allowed here LL | type Type: [const] Trait; | ^^^^^^^ | -note: associated types in non-`#[const_trait]` traits cannot have `[const]` trait bounds +note: associated types in non-`const` traits cannot have `[const]` trait bounds --> $DIR/conditionally-const-invalid-places.rs:25:5 | LL | type Type: [const] Trait; @@ -180,7 +180,7 @@ error: `[const]` is not allowed here LL | trait Child0: [const] Trait {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/conditionally-const-invalid-places.rs:52:1 | LL | trait Child0: [const] Trait {} @@ -192,7 +192,7 @@ error: `[const]` is not allowed here LL | trait Child1 where Self: [const] Trait {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/conditionally-const-invalid-places.rs:53:1 | LL | trait Child1 where Self: [const] Trait {} diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs index ae31d9ae0ac..baded179201 100644 --- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs +++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.rs @@ -4,10 +4,10 @@ trait NonConst {} const fn perform() {} -//~^ ERROR `[const]` can only be applied to `#[const_trait]` traits -//~| ERROR `[const]` can only be applied to `#[const_trait]` traits +//~^ ERROR `[const]` can only be applied to `const` traits +//~| ERROR `[const]` can only be applied to `const` traits fn operate() {} -//~^ ERROR `const` can only be applied to `#[const_trait]` traits +//~^ ERROR `const` can only be applied to `const` traits fn main() {} diff --git a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr index 6c68e4ec3ac..304d81bb917 100644 --- a/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr +++ b/tests/ui/traits/const-traits/const-bounds-non-const-trait.stderr @@ -1,33 +1,33 @@ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const-bounds-non-const-trait.rs:6:21 | LL | const fn perform() {} | ^^^^^^^ can't be applied to `NonConst` | -help: mark `NonConst` as `#[const_trait]` to allow it to have `const` implementations +help: mark `NonConst` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait NonConst {} | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/const-bounds-non-const-trait.rs:6:21 | LL | const fn perform() {} | ^^^^^^^ can't be applied to `NonConst` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `NonConst` as `#[const_trait]` to allow it to have `const` implementations +help: mark `NonConst` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait NonConst {} | ++++++++++++++ -error: `const` can only be applied to `#[const_trait]` traits +error: `const` can only be applied to `const` traits --> $DIR/const-bounds-non-const-trait.rs:10:15 | LL | fn operate() {} | ^^^^^ can't be applied to `NonConst` | -help: mark `NonConst` as `#[const_trait]` to allow it to have `const` implementations +help: mark `NonConst` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait NonConst {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs index 6bea664b65f..176ae091a41 100644 --- a/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs +++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.rs @@ -4,6 +4,6 @@ pub trait A {} impl const A for () {} -//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]` +//~^ ERROR: const `impl` for trait `A` which is not `const` fn main() {} diff --git a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr index c728eda069e..bf73436b78d 100644 --- a/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr +++ b/tests/ui/traits/const-traits/const-impl-requires-const-trait.stderr @@ -1,12 +1,12 @@ -error: const `impl` for trait `A` which is not marked with `#[const_trait]` +error: const `impl` for trait `A` which is not `const` --> $DIR/const-impl-requires-const-trait.rs:6:12 | LL | impl const A for () {} | ^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -help: mark `A` as `#[const_trait]` to allow it to have `const` implementations +help: mark `A` as `const` to allow it to have `const` implementations | LL | #[const_trait] pub trait A {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs index 1d1da9b0e3d..658132441c2 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.rs @@ -1,9 +1,7 @@ #![feature(const_trait_impl)] -// FIXME(const_trait_impl) add effects //@ edition: 2021 -#[const_trait] -trait Trait {} +const trait Trait {} fn main() { let _: &dyn const Trait; //~ ERROR const trait bounds are not allowed in trait object types @@ -14,7 +12,7 @@ fn main() { trait NonConst {} const fn handle(_: &dyn const NonConst) {} //~^ ERROR const trait bounds are not allowed in trait object types -//~| ERROR `const` can only be applied to `#[const_trait]` traits +//~| ERROR `const` can only be applied to `const` traits const fn take(_: &dyn [const] NonConst) {} //~^ ERROR `[const]` is not allowed here -//~| ERROR `[const]` can only be applied to `#[const_trait]` traits +//~| ERROR `[const]` can only be applied to `const` traits diff --git a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr index 06e0493024c..3ba5da39106 100644 --- a/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr +++ b/tests/ui/traits/const-traits/const-trait-bounds-trait-objects.stderr @@ -1,11 +1,11 @@ error: const trait bounds are not allowed in trait object types - --> $DIR/const-trait-bounds-trait-objects.rs:9:17 + --> $DIR/const-trait-bounds-trait-objects.rs:7:17 | LL | let _: &dyn const Trait; | ^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/const-trait-bounds-trait-objects.rs:10:17 + --> $DIR/const-trait-bounds-trait-objects.rs:8:17 | LL | let _: &dyn [const] Trait; | ^^^^^^^ @@ -13,37 +13,37 @@ LL | let _: &dyn [const] Trait; = note: trait objects cannot have `[const]` trait bounds error: const trait bounds are not allowed in trait object types - --> $DIR/const-trait-bounds-trait-objects.rs:15:25 + --> $DIR/const-trait-bounds-trait-objects.rs:13:25 | LL | const fn handle(_: &dyn const NonConst) {} | ^^^^^^^^^^^^^^ error: `[const]` is not allowed here - --> $DIR/const-trait-bounds-trait-objects.rs:18:23 + --> $DIR/const-trait-bounds-trait-objects.rs:16:23 | LL | const fn take(_: &dyn [const] NonConst) {} | ^^^^^^^ | = note: trait objects cannot have `[const]` trait bounds -error: `const` can only be applied to `#[const_trait]` traits - --> $DIR/const-trait-bounds-trait-objects.rs:15:25 +error: `const` can only be applied to `const` traits + --> $DIR/const-trait-bounds-trait-objects.rs:13:25 | LL | const fn handle(_: &dyn const NonConst) {} | ^^^^^ can't be applied to `NonConst` | -help: mark `NonConst` as `#[const_trait]` to allow it to have `const` implementations +help: mark `NonConst` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait NonConst {} | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits - --> $DIR/const-trait-bounds-trait-objects.rs:18:23 +error: `[const]` can only be applied to `const` traits + --> $DIR/const-trait-bounds-trait-objects.rs:16:23 | LL | const fn take(_: &dyn [const] NonConst) {} | ^^^^^^^ can't be applied to `NonConst` | -help: mark `NonConst` as `#[const_trait]` to allow it to have `const` implementations +help: mark `NonConst` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait NonConst {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.rs b/tests/ui/traits/const-traits/const_derives/derive-const-gate.rs index 04fea1189ae..c0796907855 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-gate.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.rs @@ -1,5 +1,5 @@ #[derive_const(Debug)] //~ ERROR use of unstable library feature -//~^ ERROR const `impl` for trait `Debug` which is not marked with `#[const_trait]` +//~^ ERROR const `impl` for trait `Debug` which is not `const` //~| ERROR cannot call non-const method pub struct S; diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr index 5bde358001c..5ed12b37052 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr @@ -7,13 +7,13 @@ LL | #[derive_const(Debug)] = help: add `#![feature(derive_const)]` 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: const `impl` for trait `Debug` which is not marked with `#[const_trait]` +error: const `impl` for trait `Debug` which is not `const` --> $DIR/derive-const-gate.rs:1:16 | LL | #[derive_const(Debug)] | ^^^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error[E0015]: cannot call non-const method `Formatter::<'_>::write_str` in constant functions diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr index c0bd360ebe5..93638801895 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr @@ -1,10 +1,10 @@ -error: const `impl` for trait `Debug` which is not marked with `#[const_trait]` +error: const `impl` for trait `Debug` which is not `const` --> $DIR/derive-const-non-const-type.rs:12:16 | LL | #[derive_const(Debug)] | ^^^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error[E0015]: cannot call non-const method `Formatter::<'_>::debug_tuple_field1_finish` in constant functions diff --git a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs index e53b87274d3..47c85980aca 100644 --- a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs +++ b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.rs @@ -4,7 +4,7 @@ use std::ops::FromResidual; impl const FromResidual for T { - //~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` + //~^ ERROR const `impl` for trait `FromResidual` which is not `const` //~| ERROR type parameter `T` must be used as the type parameter for some local type fn from_residual(t: T) -> _ { //~^ ERROR the placeholder `_` is not allowed diff --git a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr index a165ef12060..5c5fba95f02 100644 --- a/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr +++ b/tests/ui/traits/const-traits/ice-119717-constant-lifetime.stderr @@ -1,10 +1,10 @@ -error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` +error: const `impl` for trait `FromResidual` which is not `const` --> $DIR/ice-119717-constant-lifetime.rs:6:15 | LL | impl const FromResidual for T { | ^^^^^^^^^^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs index 3473be565c1..5e368b9e6a9 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.rs @@ -6,11 +6,11 @@ struct TryMe; struct Error; impl const FromResidual for TryMe {} -//~^ ERROR const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` +//~^ ERROR const `impl` for trait `FromResidual` which is not `const` //~| ERROR not all trait items implemented impl const Try for TryMe { - //~^ ERROR const `impl` for trait `Try` which is not marked with `#[const_trait]` + //~^ ERROR const `impl` for trait `Try` which is not `const` //~| ERROR not all trait items implemented type Output = (); type Residual = Error; diff --git a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr index 41f99c2d375..849d6522cd6 100644 --- a/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr +++ b/tests/ui/traits/const-traits/ice-126148-failed-to-normalize.stderr @@ -1,10 +1,10 @@ -error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` +error: const `impl` for trait `FromResidual` which is not `const` --> $DIR/ice-126148-failed-to-normalize.rs:8:12 | LL | impl const FromResidual for TryMe {} | ^^^^^^^^^^^^^^^^^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error[E0046]: not all trait items implemented, missing: `from_residual` @@ -15,13 +15,13 @@ LL | impl const FromResidual for TryMe {} | = help: implement the missing item: `fn from_residual(_: Error) -> Self { todo!() }` -error: const `impl` for trait `Try` which is not marked with `#[const_trait]` +error: const `impl` for trait `Try` which is not `const` --> $DIR/ice-126148-failed-to-normalize.rs:12:12 | LL | impl const Try for TryMe { | ^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error[E0046]: not all trait items implemented, missing: `from_output`, `branch` diff --git a/tests/ui/traits/const-traits/spec-effectvar-ice.rs b/tests/ui/traits/const-traits/spec-effectvar-ice.rs index c85b1746967..46f71b114a3 100644 --- a/tests/ui/traits/const-traits/spec-effectvar-ice.rs +++ b/tests/ui/traits/const-traits/spec-effectvar-ice.rs @@ -8,11 +8,11 @@ trait Specialize {} trait Foo {} impl const Foo for T {} -//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` +//~^ error: const `impl` for trait `Foo` which is not `const` impl const Foo for T where T: const Specialize {} -//~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` -//~| error: `const` can only be applied to `#[const_trait]` traits +//~^ error: const `impl` for trait `Foo` which is not `const` +//~| error: `const` can only be applied to `const` traits //~| error: specialization impl does not specialize any associated items //~| error: cannot specialize on trait `Specialize` diff --git a/tests/ui/traits/const-traits/spec-effectvar-ice.stderr b/tests/ui/traits/const-traits/spec-effectvar-ice.stderr index 474d96698d5..ef5e58e1c3d 100644 --- a/tests/ui/traits/const-traits/spec-effectvar-ice.stderr +++ b/tests/ui/traits/const-traits/spec-effectvar-ice.stderr @@ -1,36 +1,36 @@ -error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` +error: const `impl` for trait `Foo` which is not `const` --> $DIR/spec-effectvar-ice.rs:10:15 | LL | impl const Foo for T {} | ^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo {} | ++++++++++++++ -error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` +error: const `impl` for trait `Foo` which is not `const` --> $DIR/spec-effectvar-ice.rs:13:15 | LL | impl const Foo for T where T: const Specialize {} | ^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo {} | ++++++++++++++ -error: `const` can only be applied to `#[const_trait]` traits +error: `const` can only be applied to `const` traits --> $DIR/spec-effectvar-ice.rs:13:34 | LL | impl const Foo for T where T: const Specialize {} | ^^^^^ can't be applied to `Specialize` | -help: mark `Specialize` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Specialize` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Specialize {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr index 19f072b289e..0ecbad64bc8 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.nn.stderr @@ -4,43 +4,43 @@ error: `[const]` is not allowed here LL | trait Bar: [const] Foo {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/super-traits-fail-2.rs:11:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr index 4921f78d3ac..0e5b697d1dd 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.ny.stderr @@ -1,58 +1,58 @@ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-2.rs:11:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.rs b/tests/ui/traits/const-traits/super-traits-fail-2.rs index 781dacb81a1..36e7c1c4e4a 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-2.rs @@ -9,11 +9,11 @@ trait Foo { #[cfg_attr(any(yy, ny), const_trait)] trait Bar: [const] Foo {} -//[ny,nn]~^ ERROR: `[const]` can only be applied to `#[const_trait]` -//[ny,nn]~| ERROR: `[const]` can only be applied to `#[const_trait]` -//[ny,nn]~| ERROR: `[const]` can only be applied to `#[const_trait]` -//[ny]~| ERROR: `[const]` can only be applied to `#[const_trait]` -//[ny]~| ERROR: `[const]` can only be applied to `#[const_trait]` +//[ny,nn]~^ ERROR: `[const]` can only be applied to `const` traits +//[ny,nn]~| ERROR: `[const]` can only be applied to `const` traits +//[ny,nn]~| ERROR: `[const]` can only be applied to `const` traits +//[ny]~| ERROR: `[const]` can only be applied to `const` traits +//[ny]~| ERROR: `[const]` can only be applied to `const` traits //[yn,nn]~^^^^^^ ERROR: `[const]` is not allowed here const fn foo(x: &T) { diff --git a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr index a151349822e..657e8ee82e3 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-2.yn.stderr @@ -4,7 +4,7 @@ error: `[const]` is not allowed here LL | trait Bar: [const] Foo {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/super-traits-fail-2.rs:11:1 | LL | trait Bar: [const] Foo {} diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr index 3f48375dd04..a0ae60526ef 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nnn.stderr @@ -4,7 +4,7 @@ error: `[const]` is not allowed here LL | trait Bar: [const] Foo {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/super-traits-fail-3.rs:23:1 | LL | trait Bar: [const] Foo {} @@ -30,60 +30,60 @@ LL | const fn foo(x: &T) { = help: add `#![feature(const_trait_impl)]` 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: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr index 3f48375dd04..a0ae60526ef 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.nny.stderr @@ -4,7 +4,7 @@ error: `[const]` is not allowed here LL | trait Bar: [const] Foo {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/super-traits-fail-3.rs:23:1 | LL | trait Bar: [const] Foo {} @@ -30,60 +30,60 @@ LL | const fn foo(x: &T) { = help: add `#![feature(const_trait_impl)]` 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: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: enable `#![feature(const_trait_impl)]` in your crate and mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.rs b/tests/ui/traits/const-traits/super-traits-fail-3.rs index 5370f607dec..d74bd346784 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.rs +++ b/tests/ui/traits/const-traits/super-traits-fail-3.rs @@ -21,17 +21,17 @@ trait Foo { #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)] //[nyy,nyn]~^ ERROR: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future trait Bar: [const] Foo {} -//[yny,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `#[const_trait]` -//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `#[const_trait]` -//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `#[const_trait]` -//[yny]~^^^^ ERROR: `[const]` can only be applied to `#[const_trait]` -//[yny]~| ERROR: `[const]` can only be applied to `#[const_trait]` +//[yny,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `const` traits +//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits +//[yny,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits +//[yny]~^^^^ ERROR: `[const]` can only be applied to `const` traits +//[yny]~| ERROR: `[const]` can only be applied to `const` traits //[yyn,ynn,nny,nnn]~^^^^^^ ERROR: `[const]` is not allowed here //[nyy,nyn,nny,nnn]~^^^^^^^ ERROR: const trait impls are experimental const fn foo(x: &T) { - //[yyn,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `#[const_trait]` - //[yyn,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `#[const_trait]` + //[yyn,ynn,nny,nnn]~^ ERROR: `[const]` can only be applied to `const` traits + //[yyn,ynn,nny,nnn]~| ERROR: `[const]` can only be applied to `const` traits //[nyy,nyn,nny,nnn]~^^^ ERROR: const trait impls are experimental x.a(); //[yyn]~^ ERROR: the trait bound `T: [const] Foo` is not satisfied diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr index 89e090b7d1c..c8ec77c2f09 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.ynn.stderr @@ -4,66 +4,66 @@ error: `[const]` is not allowed here LL | trait Bar: [const] Foo {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/super-traits-fail-3.rs:23:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | -help: mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr index 683eeb73850..a820239cde0 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yny.stderr @@ -1,58 +1,58 @@ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:23:12 | LL | trait Bar: [const] Foo {} | ^^^^^^^ can't be applied to `Foo` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Foo` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Foo` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Foo { | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr index 39cfdfe2030..de3664dae84 100644 --- a/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr +++ b/tests/ui/traits/const-traits/super-traits-fail-3.yyn.stderr @@ -4,31 +4,31 @@ error: `[const]` is not allowed here LL | trait Bar: [const] Foo {} | ^^^^^^^ | -note: this trait is not a `#[const_trait]`, so it cannot have `[const]` trait bounds +note: this trait is not `const`, so it cannot have `[const]` trait bounds --> $DIR/super-traits-fail-3.rs:23:1 | LL | trait Bar: [const] Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | -help: mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ -error: `[const]` can only be applied to `#[const_trait]` traits +error: `[const]` can only be applied to `const` traits --> $DIR/super-traits-fail-3.rs:32:17 | LL | const fn foo(x: &T) { | ^^^^^^^ can't be applied to `Bar` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: mark `Bar` as `#[const_trait]` to allow it to have `const` implementations +help: mark `Bar` as `const` to allow it to have `const` implementations | LL | #[const_trait] trait Bar: [const] Foo {} | ++++++++++++++ diff --git a/tests/ui/traits/const-traits/trait-default-body-stability.stderr b/tests/ui/traits/const-traits/trait-default-body-stability.stderr index a13d9a1e075..b995d6f4f3d 100644 --- a/tests/ui/traits/const-traits/trait-default-body-stability.stderr +++ b/tests/ui/traits/const-traits/trait-default-body-stability.stderr @@ -1,19 +1,19 @@ -error: const `impl` for trait `Try` which is not marked with `#[const_trait]` +error: const `impl` for trait `Try` which is not `const` --> $DIR/trait-default-body-stability.rs:19:12 | LL | impl const Try for T { | ^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]` +error: const `impl` for trait `FromResidual` which is not `const` --> $DIR/trait-default-body-stability.rs:34:12 | LL | impl const FromResidual for T { | ^^^^^^^^^^^^ this trait is not `const` | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` + = note: marking a trait with `const` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change error[E0015]: `?` is not allowed on `T` in constant functions -- cgit 1.4.1-3-g733a5 From 8a8717e971dbdc6155506a4332e9ce8ef9151caa Mon Sep 17 00:00:00 2001 From: Luigi Sartor Piucco Date: Sun, 20 Apr 2025 18:43:54 -0300 Subject: fix: don't panic on volatile access to null According to https://discourse.llvm.org/t/rfc-volatile-access-to-non-dereferenceable-memory-may-be-well-defined/86303/4, LLVM allows volatile operations on null and handles it correctly. This should be allowed in Rust as well, because I/O memory may be hard-coded to address 0 in some cases, like the AVR chip ATtiny1626. A test case that ensured a failure when passing null to volatile was removed, since it's now valid. Due to the addition of `maybe_is_aligned` to `ub_checks`, `maybe_is_aligned_and_not_null` was refactored to use it. docs: revise restrictions on volatile operations A distinction between usage on Rust memory vs. non-Rust memory was introduced. Documentation was reworded to explain what that means, and make explicit that: - No trapping can occur from volatile operations; - On Rust memory, all safety rules must be respected; - On Rust memory, the primary difference from regular access is that volatile always involves a memory dereference; - On Rust memory, the only data affected by an operation is the one pointed to in the argument(s) of the function; - On Rust memory, provenance follows the same rules as non-volatile access; - On non-Rust memory, any address known to not contain Rust memory is valid (including 0 and usize::MAX); - On non-Rust memory, no Rust memory may be affected (it is implicit that any other non-Rust memory may be affected, though, even if not referenced by the pointer). This should be relevant when, for example, reading register A causes a flag to change in register B, or writing to A causes B to change in some way. Everything affected mustn't be inside an allocation. - On non-Rust memory, provenance is irrelevant and a pointer with none can be used in a valid way. fix: don't lint null as UB for volatile Also remove a now-unneeded `allow` line. fix: additional wording nits --- compiler/rustc_lint/src/ptr_nulls.rs | 4 +- library/core/src/ptr/mod.rs | 168 ++++++++++++++----------- library/core/src/ub_checks.rs | 18 ++- tests/ui/lint/invalid_null_args.rs | 5 +- tests/ui/lint/invalid_null_args.stderr | 58 +++------ tests/ui/precondition-checks/read_volatile.rs | 6 +- tests/ui/precondition-checks/write_volatile.rs | 6 +- 7 files changed, 127 insertions(+), 138 deletions(-) (limited to 'compiler/rustc_lint/src') diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 826bce2c315..b2fa0fba76d 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -160,12 +160,10 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks { let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name { sym::ptr_read | sym::ptr_read_unaligned - | sym::ptr_read_volatile | sym::ptr_replace | sym::ptr_write | sym::ptr_write_bytes - | sym::ptr_write_unaligned - | sym::ptr_write_volatile => (&[0], true), + | sym::ptr_write_unaligned => (&[0], true), sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false), sym::ptr_copy | sym::ptr_copy_nonoverlapping diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index fe8c6f83034..dbe3999b4a4 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -28,7 +28,8 @@ //! undefined behavior to perform two concurrent accesses to the same location from different //! threads unless both accesses only read from memory. Notice that this explicitly //! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot -//! be used for inter-thread synchronization. +//! be used for inter-thread synchronization, regardless of whether they are acting on +//! Rust memory or not. //! * The result of casting a reference to a pointer is valid for as long as the //! underlying allocation is live and no reference (just raw pointers) is used to //! access the same memory. That is, reference and pointer accesses cannot be @@ -114,6 +115,10 @@ //! fully contiguous (i.e., has no "holes"), there is no guarantee that this //! will not change in the future. //! +//! Allocations must behave like "normal" memory: in particular, reads must not have +//! side-effects, and writes must become visible to other threads using the usual synchronization +//! primitives. +//! //! For any allocation with `base` address, `size`, and a set of //! `addresses`, the following are guaranteed: //! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base + @@ -2021,54 +2026,61 @@ pub const unsafe fn write_unaligned(dst: *mut T, src: T) { } } -/// Performs a volatile read of the value from `src` without moving it. This -/// leaves the memory in `src` unchanged. -/// -/// Volatile operations are intended to act on I/O memory, and are guaranteed -/// to not be elided or reordered by the compiler across other volatile -/// operations. -/// -/// # Notes -/// -/// Rust does not currently have a rigorously and formally defined memory model, -/// so the precise semantics of what "volatile" means here is subject to change -/// over time. That being said, the semantics will almost always end up pretty -/// similar to [C11's definition of volatile][c11]. -/// -/// The compiler shouldn't change the relative order or number of volatile -/// memory operations. However, volatile memory operations on zero-sized types -/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops -/// and may be ignored. -/// -/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf +/// Performs a volatile read of the value from `src` without moving it. +/// +/// Volatile operations are intended to act on I/O memory. As such, they are considered externally +/// observable events (just like syscalls, but less opaque), and are guaranteed to not be elided or +/// reordered by the compiler across other externally observable events. With this in mind, there +/// are two cases of usage that need to be distinguished: +/// +/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like +/// [`read`], except for the additional guarantee that it won't be elided or reordered (see +/// above). This implies that the operation will actually access memory and not e.g. be lowered to +/// reusing data from a previous read. Other than that, all the usual rules for memory accesses +/// apply (including provenance). In particular, just like in C, whether an operation is volatile +/// has no bearing whatsoever on questions involving concurrent accesses from multiple threads. +/// Volatile accesses behave exactly like non-atomic accesses in that regard. +/// +/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust +/// allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is +/// typically used for CPU and peripheral registers that must be accessed via an I/O memory +/// mapping, most commonly at fixed addresses reserved by the hardware. These often have special +/// semantics associated to their manipulation, and cannot be used as general purpose memory. +/// Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics +/// of such a read are well-defined by the target hardware. The provenance of the pointer is +/// irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It +/// can cause side-effects, but those must not affect Rust-allocated memory in any way. This +/// access is still not considered [atomic], and as such it cannot be used for inter-thread +/// synchronization. +/// +/// Note that volatile memory operations where T is a zero-sized type are noops and may be ignored. +/// +/// [allocation]: crate::ptr#allocated-object +/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses /// /// # Safety /// +/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of whether `T` is +/// [`Copy`]. If `T` is not [`Copy`], using both the returned value and the value at `*src` can +/// [violate memory safety][read-ownership]. However, storing non-[`Copy`] types in volatile memory +/// is almost certainly incorrect. +/// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `src` must be [valid] for reads. +/// * `src` must be either [valid] for reads, or it must point to memory outside of all Rust +/// allocations and reading from that memory must: +/// - not trap, and +/// - not cause any memory inside a Rust allocation to be modified. /// /// * `src` must be properly aligned. /// -/// * `src` must point to a properly initialized value of type `T`. -/// -/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of -/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned -/// value and the value at `*src` can [violate memory safety][read-ownership]. -/// However, storing non-[`Copy`] types in volatile memory is almost certainly -/// incorrect. +/// * Reading from `src` must produce a properly initialized value of type `T`. /// /// Note that even if `T` has size `0`, the pointer must be properly aligned. /// /// [valid]: self#safety /// [read-ownership]: read#ownership-of-the-returned-value /// -/// Just like in C, whether an operation is volatile has no bearing whatsoever -/// on questions involving concurrent access from multiple threads. Volatile -/// accesses behave exactly like non-atomic accesses in that regard. In particular, -/// a race between a `read_volatile` and any write operation to the same location -/// is undefined behavior. -/// /// # Examples /// /// Basic usage: @@ -2090,50 +2102,63 @@ pub unsafe fn read_volatile(src: *const T) -> T { unsafe { ub_checks::assert_unsafe_precondition!( check_language_ub, - "ptr::read_volatile requires that the pointer argument is aligned and non-null", + "ptr::read_volatile requires that the pointer argument is aligned", ( addr: *const () = src as *const (), align: usize = align_of::(), - is_zst: bool = T::IS_ZST, - ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned(addr, align) ); intrinsics::volatile_load(src) } } -/// Performs a volatile write of a memory location with the given value without -/// reading or dropping the old value. -/// -/// Volatile operations are intended to act on I/O memory, and are guaranteed -/// to not be elided or reordered by the compiler across other volatile -/// operations. -/// -/// `write_volatile` does not drop the contents of `dst`. This is safe, but it -/// could leak allocations or resources, so care should be taken not to overwrite -/// an object that should be dropped. -/// -/// Additionally, it does not drop `src`. Semantically, `src` is moved into the -/// location pointed to by `dst`. -/// -/// # Notes -/// -/// Rust does not currently have a rigorously and formally defined memory model, -/// so the precise semantics of what "volatile" means here is subject to change -/// over time. That being said, the semantics will almost always end up pretty -/// similar to [C11's definition of volatile][c11]. -/// -/// The compiler shouldn't change the relative order or number of volatile -/// memory operations. However, volatile memory operations on zero-sized types -/// (e.g., if a zero-sized type is passed to `write_volatile`) are noops -/// and may be ignored. -/// -/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf +/// Performs a volatile write of a memory location with the given value without reading or dropping +/// the old value. +/// +/// Volatile operations are intended to act on I/O memory. As such, they are considered externally +/// observable events (just like syscalls), and are guaranteed to not be elided or reordered by the +/// compiler across other externally observable events. With this in mind, there are two cases of +/// usage that need to be distinguished: +/// +/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like +/// [`write`][write()], except for the additional guarantee that it won't be elided or reordered +/// (see above). This implies that the operation will actually access memory and not e.g. be +/// lowered to a register access. Other than that, all the usual rules for memory accesses apply +/// (including provenance). In particular, just like in C, whether an operation is volatile has no +/// bearing whatsoever on questions involving concurrent access from multiple threads. Volatile +/// accesses behave exactly like non-atomic accesses in that regard. +/// +/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust +/// allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is +/// typically used for CPU and peripheral registers that must be accessed via an I/O memory +/// mapping, most commonly at fixed addresses reserved by the hardware. These often have special +/// semantics associated to their manipulation, and cannot be used as general purpose memory. +/// Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics +/// of such a write are well-defined by the target hardware. The provenance of the pointer is +/// irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It +/// can cause side-effects, but those must not affect Rust-allocated memory in any way. This +/// access is still not considered [atomic], and as such it cannot be used for inter-thread +/// synchronization. +/// +/// Note that volatile memory operations on zero-sized types (e.g., if a zero-sized type is passed +/// to `write_volatile`) are noops and may be ignored. +/// +/// `write_volatile` does not drop the contents of `dst`. This is safe, but it could leak +/// allocations or resources, so care should be taken not to overwrite an object that should be +/// dropped when operating on Rust memory. Additionally, it does not drop `src`. Semantically, `src` +/// is moved into the location pointed to by `dst`. +/// +/// [allocation]: crate::ptr#allocated-object +/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses /// /// # Safety /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `dst` must be [valid] for writes. +/// * `dst` must be either [valid] for writes, or it must point to memory outside of all Rust +/// allocations and writing to that memory must: +/// - not trap, and +/// - not cause any memory inside a Rust allocation to be modified. /// /// * `dst` must be properly aligned. /// @@ -2141,12 +2166,6 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// /// [valid]: self#safety /// -/// Just like in C, whether an operation is volatile has no bearing whatsoever -/// on questions involving concurrent access from multiple threads. Volatile -/// accesses behave exactly like non-atomic accesses in that regard. In particular, -/// a race between a `write_volatile` and any other operation (reading or writing) -/// on the same location is undefined behavior. -/// /// # Examples /// /// Basic usage: @@ -2170,12 +2189,11 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { unsafe { ub_checks::assert_unsafe_precondition!( check_language_ub, - "ptr::write_volatile requires that the pointer argument is aligned and non-null", + "ptr::write_volatile requires that the pointer argument is aligned", ( addr: *mut () = dst as *mut (), align: usize = align_of::(), - is_zst: bool = T::IS_ZST, - ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned(addr, align) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index a7caaeb95cd..b809294cfce 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -120,13 +120,25 @@ pub(crate) const fn maybe_is_aligned_and_not_null( align: usize, is_zst: bool, ) -> bool { + // This is just for safety checks so we can const_eval_select. + maybe_is_aligned(ptr, align) && (is_zst || !ptr.is_null()) +} + +/// Checks whether `ptr` is properly aligned with respect to the given alignment. +/// +/// In `const` this is approximate and can fail spuriously. It is primarily intended +/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the +/// check is anyway not executed in `const`. +#[inline] +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn maybe_is_aligned(ptr: *const (), align: usize) -> bool { // This is just for safety checks so we can const_eval_select. const_eval_select!( - @capture { ptr: *const (), align: usize, is_zst: bool } -> bool: + @capture { ptr: *const (), align: usize } -> bool: if const { - is_zst || !ptr.is_null() + true } else { - ptr.is_aligned_to(align) && (is_zst || !ptr.is_null()) + ptr.is_aligned_to(align) } ) } diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs index f40f06a0d36..ee29d622ad7 100644 --- a/tests/ui/lint/invalid_null_args.rs +++ b/tests/ui/lint/invalid_null_args.rs @@ -58,10 +58,9 @@ unsafe fn null_ptr() { let _a: A = ptr::read_unaligned(ptr::null_mut()); //~^ ERROR calling this function with a null pointer is undefined behavior + // These two should *not* fire the lint. let _a: A = ptr::read_volatile(ptr::null()); - //~^ ERROR calling this function with a null pointer is undefined behavior let _a: A = ptr::read_volatile(ptr::null_mut()); - //~^ ERROR calling this function with a null pointer is undefined behavior let _a: A = ptr::replace(ptr::null_mut(), v); //~^ ERROR calling this function with a null pointer is undefined behavior @@ -82,8 +81,8 @@ unsafe fn null_ptr() { ptr::write_unaligned(ptr::null_mut(), v); //~^ ERROR calling this function with a null pointer is undefined behavior + // This one should *not* fire the lint. ptr::write_volatile(ptr::null_mut(), v); - //~^ ERROR calling this function with a null pointer is undefined behavior ptr::write_bytes::(ptr::null_mut(), 42, 0); //~^ ERROR calling this function with a null pointer is undefined behavior diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr index 11c6270cfb7..028bd7051dc 100644 --- a/tests/ui/lint/invalid_null_args.stderr +++ b/tests/ui/lint/invalid_null_args.stderr @@ -164,27 +164,7 @@ LL | let _a: A = ptr::read_unaligned(ptr::null_mut()); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:61:17 - | -LL | let _a: A = ptr::read_volatile(ptr::null()); - | ^^^^^^^^^^^^^^^^^^^-----------^ - | | - | null pointer originates from here - | - = help: for more information, visit and - -error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:63:17 - | -LL | let _a: A = ptr::read_volatile(ptr::null_mut()); - | ^^^^^^^^^^^^^^^^^^^---------------^ - | | - | null pointer originates from here - | - = help: for more information, visit and - -error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:66:17 + --> $DIR/invalid_null_args.rs:65:17 | LL | let _a: A = ptr::replace(ptr::null_mut(), v); | ^^^^^^^^^^^^^---------------^^^^ @@ -194,7 +174,7 @@ LL | let _a: A = ptr::replace(ptr::null_mut(), v); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:69:5 + --> $DIR/invalid_null_args.rs:68:5 | LL | ptr::swap::(ptr::null_mut(), &mut v); | ^^^^^^^^^^^^^^^---------------^^^^^^^^^ @@ -204,7 +184,7 @@ LL | ptr::swap::(ptr::null_mut(), &mut v); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:71:5 + --> $DIR/invalid_null_args.rs:70:5 | LL | ptr::swap::(&mut v, ptr::null_mut()); | ^^^^^^^^^^^^^^^^^^^^^^^---------------^ @@ -214,7 +194,7 @@ LL | ptr::swap::(&mut v, ptr::null_mut()); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:74:5 + --> $DIR/invalid_null_args.rs:73:5 | LL | ptr::swap_nonoverlapping::(ptr::null_mut(), &mut v, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^ @@ -224,7 +204,7 @@ LL | ptr::swap_nonoverlapping::(ptr::null_mut(), &mut v, 0); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:76:5 + --> $DIR/invalid_null_args.rs:75:5 | LL | ptr::swap_nonoverlapping::(&mut v, ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ @@ -234,7 +214,7 @@ LL | ptr::swap_nonoverlapping::(&mut v, ptr::null_mut(), 0); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:79:5 + --> $DIR/invalid_null_args.rs:78:5 | LL | ptr::write(ptr::null_mut(), v); | ^^^^^^^^^^^---------------^^^^ @@ -244,7 +224,7 @@ LL | ptr::write(ptr::null_mut(), v); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:82:5 + --> $DIR/invalid_null_args.rs:81:5 | LL | ptr::write_unaligned(ptr::null_mut(), v); | ^^^^^^^^^^^^^^^^^^^^^---------------^^^^ @@ -254,17 +234,7 @@ LL | ptr::write_unaligned(ptr::null_mut(), v); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:85:5 - | -LL | ptr::write_volatile(ptr::null_mut(), v); - | ^^^^^^^^^^^^^^^^^^^^---------------^^^^ - | | - | null pointer originates from here - | - = help: for more information, visit and - -error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:88:5 + --> $DIR/invalid_null_args.rs:87:5 | LL | ptr::write_bytes::(ptr::null_mut(), 42, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^ @@ -274,7 +244,7 @@ LL | ptr::write_bytes::(ptr::null_mut(), 42, 0); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:93:18 + --> $DIR/invalid_null_args.rs:92:18 | LL | let _a: u8 = ptr::read(const_ptr); | ^^^^^^^^^^^^^^^^^^^^ @@ -287,7 +257,7 @@ LL | let null_ptr = ptr::null_mut(); | ^^^^^^^^^^^^^^^ error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:100:5 + --> $DIR/invalid_null_args.rs:99:5 | LL | std::slice::from_raw_parts::<()>(ptr::null(), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ @@ -297,7 +267,7 @@ LL | std::slice::from_raw_parts::<()>(ptr::null(), 0); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:102:5 + --> $DIR/invalid_null_args.rs:101:5 | LL | std::slice::from_raw_parts::(ptr::null(), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^ @@ -307,7 +277,7 @@ LL | std::slice::from_raw_parts::(ptr::null(), 0); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:104:5 + --> $DIR/invalid_null_args.rs:103:5 | LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ @@ -317,7 +287,7 @@ LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0); = help: for more information, visit and error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused - --> $DIR/invalid_null_args.rs:106:5 + --> $DIR/invalid_null_args.rs:105:5 | LL | std::slice::from_raw_parts_mut::(ptr::null_mut(), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^ @@ -326,5 +296,5 @@ LL | std::slice::from_raw_parts_mut::(ptr::null_mut(), 0); | = help: for more information, visit and -error: aborting due to 31 previous errors +error: aborting due to 28 previous errors diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs index ada8932c398..d858e6b939a 100644 --- a/tests/ui/precondition-checks/read_volatile.rs +++ b/tests/ui/precondition-checks/read_volatile.rs @@ -1,9 +1,7 @@ //@ run-fail //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes //@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires -//@ revisions: null misaligned - -#![allow(invalid_null_arguments)] +//@ revisions: misaligned use std::ptr; @@ -11,8 +9,6 @@ fn main() { let src = [0u16; 2]; let src = src.as_ptr(); unsafe { - #[cfg(null)] - ptr::read_volatile(ptr::null::()); #[cfg(misaligned)] ptr::read_volatile(src.byte_add(1)); } diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs index 0d5ecb014b3..ddc882be432 100644 --- a/tests/ui/precondition-checks/write_volatile.rs +++ b/tests/ui/precondition-checks/write_volatile.rs @@ -1,9 +1,7 @@ //@ run-fail //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes //@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires -//@ revisions: null misaligned - -#![allow(invalid_null_arguments)] +//@ revisions: misaligned use std::ptr; @@ -11,8 +9,6 @@ fn main() { let mut dst = [0u16; 2]; let mut dst = dst.as_mut_ptr(); unsafe { - #[cfg(null)] - ptr::write_volatile(ptr::null_mut::(), 1u8); #[cfg(misaligned)] ptr::write_volatile(dst.byte_add(1), 1u16); } -- cgit 1.4.1-3-g733a5