Auto merge of #118881 - matthiaskrgr:rollup-0rl3tir, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #116740 (dont ICE when ConstKind::Expr for is_const_evaluatable)
 - #117914 (On borrow return type, suggest borrowing from arg or owned return type)
 - #117927 (Clarify how to choose a FutureIncompatibilityReason variant.)
 - #118855 (Improve an error involving attribute values.)
 - #118856 (rustdoc-search: clean up parser)
 - #118865 (rustc_codegen_llvm: Enforce `rustc::potential_query_instability` lint)
 - #118866 (llvm-wrapper: adapt for LLVM API change)
 - #118868 (Correctly gate the parsing of match arms without body)
 - #118877 (tests: CGU tests require build-pass, not check-pass (remove FIXME))

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-12-12 18:20:37 +00:00
commit 028b6d152e
58 changed files with 939 additions and 168 deletions

View file

@ -676,6 +676,19 @@ impl Pat {
});
could_be_never_pattern
}
/// Whether this contains a `!` pattern. This in particular means that a feature gate error will
/// be raised if the feature is off. Used to avoid gating the feature twice.
pub fn contains_never_pattern(&self) -> bool {
let mut contains_never_pattern = false;
self.walk(&mut |pat| {
if matches!(pat.kind, PatKind::Never) {
contains_never_pattern = true;
}
true
});
contains_never_pattern
}
}
/// A single field in a struct pattern.

View file

@ -581,8 +581,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
} else {
// Either `body.is_none()` or `is_never_pattern` here.
if !is_never_pattern {
let suggestion = span.shrink_to_hi();
self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
if self.tcx.features().never_patterns {
// If the feature is off we already emitted the error after parsing.
let suggestion = span.shrink_to_hi();
self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
}
} else if let Some(body) = &arm.body {
self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span });
guard = None;

View file

@ -174,6 +174,10 @@ ast_passes_item_underscore = `{$kind}` items in this context need a name
ast_passes_keyword_lifetime =
lifetimes cannot use keyword names
ast_passes_match_arm_with_no_body =
`match` arm with no body
.suggestion = add a body after the pattern
ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
.help = consider using the `#[path]` attribute to specify filesystem path

View file

@ -758,3 +758,12 @@ pub struct AnonStructOrUnionNotAllowed {
pub span: Span,
pub struct_or_union: &'static str,
}
#[derive(Diagnostic)]
#[diag(ast_passes_match_arm_with_no_body)]
pub struct MatchArmWithNoBody {
#[primary_span]
pub span: Span,
#[suggestion(code = " => todo!(),", applicability = "has-placeholders")]
pub suggestion: Span,
}

View file

@ -554,7 +554,34 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(explicit_tail_calls, "`become` expression is experimental");
gate_all!(generic_const_items, "generic const items are experimental");
gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
gate_all!(never_patterns, "`!` patterns are experimental");
if !visitor.features.never_patterns {
if let Some(spans) = spans.get(&sym::never_patterns) {
for &span in spans {
if span.allows_unstable(sym::never_patterns) {
continue;
}
let sm = sess.source_map();
// We gate two types of spans: the span of a `!` pattern, and the span of a
// match arm without a body. For the latter we want to give the user a normal
// error.
if let Ok(snippet) = sm.span_to_snippet(span)
&& snippet == "!"
{
feature_err(
&sess.parse_sess,
sym::never_patterns,
span,
"`!` patterns are experimental",
)
.emit();
} else {
let suggestion = span.shrink_to_hi();
sess.emit_err(errors::MatchArmWithNoBody { span, suggestion });
}
}
}
}
if !visitor.features.negative_bounds {
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {

View file

@ -816,6 +816,9 @@ impl ThinLTOKeysMap {
use std::io::Write;
let file = File::create(path)?;
let mut writer = io::BufWriter::new(file);
// The entries are loaded back into a hash map in `load_from_file()`, so
// the order in which we write them to file here does not matter.
#[allow(rustc::potential_query_instability)]
for (module, key) in &self.keys {
writeln!(writer, "{module} {key}")?;
}

View file

@ -58,6 +58,11 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
return;
}
// The entries of the map are only used to get a list of all files with
// coverage info. In the end the list of files is passed into
// `GlobalFileTable::new()` which internally do `.sort_unstable_by()`, so
// the iteration order here does not matter.
#[allow(rustc::potential_query_instability)]
let function_coverage_entries = function_coverage_map
.into_iter()
.map(|(instance, function_coverage)| (instance, function_coverage.into_finished()))

View file

@ -17,7 +17,6 @@
#![feature(never_type)]
#![feature(impl_trait_in_assoc_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]

View file

@ -345,12 +345,34 @@ pub struct FutureIncompatibleInfo {
}
/// The reason for future incompatibility
///
/// Future-incompatible lints come in roughly two categories:
///
/// 1. There was a mistake in the compiler (such as a soundness issue), and
/// we're trying to fix it, but it may be a breaking change.
/// 2. A change across an Edition boundary, typically used for the
/// introduction of new language features that can't otherwise be
/// introduced in a backwards-compatible way.
///
/// See <https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html> and
/// <https://rustc-dev-guide.rust-lang.org/diagnostics.html#future-incompatible-lints>
/// for more information.
#[derive(Copy, Clone, Debug)]
pub enum FutureIncompatibilityReason {
/// This will be an error in a future release for all editions
///
/// This will *not* show up in cargo's future breakage report.
/// The warning will hence only be seen in local crates, not in dependencies.
///
/// Choose this variant when you are first introducing a "future
/// incompatible" warning that is intended to eventually be fixed in the
/// future. This allows crate developers an opportunity to fix the warning
/// before blasting all dependents with a warning they can't fix
/// (dependents have to wait for a new release of the affected crate to be
/// published).
///
/// After a lint has been in this state for a while, consider graduating
/// it to [`FutureIncompatibilityReason::FutureReleaseErrorReportInDeps`].
FutureReleaseErrorDontReportInDeps,
/// This will be an error in a future release, and
/// Cargo should create a report even for dependencies
@ -358,17 +380,62 @@ pub enum FutureIncompatibilityReason {
/// This is the *only* reason that will make future incompatibility warnings show up in cargo's
/// reports. All other future incompatibility warnings are not visible when they occur in a
/// dependency.
///
/// Choose this variant after the lint has been sitting in the
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`]
/// state for a while, and you feel like it is ready to graduate to
/// warning everyone. It is a good signal that it is ready if you can
/// determine that all or most affected crates on crates.io have been
/// updated.
///
/// After some period of time, lints with this variant can be turned into
/// hard errors (and the lint removed). Preferably when there is some
/// confidence that the number of impacted projects is very small (few
/// should have a broken dependency in their dependency tree).
FutureReleaseErrorReportInDeps,
/// Code that changes meaning in some way in a
/// future release.
///
/// Choose this variant when the semantics of existing code is changing,
/// (as opposed to
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`],
/// which is for when code is going to be rejected in the future).
FutureReleaseSemanticsChange,
/// Previously accepted code that will become an
/// error in the provided edition
///
/// Choose this variant for code that you want to start rejecting across
/// an edition boundary. This will automatically include the lint in the
/// `rust-20xx-compatibility` lint group, which is used by `cargo fix
/// --edition` to do migrations. The lint *should* be auto-fixable with
/// [`Applicability::MachineApplicable`].
///
/// The lint can either be `Allow` or `Warn` by default. If it is `Allow`,
/// users usually won't see this warning unless they are doing an edition
/// migration manually or there is a problem during the migration (cargo's
/// automatic migrations will force the level to `Warn`). If it is `Warn`
/// by default, users on all editions will see this warning (only do this
/// if you think it is important for everyone to be aware of the change,
/// and to encourage people to update their code on all editions).
///
/// See also [`FutureIncompatibilityReason::EditionSemanticsChange`] if
/// you have code that is changing semantics across the edition (as
/// opposed to being rejected).
EditionError(Edition),
/// Code that changes meaning in some way in
/// the provided edition
///
/// This is the same as [`FutureIncompatibilityReason::EditionError`],
/// except for situations where the semantics change across an edition. It
/// slightly changes the text of the diagnostic, but is otherwise the
/// same.
EditionSemanticsChange(Edition),
/// A custom reason.
///
/// Choose this variant if the built-in text of the diagnostic of the
/// other variants doesn't match your situation. This is behaviorally
/// equivalent to
/// [`FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps`].
Custom(&'static str),
}

View file

@ -37,7 +37,9 @@
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#if LLVM_VERSION_GE(18, 0)
#include "llvm/TargetParser/Host.h"
#endif
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
#include "llvm/Support/TimeProfiler.h"

View file

@ -2918,7 +2918,15 @@ impl<'a> Parser<'a> {
let mut result = if !is_fat_arrow && !is_almost_fat_arrow {
// A pattern without a body, allowed for never patterns.
arm_body = None;
this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)])
this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]).map(
|x| {
// Don't gate twice
if !pat.contains_never_pattern() {
this.sess.gated_spans.gate(sym::never_patterns, pat.span);
}
x
},
)
} else {
if let Err(mut err) = this.expect(&token::FatArrow) {
// We might have a `=>` -> `=` or `->` typo (issue #89396).

View file

@ -6,9 +6,9 @@ use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::MetaItemKind;
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem};
use rustc_ast_pretty::pprust;
use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::errors::report_lit_error;
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
use rustc_session::parse::ParseSess;
use rustc_span::{sym, Span, Symbol};
@ -51,28 +51,44 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
MetaItemKind::List(nmis)
}
AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
if let ast::ExprKind::Lit(token_lit) = expr.kind
&& let Ok(lit) = ast::MetaItemLit::from_token_lit(token_lit, expr.span)
{
if token_lit.suffix.is_some() {
let mut err = sess.span_diagnostic.struct_span_err(
expr.span,
"suffixed literals are not allowed in attributes",
);
err.help(
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
use an unsuffixed version (`1`, `1.0`, etc.)",
);
return Err(err);
} else {
MetaItemKind::NameValue(lit)
}
if let ast::ExprKind::Lit(token_lit) = expr.kind {
let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
let res = match res {
Ok(lit) => {
if token_lit.suffix.is_some() {
let mut err = sess.span_diagnostic.struct_span_err(
expr.span,
"suffixed literals are not allowed in attributes",
);
err.help(
"instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
use an unsuffixed version (`1`, `1.0`, etc.)",
);
return Err(err);
} else {
MetaItemKind::NameValue(lit)
}
}
Err(err) => {
report_lit_error(sess, err, token_lit, expr.span);
let lit = ast::MetaItemLit {
symbol: token_lit.symbol,
suffix: token_lit.suffix,
kind: ast::LitKind::Err,
span: expr.span,
};
MetaItemKind::NameValue(lit)
}
};
res
} else {
// The non-error case can happen with e.g. `#[foo = 1+1]`. The error case can
// happen with e.g. `#[foo = include_str!("nonexistent-file.rs")]`; in that
// case we delay the error because an earlier error will have already been
// reported.
let msg = format!("unexpected expression: `{}`", pprust::expr_to_string(expr));
// Example cases:
// - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
// - `#[foo = include_str!("nonexistent-file.rs")]`:
// results in `ast::ExprKind::Err`. In that case we delay
// the error because an earlier error will have already
// been reported.
let msg = format!("attribute value must be a literal");
let mut err = sess.span_diagnostic.struct_span_err(expr.span, msg);
if let ast::ExprKind::Err = expr.kind {
err.downgrade_to_delayed_bug();

View file

@ -8,7 +8,7 @@ use crate::{PathResult, PathSource, Segment};
use rustc_hir::def::Namespace::{self, *};
use rustc_ast::ptr::P;
use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt};
use rustc_ast::visit::{walk_ty, FnCtxt, FnKind, LifetimeCtxt, Visitor};
use rustc_ast::{
self as ast, AssocItemKind, Expr, ExprKind, GenericParam, GenericParamKind, Item, ItemKind,
MethodCall, NodeId, Path, Ty, TyKind, DUMMY_NODE_ID,
@ -2830,6 +2830,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
.collect();
debug!(?in_scope_lifetimes);
let mut maybe_static = false;
debug!(?function_param_lifetimes);
if let Some((param_lifetimes, params)) = &function_param_lifetimes {
let elided_len = param_lifetimes.len();
@ -2868,10 +2869,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
if num_params == 0 {
err.help(
"this function's return type contains a borrowed value, \
but there is no value for it to be borrowed from",
"this function's return type contains a borrowed value, but there is no value \
for it to be borrowed from",
);
if in_scope_lifetimes.is_empty() {
maybe_static = true;
in_scope_lifetimes = vec![(
Ident::with_dummy_span(kw::StaticLifetime),
(DUMMY_NODE_ID, LifetimeRes::Static),
@ -2879,11 +2881,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
} else if elided_len == 0 {
err.help(
"this function's return type contains a borrowed value with \
an elided lifetime, but the lifetime cannot be derived from \
the arguments",
"this function's return type contains a borrowed value with an elided \
lifetime, but the lifetime cannot be derived from the arguments",
);
if in_scope_lifetimes.is_empty() {
maybe_static = true;
in_scope_lifetimes = vec![(
Ident::with_dummy_span(kw::StaticLifetime),
(DUMMY_NODE_ID, LifetimeRes::Static),
@ -2891,13 +2893,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
} else if num_params == 1 {
err.help(format!(
"this function's return type contains a borrowed value, \
but the signature does not say which {m} it is borrowed from"
"this function's return type contains a borrowed value, but the signature does \
not say which {m} it is borrowed from",
));
} else {
err.help(format!(
"this function's return type contains a borrowed value, \
but the signature does not say whether it is borrowed from {m}"
"this function's return type contains a borrowed value, but the signature does \
not say whether it is borrowed from {m}",
));
}
}
@ -2962,11 +2964,238 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
);
}
1 => {
let post = if maybe_static {
let owned = if let [lt] = &lifetime_refs[..]
&& lt.kind != MissingLifetimeKind::Ampersand
{
", or if you will only have owned values"
} else {
""
};
format!(
", but this is uncommon unless you're returning a borrowed value from a \
`const` or a `static`{owned}",
)
} else {
String::new()
};
err.multipart_suggestion_verbose(
format!("consider using the `{existing_name}` lifetime"),
format!("consider using the `{existing_name}` lifetime{post}"),
spans_suggs,
Applicability::MaybeIncorrect,
);
if maybe_static {
// FIXME: what follows are general suggestions, but we'd want to perform some
// minimal flow analysis to provide more accurate suggestions. For example, if
// we identified that the return expression references only one argument, we
// would suggest borrowing only that argument, and we'd skip the prior
// "use `'static`" suggestion entirely.
if let [lt] = &lifetime_refs[..]
&& (lt.kind == MissingLifetimeKind::Ampersand
|| lt.kind == MissingLifetimeKind::Underscore)
{
let pre = if lt.kind == MissingLifetimeKind::Ampersand
&& let Some((kind, _span)) = self.diagnostic_metadata.current_function
&& let FnKind::Fn(_, _, sig, _, _, _) = kind
&& !sig.decl.inputs.is_empty()
&& let sugg = sig
.decl
.inputs
.iter()
.filter_map(|param| {
if param.ty.span.contains(lt.span) {
// We don't want to suggest `fn elision(_: &fn() -> &i32)`
// when we have `fn elision(_: fn() -> &i32)`
None
} else if let TyKind::CVarArgs = param.ty.kind {
// Don't suggest `&...` for ffi fn with varargs
None
} else if let TyKind::ImplTrait(..) = &param.ty.kind {
// We handle these in the next `else if` branch.
None
} else {
Some((param.ty.span.shrink_to_lo(), "&".to_string()))
}
})
.collect::<Vec<_>>()
&& !sugg.is_empty()
{
let (the, s) = if sig.decl.inputs.len() == 1 {
("the", "")
} else {
("one of the", "s")
};
err.multipart_suggestion_verbose(
format!(
"instead, you are more likely to want to change {the} \
argument{s} to be borrowed...",
),
sugg,
Applicability::MaybeIncorrect,
);
"...or alternatively, you might want"
} else if (lt.kind == MissingLifetimeKind::Ampersand
|| lt.kind == MissingLifetimeKind::Underscore)
&& let Some((kind, _span)) = self.diagnostic_metadata.current_function
&& let FnKind::Fn(_, _, sig, _, _, _) = kind
&& let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output
&& !sig.decl.inputs.is_empty()
&& let arg_refs = sig
.decl
.inputs
.iter()
.filter_map(|param| match &param.ty.kind {
TyKind::ImplTrait(_, bounds) => Some(bounds),
_ => None,
})
.flat_map(|bounds| bounds.into_iter())
.collect::<Vec<_>>()
&& !arg_refs.is_empty()
{
// We have a situation like
// fn g(mut x: impl Iterator<Item = &()>) -> Option<&()>
// So we look at every ref in the trait bound. If there's any, we
// suggest
// fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()>
let mut lt_finder =
LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] };
for bound in arg_refs {
if let ast::GenericBound::Trait(trait_ref, _) = bound {
lt_finder.visit_trait_ref(&trait_ref.trait_ref);
}
}
lt_finder.visit_ty(ret_ty);
let spans_suggs: Vec<_> = lt_finder
.seen
.iter()
.filter_map(|ty| match &ty.kind {
TyKind::Ref(_, mut_ty) => {
let span = ty.span.with_hi(mut_ty.ty.span.lo());
Some((span, "&'a ".to_string()))
}
_ => None,
})
.collect();
self.suggest_introducing_lifetime(
err,
None,
|err, higher_ranked, span, message, intro_sugg| {
err.multipart_suggestion_verbose(
message,
std::iter::once((span, intro_sugg))
.chain(spans_suggs.iter().cloned())
.collect(),
Applicability::MaybeIncorrect,
);
higher_ranked
},
);
"alternatively, you might want"
} else {
"instead, you are more likely to want"
};
let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
let mut sugg = vec![(lt.span, String::new())];
if let Some((kind, _span)) = self.diagnostic_metadata.current_function
&& let FnKind::Fn(_, _, sig, _, _, _) = kind
&& let ast::FnRetTy::Ty(ty) = &sig.decl.output
{
let mut lt_finder =
LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] };
lt_finder.visit_ty(&ty);
if let [Ty { span, kind: TyKind::Ref(_, mut_ty), .. }] =
&lt_finder.seen[..]
{
// We might have a situation like
// fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()>
// but `lt.span` only points at `'_`, so to suggest `-> Option<()>`
// we need to find a more accurate span to end up with
// fn g<'a>(mut x: impl Iterator<Item = &'_ ()>) -> Option<()>
sugg = vec![(span.with_hi(mut_ty.ty.span.lo()), String::new())];
owned_sugg = true;
}
if let Some(ty) = lt_finder.found {
if let TyKind::Path(None, path) = &ty.kind {
// Check if the path being borrowed is likely to be owned.
let path: Vec<_> = Segment::from_path(path);
match self.resolve_path(&path, Some(TypeNS), None) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
match module.res() {
Some(Res::PrimTy(PrimTy::Str)) => {
// Don't suggest `-> str`, suggest `-> String`.
sugg = vec![(
lt.span.with_hi(ty.span.hi()),
"String".to_string(),
)];
}
Some(Res::PrimTy(..)) => {}
Some(Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::ForeignTy
| DefKind::AssocTy
| DefKind::OpaqueTy
| DefKind::TyParam,
_,
)) => {}
_ => {
// Do not suggest in all other cases.
owned_sugg = false;
}
}
}
PathResult::NonModule(res) => {
match res.base_res() {
Res::PrimTy(PrimTy::Str) => {
// Don't suggest `-> str`, suggest `-> String`.
sugg = vec![(
lt.span.with_hi(ty.span.hi()),
"String".to_string(),
)];
}
Res::PrimTy(..) => {}
Res::Def(
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::ForeignTy
| DefKind::AssocTy
| DefKind::OpaqueTy
| DefKind::TyParam,
_,
) => {}
_ => {
// Do not suggest in all other cases.
owned_sugg = false;
}
}
}
_ => {
// Do not suggest in all other cases.
owned_sugg = false;
}
}
}
if let TyKind::Slice(inner_ty) = &ty.kind {
// Don't suggest `-> [T]`, suggest `-> Vec<T>`.
sugg = vec![
(lt.span.with_hi(inner_ty.span.lo()), "Vec<".to_string()),
(ty.span.with_lo(inner_ty.span.hi()), ">".to_string()),
];
}
}
}
if owned_sugg {
err.multipart_suggestion_verbose(
format!("{pre} to return an owned value"),
sugg,
Applicability::MaybeIncorrect,
);
}
}
}
// Record as using the suggested resolution.
let (_, (_, res)) = in_scope_lifetimes[0];
@ -2996,7 +3225,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
fn mk_where_bound_predicate(
path: &Path,
poly_trait_ref: &ast::PolyTraitRef,
ty: &ast::Ty,
ty: &Ty,
) -> Option<ast::WhereBoundPredicate> {
use rustc_span::DUMMY_SP;
let modified_segments = {
@ -3073,6 +3302,24 @@ pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: I
err.emit();
}
struct LifetimeFinder<'ast> {
lifetime: Span,
found: Option<&'ast Ty>,
seen: Vec<&'ast Ty>,
}
impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> {
fn visit_ty(&mut self, t: &'ast Ty) {
if let TyKind::Ref(_, mut_ty) = &t.kind {
self.seen.push(t);
if t.span.lo() == self.lifetime.lo() {
self.found = Some(&mut_ty.ty);
}
}
walk_ty(self, t)
}
}
/// Shadowing involving a label is only a warning for historical reasons.
//FIXME: make this a proper lint.
pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {

View file

@ -3525,20 +3525,30 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => match ct.kind() {
ty::ConstKind::Unevaluated(uv) => {
let mut err =
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
let const_span = self.tcx.def_span(uv.def);
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => err.help(format!(
"try adding a `where` bound using this expression: `where [(); {snippet}]:`"
)),
_ => err.help("consider adding a `where` bound using this expression"),
};
Some(err)
}
ty::ConstKind::Expr(_) => {
let err = self
.tcx
.sess
.struct_span_err(span, format!("unconstrained generic constant `{ct}`"));
Some(err)
}
_ => {
bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
};
let mut err = self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
let const_span = self.tcx.def_span(uv.def);
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => err.help(format!(
"try adding a `where` bound using this expression: `where [(); {snippet}]:`"
)),
_ => err.help("consider adding a `where` bound using this expression"),
};
Some(err)
}
}
},
_ => {
span_bug!(
span,

View file

@ -298,10 +298,6 @@ function initSearch(rawSearchIndex) {
return "=,>-]".indexOf(c) !== -1;
}
function isStopCharacter(c) {
return isEndCharacter(c);
}
function isErrorCharacter(c) {
return "()".indexOf(c) !== -1;
}
@ -617,8 +613,7 @@ function initSearch(rawSearchIndex) {
}
} else if (
c === "[" ||
c === "=" ||
isStopCharacter(c) ||
isEndCharacter(c) ||
isSpecialStartCharacter(c) ||
isSeparatorCharacter(c)
) {
@ -917,7 +912,7 @@ function initSearch(rawSearchIndex) {
while (parserState.pos < parserState.length) {
const c = parserState.userQuery[parserState.pos];
if (isStopCharacter(c)) {
if (isEndCharacter(c)) {
foundStopChar = true;
if (isSeparatorCharacter(c)) {
parserState.pos += 1;

View file

@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
const ENTRY_LIMIT: usize = 900;
// FIXME: The following limits should be reduced eventually.
const ISSUES_ENTRY_LIMIT: usize = 1852;
const ROOT_ENTRY_LIMIT: usize = 867;
const ROOT_ENTRY_LIMIT: usize = 866;
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
"rs", // test source files

View file

@ -4,7 +4,7 @@
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -O
// build-pass (FIXME(62277): could be check-pass?)
// build-pass
#![feature(rustc_attrs)]
#![crate_type="rlib"]

View file

@ -5,7 +5,7 @@
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -O
// build-pass (FIXME(62277): could be check-pass?)
// build-pass
#![feature(rustc_attrs)]
#![crate_type = "rlib"]

View file

@ -3,7 +3,7 @@
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph -O
// build-pass (FIXME(62277): could be check-pass?)
// build-pass
#![feature(rustc_attrs)]
#![crate_type="rlib"]

View file

@ -5,10 +5,15 @@ LL | fn elision<T: Fn() -> &i32>() {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn elision<T: Fn() -> &'static i32>() {
| +++++++
help: instead, you are more likely to want to return an owned value
|
LL - fn elision<T: Fn() -> &i32>() {
LL + fn elision<T: Fn() -> i32>() {
|
error: aborting due to 1 previous error

View file

@ -5,10 +5,15 @@ LL | fn elision(_: fn() -> &i32) {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn elision(_: fn() -> &'static i32) {
| +++++++
help: instead, you are more likely to want to return an owned value
|
LL - fn elision(_: fn() -> &i32) {
LL + fn elision(_: fn() -> i32) {
|
error: aborting due to 1 previous error

View file

@ -1,9 +1,9 @@
#![u=||{static d=||1;}]
//~^ unexpected expression
//~^ attribute value must be a literal
//~| cannot find attribute `u` in this scope
//~| missing type for `static` item
#![a={impl std::ops::Neg for i8 {}}]
//~^ ERROR unexpected expression
//~^ ERROR attribute value must be a literal
//~| ERROR cannot find attribute `a` in this scope
//~| ERROR `main` function not found in crate `issue_90873`

View file

@ -1,15 +1,10 @@
error: unexpected expression: `||
{
static d: _ = || 1;
}`
error: attribute value must be a literal
--> $DIR/issue-90873.rs:1:6
|
LL | #![u=||{static d=||1;}]
| ^^^^^^^^^^^^^^^^^
error: unexpected expression: `{
impl std::ops::Neg for i8 {}
}`
error: attribute value must be a literal
--> $DIR/issue-90873.rs:6:6
|
LL | #![a={impl std::ops::Neg for i8 {}}]

View file

@ -7,8 +7,8 @@ macro_rules! bar {
// FIXME?: `bar` here expands before `stringify` has a chance to expand.
// `#[rustc_dummy = ...]` is validated and dropped during expansion of `bar`,
// the "unexpected expression" errors comes from the validation.
#[rustc_dummy = stringify!(b)] //~ ERROR unexpected expression: `stringify!(b)`
// the "attribute value must be a literal" error comes from the validation.
#[rustc_dummy = stringify!(b)] //~ ERROR attribute value must be a literal
bar!();
fn main() {}

View file

@ -1,4 +1,4 @@
error: unexpected expression: `stringify!(b)`
error: attribute value must be a literal
--> $DIR/key-value-expansion-on-mac.rs:11:17
|
LL | #[rustc_dummy = stringify!(b)]

View file

@ -18,13 +18,13 @@ macro_rules! bug {
// Any expressions containing macro call `X` that's more complex than `X` itself.
// Parentheses will work.
bug!((column!())); //~ ERROR unexpected expression: `(7u32)`
bug!((column!())); //~ ERROR attribute value must be a literal
// Original test case.
macro_rules! bug {
() => {
bug!("bug" + stringify!(found)); //~ ERROR unexpected expression: `"bug" + "found"`
bug!("bug" + stringify!(found)); //~ ERROR attribute value must be a literal
};
($test:expr) => {
#[doc = $test]
@ -46,7 +46,7 @@ macro_rules! doc_comment {
macro_rules! some_macro {
($t1: ty) => {
doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}
//~^ ERROR unexpected expression: `{
//~^ ERROR attribute value must be a literal
};
}

View file

@ -1,10 +1,10 @@
error: unexpected expression: `(7u32)`
error: attribute value must be a literal
--> $DIR/key-value-expansion.rs:21:6
|
LL | bug!((column!()));
| ^^^^^^^^^^^
error: unexpected expression: `"bug" + "found"`
error: attribute value must be a literal
--> $DIR/key-value-expansion.rs:27:14
|
LL | bug!("bug" + stringify!(found));
@ -15,7 +15,7 @@ LL | bug!();
|
= note: this error originates in the macro `bug` (in Nightly builds, run with -Z macro-backtrace for more info)
error: unexpected expression: `{ let res = ::alloc::fmt::format(format_args!("{0}", "u8")); res }.as_str()`
error: attribute value must be a literal
--> $DIR/key-value-expansion.rs:48:23
|
LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()}

View file

@ -1,5 +1,5 @@
#[w = { extern crate alloc; }]
//~^ ERROR unexpected expression: `{
//~^ ERROR attribute value must be a literal
//~| ERROR cannot find attribute `w` in this scope
fn f() {}

View file

@ -1,6 +1,4 @@
error: unexpected expression: `{
extern crate alloc;
}`
error: attribute value must be a literal
--> $DIR/unused-item-in-attr.rs:1:7
|
LL | #[w = { extern crate alloc; }]

View file

@ -5,10 +5,19 @@ LL | ) -> &usize {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | ) -> &'static usize {
| +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
|
LL | x: &usize,
| +
help: ...or alternatively, you might want to return an owned value
|
LL - ) -> &usize {
LL + ) -> usize {
|
error: aborting due to 1 previous error

View file

@ -0,0 +1,25 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
fn foo<const N: usize>(
_: [u8; {
{
N
}
}],
) {
}
fn ice<const L: usize>()
where
[(); (L - 1) + 1 + L]:,
{
foo::<_, L>([(); L + 1 + L]);
//~^ ERROR: mismatched types
//~^^ ERROR: unconstrained generic constant
//~^^^ ERROR: function takes 1 generic argument but 2 generic arguments were supplied
//~^^^^ ERROR: unconstrained generic constant
//~^^^^^ ERROR: unconstrained generic constant `{const expr}`
}
fn main() {}

View file

@ -0,0 +1,64 @@
error[E0107]: function takes 1 generic argument but 2 generic arguments were supplied
--> $DIR/issue_114151.rs:17:5
|
LL | foo::<_, L>([(); L + 1 + L]);
| ^^^ - help: remove this generic argument
| |
| expected 1 generic argument
|
note: function defined here, with 1 generic parameter: `N`
--> $DIR/issue_114151.rs:4:4
|
LL | fn foo<const N: usize>(
| ^^^ --------------
error[E0308]: mismatched types
--> $DIR/issue_114151.rs:17:18
|
LL | foo::<_, L>([(); L + 1 + L]);
| ^^ expected `u8`, found `()`
error: unconstrained generic constant
--> $DIR/issue_114151.rs:17:22
|
LL | foo::<_, L>([(); L + 1 + L]);
| ^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
error: unconstrained generic constant
--> $DIR/issue_114151.rs:17:17
|
LL | foo::<_, L>([(); L + 1 + L]);
| ----------- ^^^^^^^^^^^^^^^
| |
| required by a bound introduced by this call
|
= help: try adding a `where` bound using this expression: `where [(); {
{
N
}
}]:`
note: required by a bound in `foo`
--> $DIR/issue_114151.rs:5:13
|
LL | fn foo<const N: usize>(
| --- required by a bound in this function
LL | _: [u8; {
| _____________^
LL | | {
LL | | N
LL | | }
LL | | }],
| |_____^ required by this bound in `foo`
error: unconstrained generic constant `{const expr}`
--> $DIR/issue_114151.rs:17:5
|
LL | foo::<_, L>([(); L + 1 + L]);
| ^^^^^^^^^^^
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0107, E0308.
For more information about an error, try `rustc --explain E0107`.

View file

@ -1,4 +1,4 @@
#![l=|x|[b;x ]] //~ ERROR unexpected expression: `|x| [b; x]`
#![l=|x|[b;x ]] //~ ERROR attribute value must be a literal
//~^ ERROR cannot find attribute `l` in this scope
// notice the space at the start,

View file

@ -1,4 +1,4 @@
error: unexpected expression: `|x| [b; x]`
error: attribute value must be a literal
--> $DIR/issue-90878-2.rs:1:7
|
LL | #![l=|x|[b;x ]]

View file

@ -12,16 +12,63 @@ fn main() {
unsafe {
let ptr: *const Void = NonNull::dangling().as_ptr();
match *ptr {
! //~ ERROR `!` patterns are experimental
!
//~^ ERROR `!` patterns are experimental
}
// Check that the gate operates even behind `cfg`.
#[cfg(FALSE)]
match *ptr {
!
//~^ ERROR `!` patterns are experimental
}
#[cfg(FALSE)]
match *ptr {
! => {}
//~^ ERROR `!` patterns are experimental
}
}
// Correctly gate match arms with no body.
match Some(0) {
None => {}
Some(_),
//~^ ERROR unexpected `,` in pattern
}
match Some(0) {
None => {}
Some(_)
//~^ ERROR `match` arm with no body
}
match Some(0) {
_ => {}
Some(_) if false,
//~^ ERROR `match` arm with no body
Some(_) if false
//~^ ERROR `match` arm with no body
}
match res {
Ok(_) => {}
Err(!),
//~^ ERROR `!` patterns are experimental
}
match res {
Err(!) if false,
//~^ ERROR `!` patterns are experimental
//~| ERROR a guard on a never pattern will never be run
_ => {}
}
// Check that the gate operates even behind `cfg`.
#[cfg(FALSE)]
unsafe {
let ptr: *const Void = NonNull::dangling().as_ptr();
match *ptr {
! => {} //~ ERROR `!` patterns are experimental
}
match Some(0) {
None => {}
#[cfg(FALSE)]
Some(_)
//~^ ERROR `match` arm with no body
}
match Some(0) {
_ => {}
#[cfg(FALSE)]
Some(_) if false
//~^ ERROR `match` arm with no body
}
}

View file

@ -1,3 +1,18 @@
error: unexpected `,` in pattern
--> $DIR/feature-gate-never_patterns.rs:34:16
|
LL | Some(_),
| ^
|
help: try adding parentheses to match on a tuple...
|
LL | (Some(_),)
| + +
help: ...or a vertical bar to match on multiple alternatives
|
LL | Some(_) |
|
error[E0408]: variable `_x` is not bound in all patterns
--> $DIR/feature-gate-never_patterns.rs:8:19
|
@ -25,7 +40,16 @@ LL | !
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
error[E0658]: `!` patterns are experimental
--> $DIR/feature-gate-never_patterns.rs:24:13
--> $DIR/feature-gate-never_patterns.rs:21:13
|
LL | !
| ^
|
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
error[E0658]: `!` patterns are experimental
--> $DIR/feature-gate-never_patterns.rs:26:13
|
LL | ! => {}
| ^
@ -33,7 +57,61 @@ LL | ! => {}
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
error: aborting due to 4 previous errors
error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:39:9
|
LL | Some(_)
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:44:9
|
LL | Some(_) if false,
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:46:9
|
LL | Some(_) if false
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error[E0658]: `!` patterns are experimental
--> $DIR/feature-gate-never_patterns.rs:51:13
|
LL | Err(!),
| ^
|
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
error[E0658]: `!` patterns are experimental
--> $DIR/feature-gate-never_patterns.rs:55:13
|
LL | Err(!) if false,
| ^
|
= note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:65:9
|
LL | Some(_)
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:71:9
|
LL | Some(_) if false
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: a guard on a never pattern will never be run
--> $DIR/feature-gate-never_patterns.rs:55:19
|
LL | Err(!) if false,
| ^^^^^ help: remove this guard
error: aborting due to 14 previous errors
Some errors have detailed explanations: E0408, E0658.
For more information about an error, try `rustc --explain E0408`.

View file

@ -1,8 +0,0 @@
// run-rustfix
extern "C" {
pub fn g(_: &u8) -> &u8; // OK
pub fn f() -> &'static u8; //~ ERROR missing lifetime specifier
}
fn main() {}

View file

@ -1,5 +1,3 @@
// run-rustfix
extern "C" {
pub fn g(_: &u8) -> &u8; // OK
pub fn f() -> &u8; //~ ERROR missing lifetime specifier

View file

@ -1,14 +1,19 @@
error[E0106]: missing lifetime specifier
--> $DIR/foreign-fn-return-lifetime.rs:5:19
--> $DIR/foreign-fn-return-lifetime.rs:3:19
|
LL | pub fn f() -> &u8;
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | pub fn f() -> &'static u8;
| +++++++
help: instead, you are more likely to want to return an owned value
|
LL - pub fn f() -> &u8;
LL + pub fn f() -> u8;
|
error: aborting due to 1 previous error

View file

@ -11,7 +11,7 @@ LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> {
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'static>> {
| ~~~~~~~

View file

@ -5,7 +5,7 @@ LL | fn d() -> impl Fn() -> (impl Debug + '_) {
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | fn d() -> impl Fn() -> (impl Debug + 'static) {
| ~~~~~~~

View file

@ -5,10 +5,14 @@ LL | &str
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | &'static str
| +++++++
help: instead, you are more likely to want to return an owned value
|
LL | String
| ~~~~~~
error: aborting due to 1 previous error

View file

@ -17,10 +17,18 @@ LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() }
| +++++++
help: instead, you are more likely to want to change the argument to be borrowed...
|
LL | fn parse_type_2(iter: &fn(&u8)->&u8) -> &str { iter() }
| +
help: ...or alternatively, you might want to return an owned value
|
LL | fn parse_type_2(iter: fn(&u8)->&u8) -> String { iter() }
| ~~~~~~
error[E0106]: missing lifetime specifier
--> $DIR/issue-26638.rs:10:22
@ -29,10 +37,14 @@ LL | fn parse_type_3() -> &str { unimplemented!() }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn parse_type_3() -> &'static str { unimplemented!() }
| +++++++
help: instead, you are more likely to want to return an owned value
|
LL | fn parse_type_3() -> String { unimplemented!() }
| ~~~~~~
error[E0308]: mismatched types
--> $DIR/issue-26638.rs:1:69

View file

@ -5,10 +5,15 @@ LL | fn f() -> &isize {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn f() -> &'static isize {
| +++++++
help: instead, you are more likely to want to return an owned value
|
LL - fn f() -> &isize {
LL + fn f() -> isize {
|
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33
@ -41,10 +46,19 @@ LL | fn i(_x: isize) -> &isize {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn i(_x: isize) -> &'static isize {
| +++++++
help: instead, you are more likely to want to change the argument to be borrowed...
|
LL | fn i(_x: &isize) -> &isize {
| +
help: ...or alternatively, you might want to return an owned value
|
LL - fn i(_x: isize) -> &isize {
LL + fn i(_x: isize) -> isize {
|
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:34:24
@ -53,10 +67,19 @@ LL | fn j(_x: StaticStr) -> &isize {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn j(_x: StaticStr) -> &'static isize {
| +++++++
help: instead, you are more likely to want to change the argument to be borrowed...
|
LL | fn j(_x: &StaticStr) -> &isize {
| +
help: ...or alternatively, you might want to return an owned value
|
LL - fn j(_x: StaticStr) -> &isize {
LL + fn j(_x: StaticStr) -> isize {
|
error[E0106]: missing lifetime specifier
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:40:49

View file

@ -10,7 +10,7 @@ macro_rules! check {
check!("0"); // OK
check!(0); // OK
check!(0u8); //~ ERROR suffixed literals are not allowed in attributes
check!(-0); //~ ERROR unexpected expression: `-0`
check!(0 + 0); //~ ERROR unexpected expression: `0 + 0`
check!(-0); //~ ERROR attribute value must be a literal
check!(0 + 0); //~ ERROR attribute value must be a literal
fn main() {}

View file

@ -6,13 +6,13 @@ LL | check!(0u8);
|
= help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
error: unexpected expression: `-0`
error: attribute value must be a literal
--> $DIR/malformed-interpolated.rs:13:8
|
LL | check!(-0);
| ^^
error: unexpected expression: `0 + 0`
error: attribute value must be a literal
--> $DIR/malformed-interpolated.rs:14:8
|
LL | check!(0 + 0);

View file

@ -28,11 +28,12 @@ fn main() {
}
#[rustc_dummy = "string"suffix]
//~^ ERROR unexpected expression: `"string"suffix`
//~^ ERROR suffixes on string literals are invalid
fn f() {}
#[must_use = "string"suffix]
//~^ ERROR unexpected expression: `"string"suffix`
//~^ ERROR suffixes on string literals are invalid
//~| ERROR malformed `must_use` attribute input
fn g() {}
#[link(name = "string"suffix)]

View file

@ -10,26 +10,39 @@ error: suffixes on string literals are invalid
LL | "C"suffix
| ^^^^^^^^^ invalid suffix `suffix`
error: unexpected expression: `"string"suffix`
error: suffixes on string literals are invalid
--> $DIR/bad-lit-suffixes.rs:30:17
|
LL | #[rustc_dummy = "string"suffix]
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ invalid suffix `suffix`
error: unexpected expression: `"string"suffix`
error: suffixes on string literals are invalid
--> $DIR/bad-lit-suffixes.rs:34:14
|
LL | #[must_use = "string"suffix]
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ invalid suffix `suffix`
error: malformed `must_use` attribute input
--> $DIR/bad-lit-suffixes.rs:34:1
|
LL | #[must_use = "string"suffix]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: the following are the possible correct uses
|
LL | #[must_use = "reason"]
|
LL | #[must_use]
|
error: suffixes on string literals are invalid
--> $DIR/bad-lit-suffixes.rs:38:15
--> $DIR/bad-lit-suffixes.rs:39:15
|
LL | #[link(name = "string"suffix)]
| ^^^^^^^^^^^^^^ invalid suffix `suffix`
error: invalid suffix `suffix` for number literal
--> $DIR/bad-lit-suffixes.rs:42:41
--> $DIR/bad-lit-suffixes.rs:43:41
|
LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
| ^^^^^^^ invalid suffix `suffix`
@ -136,5 +149,5 @@ LL | 1.0e10suffix;
|
= help: valid suffixes are `f32` and `f64`
error: aborting due to 20 previous errors
error: aborting due to 21 previous errors

View file

@ -1,4 +1,4 @@
#![feature(rustc_attrs)]
#![rustc_dummy=5z] //~ ERROR unexpected expression: `5z`
#![rustc_dummy=5z] //~ ERROR invalid suffix `z` for number literal
fn main() {}

View file

@ -1,8 +1,10 @@
error: unexpected expression: `5z`
error: invalid suffix `z` for number literal
--> $DIR/issue-104620.rs:3:16
|
LL | #![rustc_dummy=5z]
| ^^
| ^^ invalid suffix `z`
|
= help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
error: aborting due to 1 previous error

View file

@ -66,8 +66,6 @@ fn main() {
pat!()
//~^ ERROR expected `,` following `match` arm
//~| HELP missing a comma here
//~| ERROR `match` arm with no body
//~| HELP add a body after the pattern
_ => {}
}
match Some(false) {

View file

@ -68,19 +68,19 @@ error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:30:9
|
LL | Some(_) if true
| ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:40:9
|
LL | Some(_) if true,
| ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:45:9
|
LL | Some(_) if true,
| ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
| ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:51:9
@ -98,19 +98,13 @@ error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:61:9
|
LL | pat!() if true,
| ^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:66:9
|
LL | pat!()
| ^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:74:9
--> $DIR/match-arm-without-body.rs:72:9
|
LL | pat!(),
| ^^^^^^- help: add a body after the pattern: `=> todo!(),`
error: aborting due to 14 previous errors
error: aborting due to 13 previous errors

View file

@ -21,10 +21,19 @@ LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &'static () {
| +++++++
help: instead, you are more likely to want to change the argument to be borrowed...
|
LL | fn wrap(self: &Wrap<{ fn bar(&self) {} }>) -> &() {
| +
help: ...or alternatively, you might want to return an owned value
|
LL - fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> &() {
LL + fn wrap(self: Wrap<{ fn bar(&self) {} }>) -> () {
|
error[E0412]: cannot find type `Wrap` in this scope
--> $DIR/nested-item.rs:5:15

View file

@ -5,10 +5,19 @@ LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn g(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
| +++++++
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
| ++++ ~~~ ~~~
help: alternatively, you might want to return an owned value
|
LL - fn g(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
LL + fn g(mut x: impl Iterator<Item = &()>) -> Option<()> { x.next() }
|
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:19:60
@ -17,10 +26,19 @@ LL | async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next()
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | async fn i(mut x: impl Iterator<Item = &()>) -> Option<&'static ()> { x.next() }
| +++++++
help: consider introducing a named lifetime parameter
|
LL | async fn i<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
| ++++ ~~~ ~~~
help: alternatively, you might want to return an owned value
|
LL - async fn i(mut x: impl Iterator<Item = &()>) -> Option<&()> { x.next() }
LL + async fn i(mut x: impl Iterator<Item = &()>) -> Option<()> { x.next() }
|
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:27:58
@ -29,10 +47,19 @@ LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next()
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
| ++++ ~~~ ~~~
help: alternatively, you might want to return an owned value
|
LL - fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
LL + fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
|
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:37:64
@ -41,10 +68,19 @@ LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.n
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
help: consider introducing a named lifetime parameter
|
LL | async fn i<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
| ++++ ~~~ ~~~
help: alternatively, you might want to return an owned value
|
LL - async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
LL + async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
|
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:47:37
@ -53,10 +89,19 @@ LL | fn g(mut x: impl Foo) -> Option<&()> { x.next() }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn g(mut x: impl Foo) -> Option<&'static ()> { x.next() }
| +++++++
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Foo) -> Option<&'a ()> { x.next() }
| ++++ ~~~
help: alternatively, you might want to return an owned value
|
LL - fn g(mut x: impl Foo) -> Option<&()> { x.next() }
LL + fn g(mut x: impl Foo) -> Option<()> { x.next() }
|
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime-gated.rs:58:41
@ -65,10 +110,19 @@ LL | fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn g(mut x: impl Foo<()>) -> Option<&'static ()> { x.next() }
| +++++++
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Foo<()>) -> Option<&'a ()> { x.next() }
| ++++ ~~~
help: alternatively, you might want to return an owned value
|
LL - fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
LL + fn g(mut x: impl Foo<()>) -> Option<()> { x.next() }
|
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:6:35

View file

@ -5,10 +5,19 @@ LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
help: consider introducing a named lifetime parameter
|
LL | fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
| ++++ ~~~ ~~~
help: alternatively, you might want to return an owned value
|
LL - fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
LL + fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
|
error[E0106]: missing lifetime specifier
--> $DIR/impl-trait-missing-lifetime.rs:16:60
@ -17,10 +26,19 @@ LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next(
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'static ()> { x.next() }
| ~~~~~~~
help: consider introducing a named lifetime parameter
|
LL | async fn i<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()> { x.next() }
| ++++ ~~~ ~~~
help: alternatively, you might want to return an owned value
|
LL - async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
LL + async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() }
|
error: lifetime may not live long enough
--> $DIR/impl-trait-missing-lifetime.rs:16:69

View file

@ -5,7 +5,7 @@ LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::
| ^^^ expected 2 lifetime parameters
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefCell::new(HashMap::new());
| ++++++++++++++++++
@ -32,7 +32,7 @@ LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap:
| expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | static b: RefCell<HashMap<i32, Vec<Vec<&'static Bar<'static, 'static>>>>> = RefCell::new(HashMap::new());
| +++++++ ++++++++++++++++++
@ -59,7 +59,7 @@ LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(Hash
| ^ expected 2 lifetime parameters
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++++++++++++
@ -86,7 +86,7 @@ LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(Has
| expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++ +++++++++++++++++
@ -113,7 +113,7 @@ LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| +++++++

View file

@ -5,10 +5,15 @@ LL | fn f1() -> &i32 { loop {} }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn f1() -> &'static i32 { loop {} }
| +++++++
help: instead, you are more likely to want to return an owned value
|
LL - fn f1() -> &i32 { loop {} }
LL + fn f1() -> i32 { loop {} }
|
error[E0106]: missing lifetime specifiers
--> $DIR/return-elided-lifetime.rs:8:14
@ -19,7 +24,7 @@ LL | fn f1_() -> (&i32, &i32) { loop {} }
| expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn f1_() -> (&'static i32, &'static i32) { loop {} }
| +++++++ +++++++
@ -31,10 +36,19 @@ LL | fn f2(a: i32, b: i32) -> &i32 { loop {} }
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn f2(a: i32, b: i32) -> &'static i32 { loop {} }
| +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
|
LL | fn f2(a: &i32, b: &i32) -> &i32 { loop {} }
| + +
help: ...or alternatively, you might want to return an owned value
|
LL - fn f2(a: i32, b: i32) -> &i32 { loop {} }
LL + fn f2(a: i32, b: i32) -> i32 { loop {} }
|
error[E0106]: missing lifetime specifiers
--> $DIR/return-elided-lifetime.rs:13:28
@ -45,7 +59,7 @@ LL | fn f2_(a: i32, b: i32) -> (&i32, &i32) { loop {} }
| expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
LL | fn f2_(a: i32, b: i32) -> (&'static i32, &'static i32) { loop {} }
| +++++++ +++++++

View file

@ -28,7 +28,7 @@ LL | fn meh() -> Box<dyn for<'_> Meh<'_>>
| ^^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
|
LL | fn meh() -> Box<dyn for<'_> Meh<'static>>
| ~~~~~~~