Auto merge of #129841 - matthiaskrgr:rollup-pkavdtl, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #128495 (core: use `compare_bytes` for more slice element types) - #128641 (refactor: standardize duplicate processes in parser) - #129207 (Lint that warns when an elided lifetime ends up being a named lifetime) - #129493 (Create opaque definitions in resolver.) - #129619 (Update stacker to 0.1.17) - #129672 (Make option-like-enum.rs UB-free and portable) - #129780 (add crashtests for several old unfixed ICEs) - #129832 (Remove stray dot in `std::char::from_u32_unchecked` documentation) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
78d5c04d9c
@ -4978,15 +4978,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.15"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
|
||||
checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"psm",
|
||||
"winapi",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -69,14 +69,14 @@ pub enum FnKind<'a> {
|
||||
Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>),
|
||||
|
||||
/// E.g., `|x, y| body`.
|
||||
Closure(&'a ClosureBinder, &'a FnDecl, &'a Expr),
|
||||
Closure(&'a ClosureBinder, &'a Option<CoroutineKind>, &'a FnDecl, &'a Expr),
|
||||
}
|
||||
|
||||
impl<'a> FnKind<'a> {
|
||||
pub fn header(&self) -> Option<&'a FnHeader> {
|
||||
match *self {
|
||||
FnKind::Fn(_, _, sig, _, _, _) => Some(&sig.header),
|
||||
FnKind::Closure(_, _, _) => None,
|
||||
FnKind::Closure(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ pub fn ident(&self) -> Option<&Ident> {
|
||||
pub fn decl(&self) -> &'a FnDecl {
|
||||
match self {
|
||||
FnKind::Fn(_, _, sig, _, _, _) => &sig.decl,
|
||||
FnKind::Closure(_, decl, _) => decl,
|
||||
FnKind::Closure(_, _, decl, _) => decl,
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,7 +839,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
|
||||
try_visit!(walk_fn_decl(visitor, decl));
|
||||
visit_opt!(visitor, visit_block, body);
|
||||
}
|
||||
FnKind::Closure(binder, decl, body) => {
|
||||
FnKind::Closure(binder, _coroutine_kind, decl, body) => {
|
||||
try_visit!(visitor.visit_closure_binder(binder));
|
||||
try_visit!(walk_fn_decl(visitor, decl));
|
||||
try_visit!(visitor.visit_expr(body));
|
||||
@ -1107,7 +1107,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
ExprKind::Closure(box Closure {
|
||||
binder,
|
||||
capture_clause,
|
||||
coroutine_kind: _,
|
||||
coroutine_kind,
|
||||
constness: _,
|
||||
movability: _,
|
||||
fn_decl,
|
||||
@ -1116,7 +1116,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
|
||||
fn_arg_span: _,
|
||||
}) => {
|
||||
try_visit!(visitor.visit_capture_by(capture_clause));
|
||||
try_visit!(visitor.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id))
|
||||
try_visit!(visitor.visit_fn(
|
||||
FnKind::Closure(binder, coroutine_kind, fn_decl, body),
|
||||
*span,
|
||||
*id
|
||||
))
|
||||
}
|
||||
ExprKind::Block(block, opt_label) => {
|
||||
visit_opt!(visitor, visit_label, opt_label);
|
||||
|
@ -45,7 +45,6 @@
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
@ -837,7 +836,7 @@ fn lifetime_res_to_generic_param(
|
||||
|
||||
(hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind))
|
||||
}
|
||||
LifetimeRes::Static | LifetimeRes::Error => return None,
|
||||
LifetimeRes::Static { .. } | LifetimeRes::Error => return None,
|
||||
res => panic!(
|
||||
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
|
||||
res, ident, ident.span
|
||||
@ -1399,24 +1398,9 @@ fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir>
|
||||
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnApit { span });
|
||||
}
|
||||
|
||||
let span = t.span;
|
||||
|
||||
// HACK: pprust breaks strings with newlines when the type
|
||||
// gets too long. We don't want these to show up in compiler
|
||||
// output or built artifacts, so replace them here...
|
||||
// Perhaps we should instead format APITs more robustly.
|
||||
let ident = Ident::from_str_and_span(
|
||||
&pprust::ty_to_string(t).replace('\n', " "),
|
||||
span,
|
||||
);
|
||||
|
||||
self.create_def(
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
*def_node_id,
|
||||
ident.name,
|
||||
DefKind::TyParam,
|
||||
span,
|
||||
);
|
||||
let def_id = self.local_def_id(*def_node_id);
|
||||
let name = self.tcx.item_name(def_id.to_def_id());
|
||||
let ident = Ident::new(name, span);
|
||||
let (param, bounds, path) = self.lower_universal_param_and_bounds(
|
||||
*def_node_id,
|
||||
span,
|
||||
@ -1618,13 +1602,7 @@ fn lower_opaque_inner(
|
||||
opaque_ty_span: Span,
|
||||
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
|
||||
) -> hir::TyKind<'hir> {
|
||||
let opaque_ty_def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
opaque_ty_node_id,
|
||||
kw::Empty,
|
||||
DefKind::OpaqueTy,
|
||||
opaque_ty_span,
|
||||
);
|
||||
let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
|
||||
debug!(?opaque_ty_def_id);
|
||||
|
||||
// Map from captured (old) lifetime to synthetic (new) lifetime.
|
||||
@ -1656,7 +1634,7 @@ fn lower_opaque_inner(
|
||||
}
|
||||
|
||||
// Opaques do not capture `'static`
|
||||
LifetimeRes::Static | LifetimeRes::Error => {
|
||||
LifetimeRes::Static { .. } | LifetimeRes::Error => {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2069,7 +2047,7 @@ fn new_named_lifetime_with_res(
|
||||
hir::LifetimeName::Param(param)
|
||||
}
|
||||
LifetimeRes::Infer => hir::LifetimeName::Infer,
|
||||
LifetimeRes::Static => hir::LifetimeName::Static,
|
||||
LifetimeRes::Static { .. } => hir::LifetimeName::Static,
|
||||
LifetimeRes::Error => hir::LifetimeName::Error,
|
||||
res => panic!(
|
||||
"Unexpected lifetime resolution {:?} for {:?} at {:?}",
|
||||
|
@ -27,7 +27,7 @@ fn record_lifetime_use(&mut self, lifetime: Lifetime) {
|
||||
self.collected_lifetimes.insert(lifetime);
|
||||
}
|
||||
}
|
||||
LifetimeRes::Static | LifetimeRes::Error => {
|
||||
LifetimeRes::Static { .. } | LifetimeRes::Error => {
|
||||
self.collected_lifetimes.insert(lifetime);
|
||||
}
|
||||
LifetimeRes::Infer => {}
|
||||
|
@ -1485,7 +1485,7 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
|
||||
|
||||
let disallowed = (!tilde_const_allowed).then(|| match fk {
|
||||
FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span },
|
||||
FnKind::Closure(_, _, _) => TildeConstReason::Closure,
|
||||
FnKind::Closure(..) => TildeConstReason::Closure,
|
||||
});
|
||||
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ rustc_index = { path = "../rustc_index", package = "rustc_index" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
|
||||
stacker = "0.1.15"
|
||||
stacker = "0.1.17"
|
||||
tempfile = "3.2"
|
||||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
|
@ -863,8 +863,13 @@ pub enum LifetimeRes {
|
||||
/// This variant is used for anonymous lifetimes that we did not resolve during
|
||||
/// late resolution. Those lifetimes will be inferred by typechecking.
|
||||
Infer,
|
||||
/// Explicit `'static` lifetime.
|
||||
Static,
|
||||
/// `'static` lifetime.
|
||||
Static {
|
||||
/// We do not want to emit `elided_named_lifetimes`
|
||||
/// when we are inside of a const item or a static,
|
||||
/// because it would get too annoying.
|
||||
suppress_elision_warning: bool,
|
||||
},
|
||||
/// Resolution failure.
|
||||
Error,
|
||||
/// HACK: This is used to recover the NodeId of an elided lifetime.
|
||||
|
@ -252,6 +252,10 @@ lint_duplicate_macro_attribute =
|
||||
|
||||
lint_duplicate_matcher_binding = duplicate matcher binding
|
||||
|
||||
lint_elided_named_lifetime = elided lifetime has a name
|
||||
.label_elided = this elided lifetime gets resolved as `{$name}`
|
||||
.label_named = lifetime `{$name}` declared here
|
||||
|
||||
lint_enum_intrinsics_mem_discriminant =
|
||||
the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
.note = the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum
|
||||
|
@ -10,6 +10,7 @@
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::BytePos;
|
||||
use tracing::debug;
|
||||
|
||||
@ -441,5 +442,17 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
|
||||
BuiltinLintDiag::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by } => {
|
||||
lints::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.decorate_lint(diag)
|
||||
}
|
||||
BuiltinLintDiag::ElidedIsStatic { elided } => {
|
||||
lints::ElidedNamedLifetime { elided, name: kw::StaticLifetime, named_declaration: None }
|
||||
.decorate_lint(diag)
|
||||
}
|
||||
BuiltinLintDiag::ElidedIsParam { elided, param: (param_name, param_span) } => {
|
||||
lints::ElidedNamedLifetime {
|
||||
elided,
|
||||
name: param_name,
|
||||
named_declaration: Some(param_span),
|
||||
}
|
||||
.decorate_lint(diag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2611,6 +2611,16 @@ pub(crate) struct ElidedLifetimesInPaths {
|
||||
pub subdiag: ElidedLifetimeInPathSubdiag,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_elided_named_lifetime)]
|
||||
pub(crate) struct ElidedNamedLifetime {
|
||||
#[label(lint_label_elided)]
|
||||
pub elided: Span,
|
||||
pub name: Symbol,
|
||||
#[label(lint_label_named)]
|
||||
pub named_declaration: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_invalid_crate_type_value)]
|
||||
pub(crate) struct UnknownCrateTypes {
|
||||
|
@ -42,6 +42,7 @@
|
||||
DUPLICATE_MACRO_ATTRIBUTES,
|
||||
ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
|
||||
ELIDED_LIFETIMES_IN_PATHS,
|
||||
ELIDED_NAMED_LIFETIMES,
|
||||
EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
|
||||
EXPORTED_PRIVATE_DEPENDENCIES,
|
||||
FFI_UNWIND_CALLS,
|
||||
@ -1862,6 +1863,38 @@
|
||||
"hidden lifetime parameters in types are deprecated"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `elided_named_lifetimes` lint detects when an elided
|
||||
/// lifetime ends up being a named lifetime, such as `'static`
|
||||
/// or some lifetime parameter `'a`.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(elided_named_lifetimes)]
|
||||
/// struct Foo;
|
||||
/// impl Foo {
|
||||
/// pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
|
||||
/// unsafe { &mut *(x as *mut _) }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Lifetime elision is quite useful, because it frees you from having
|
||||
/// to give each lifetime its own name, but sometimes it can produce
|
||||
/// somewhat surprising resolutions. In safe code, it is mostly okay,
|
||||
/// because the borrow checker prevents any unsoundness, so the worst
|
||||
/// case scenario is you get a confusing error message in some other place.
|
||||
/// But with `unsafe` code, such unexpected resolutions may lead to unsound code.
|
||||
pub ELIDED_NAMED_LIFETIMES,
|
||||
Warn,
|
||||
"detects when an elided lifetime gets resolved to be `'static` or some named parameter"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `bare_trait_objects` lint suggests using `dyn Trait` for trait
|
||||
/// objects.
|
||||
|
@ -589,6 +589,13 @@ pub enum BuiltinLintDiag {
|
||||
},
|
||||
MacroExpandedMacroExportsAccessedByAbsolutePaths(Span),
|
||||
ElidedLifetimesInPaths(usize, Span, bool, Span),
|
||||
ElidedIsStatic {
|
||||
elided: Span,
|
||||
},
|
||||
ElidedIsParam {
|
||||
elided: Span,
|
||||
param: (Symbol, Span),
|
||||
},
|
||||
UnknownCrateTypes {
|
||||
span: Span,
|
||||
candidate: Option<Symbol>,
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use rustc_ast::visit::FnKind;
|
||||
use rustc_ast::*;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_expand::expand::AstFragment;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
||||
@ -120,8 +121,6 @@ fn visit_macro_invoc(&mut self, id: NodeId) {
|
||||
|
||||
impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> {
|
||||
fn visit_item(&mut self, i: &'a Item) {
|
||||
debug!("visit_item: {:?}", i);
|
||||
|
||||
// Pick the def data. This need not be unique, but the more
|
||||
// information we encapsulate into, the better
|
||||
let mut opt_macro_data = None;
|
||||
@ -183,38 +182,51 @@ fn visit_item(&mut self, i: &'a Item) {
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
||||
if let FnKind::Fn(_, _, sig, _, generics, body) = fn_kind {
|
||||
match sig.header.coroutine_kind {
|
||||
Some(coroutine_kind) => {
|
||||
self.visit_generics(generics);
|
||||
match fn_kind {
|
||||
FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body)
|
||||
if let Some(coroutine_kind) = header.coroutine_kind =>
|
||||
{
|
||||
self.visit_fn_header(header);
|
||||
self.visit_generics(generics);
|
||||
|
||||
// For async functions, we need to create their inner defs inside of a
|
||||
// closure to match their desugared representation. Besides that,
|
||||
// we must mirror everything that `visit::walk_fn` below does.
|
||||
self.visit_fn_header(&sig.header);
|
||||
for param in &sig.decl.inputs {
|
||||
self.visit_param(param);
|
||||
}
|
||||
self.visit_fn_ret_ty(&sig.decl.output);
|
||||
// If this async fn has no body (i.e. it's an async fn signature in a trait)
|
||||
// then the closure_def will never be used, and we should avoid generating a
|
||||
// def-id for it.
|
||||
if let Some(body) = body {
|
||||
let closure_def = self.create_def(
|
||||
coroutine_kind.closure_id(),
|
||||
kw::Empty,
|
||||
DefKind::Closure,
|
||||
span,
|
||||
);
|
||||
self.with_parent(closure_def, |this| this.visit_block(body));
|
||||
}
|
||||
return;
|
||||
// For async functions, we need to create their inner defs inside of a
|
||||
// closure to match their desugared representation. Besides that,
|
||||
// we must mirror everything that `visit::walk_fn` below does.
|
||||
let FnDecl { inputs, output } = &**decl;
|
||||
for param in inputs {
|
||||
self.visit_param(param);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
visit::walk_fn(self, fn_kind);
|
||||
let (return_id, return_span) = coroutine_kind.return_id();
|
||||
let return_def =
|
||||
self.create_def(return_id, kw::Empty, DefKind::OpaqueTy, return_span);
|
||||
self.with_parent(return_def, |this| this.visit_fn_ret_ty(output));
|
||||
|
||||
// If this async fn has no body (i.e. it's an async fn signature in a trait)
|
||||
// then the closure_def will never be used, and we should avoid generating a
|
||||
// def-id for it.
|
||||
if let Some(body) = body {
|
||||
let closure_def = self.create_def(
|
||||
coroutine_kind.closure_id(),
|
||||
kw::Empty,
|
||||
DefKind::Closure,
|
||||
span,
|
||||
);
|
||||
self.with_parent(closure_def, |this| this.visit_block(body));
|
||||
}
|
||||
}
|
||||
FnKind::Closure(binder, Some(coroutine_kind), decl, body) => {
|
||||
self.visit_closure_binder(binder);
|
||||
visit::walk_fn_decl(self, decl);
|
||||
|
||||
// Async closures desugar to closures inside of closures, so
|
||||
// we must create two defs.
|
||||
let coroutine_def =
|
||||
self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span);
|
||||
self.with_parent(coroutine_def, |this| visit::walk_expr(this, body));
|
||||
}
|
||||
_ => visit::walk_fn(self, fn_kind),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
|
||||
@ -334,27 +346,7 @@ fn visit_anon_const(&mut self, constant: &'a AnonConst) {
|
||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||
let parent_def = match expr.kind {
|
||||
ExprKind::MacCall(..) => return self.visit_macro_invoc(expr.id),
|
||||
ExprKind::Closure(ref closure) => {
|
||||
// Async closures desugar to closures inside of closures, so
|
||||
// we must create two defs.
|
||||
let closure_def = self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span);
|
||||
match closure.coroutine_kind {
|
||||
Some(coroutine_kind) => {
|
||||
self.with_parent(closure_def, |this| {
|
||||
let coroutine_def = this.create_def(
|
||||
coroutine_kind.closure_id(),
|
||||
kw::Empty,
|
||||
DefKind::Closure,
|
||||
expr.span,
|
||||
);
|
||||
this.with_parent(coroutine_def, |this| visit::walk_expr(this, expr));
|
||||
});
|
||||
return;
|
||||
}
|
||||
None => closure_def,
|
||||
}
|
||||
}
|
||||
ExprKind::Gen(_, _, _, _) => {
|
||||
ExprKind::Closure(..) | ExprKind::Gen(..) => {
|
||||
self.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
|
||||
}
|
||||
ExprKind::ConstBlock(ref constant) => {
|
||||
@ -381,6 +373,26 @@ fn visit_ty(&mut self, ty: &'a Ty) {
|
||||
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
|
||||
// Anonymous structs or unions are visited later after defined.
|
||||
TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {}
|
||||
TyKind::ImplTrait(id, _) => {
|
||||
// HACK: pprust breaks strings with newlines when the type
|
||||
// gets too long. We don't want these to show up in compiler
|
||||
// output or built artifacts, so replace them here...
|
||||
// Perhaps we should instead format APITs more robustly.
|
||||
let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " "));
|
||||
let kind = match self.impl_trait_context {
|
||||
ImplTraitContext::Universal => DefKind::TyParam,
|
||||
ImplTraitContext::Existential => DefKind::OpaqueTy,
|
||||
};
|
||||
let id = self.create_def(*id, name, kind, ty.span);
|
||||
match self.impl_trait_context {
|
||||
// Do not nest APIT, as we desugar them as `impl_trait: bounds`,
|
||||
// so the `impl_trait` node is not a parent to `bounds`.
|
||||
ImplTraitContext::Universal => visit::walk_ty(self, ty),
|
||||
ImplTraitContext::Existential => {
|
||||
self.with_parent(id, |this| visit::walk_ty(this, ty))
|
||||
}
|
||||
};
|
||||
}
|
||||
_ => visit::walk_ty(self, ty),
|
||||
}
|
||||
}
|
||||
|
@ -1010,7 +1010,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
|
||||
this.in_func_body = previous_state;
|
||||
}
|
||||
}
|
||||
FnKind::Closure(binder, declaration, body) => {
|
||||
FnKind::Closure(binder, _, declaration, body) => {
|
||||
this.visit_closure_binder(binder);
|
||||
|
||||
this.with_lifetime_rib(
|
||||
@ -1557,14 +1557,14 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
if ident.name == kw::StaticLifetime {
|
||||
self.record_lifetime_res(
|
||||
lifetime.id,
|
||||
LifetimeRes::Static,
|
||||
LifetimeRes::Static { suppress_elision_warning: false },
|
||||
LifetimeElisionCandidate::Named,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if ident.name == kw::UnderscoreLifetime {
|
||||
return self.resolve_anonymous_lifetime(lifetime, false);
|
||||
return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false);
|
||||
}
|
||||
|
||||
let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
|
||||
@ -1667,13 +1667,23 @@ fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::Lifeti
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
|
||||
fn resolve_anonymous_lifetime(
|
||||
&mut self,
|
||||
lifetime: &Lifetime,
|
||||
id_for_lint: NodeId,
|
||||
elided: bool,
|
||||
) {
|
||||
debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
|
||||
|
||||
let kind =
|
||||
if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore };
|
||||
let missing_lifetime =
|
||||
MissingLifetime { id: lifetime.id, span: lifetime.ident.span, kind, count: 1 };
|
||||
let missing_lifetime = MissingLifetime {
|
||||
id: lifetime.id,
|
||||
span: lifetime.ident.span,
|
||||
kind,
|
||||
count: 1,
|
||||
id_for_lint,
|
||||
};
|
||||
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
|
||||
for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() {
|
||||
debug!(?rib.kind);
|
||||
@ -1697,7 +1707,8 @@ fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
|
||||
if lifetimes_in_scope.is_empty() {
|
||||
self.record_lifetime_res(
|
||||
lifetime.id,
|
||||
LifetimeRes::Static,
|
||||
// We are inside a const item, so do not warn.
|
||||
LifetimeRes::Static { suppress_elision_warning: true },
|
||||
elision_candidate,
|
||||
);
|
||||
return;
|
||||
@ -1800,7 +1811,7 @@ fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
|
||||
LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) },
|
||||
LifetimeElisionCandidate::Ignore,
|
||||
);
|
||||
self.resolve_anonymous_lifetime(<, true);
|
||||
self.resolve_anonymous_lifetime(<, anchor_id, true);
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
@ -1916,6 +1927,7 @@ fn resolve_elided_lifetimes_in_path(
|
||||
};
|
||||
let missing_lifetime = MissingLifetime {
|
||||
id: node_ids.start,
|
||||
id_for_lint: segment_id,
|
||||
span: elided_lifetime_span,
|
||||
kind,
|
||||
count: expected_lifetimes,
|
||||
@ -2039,8 +2051,44 @@ fn record_lifetime_res(
|
||||
if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
|
||||
panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)")
|
||||
}
|
||||
|
||||
match candidate {
|
||||
LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => {
|
||||
debug_assert_eq!(id, missing.id);
|
||||
match res {
|
||||
LifetimeRes::Static { suppress_elision_warning } => {
|
||||
if !suppress_elision_warning {
|
||||
self.r.lint_buffer.buffer_lint(
|
||||
lint::builtin::ELIDED_NAMED_LIFETIMES,
|
||||
missing.id_for_lint,
|
||||
missing.span,
|
||||
BuiltinLintDiag::ElidedIsStatic { elided: missing.span },
|
||||
);
|
||||
}
|
||||
}
|
||||
LifetimeRes::Param { param, binder: _ } => {
|
||||
let tcx = self.r.tcx();
|
||||
self.r.lint_buffer.buffer_lint(
|
||||
lint::builtin::ELIDED_NAMED_LIFETIMES,
|
||||
missing.id_for_lint,
|
||||
missing.span,
|
||||
BuiltinLintDiag::ElidedIsParam {
|
||||
elided: missing.span,
|
||||
param: (tcx.item_name(param.into()), tcx.source_span(param)),
|
||||
},
|
||||
);
|
||||
}
|
||||
LifetimeRes::Fresh { .. }
|
||||
| LifetimeRes::Infer
|
||||
| LifetimeRes::Error
|
||||
| LifetimeRes::ElidedAnchor { .. } => {}
|
||||
}
|
||||
}
|
||||
LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {}
|
||||
}
|
||||
|
||||
match res {
|
||||
LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static => {
|
||||
LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => {
|
||||
if let Some(ref mut candidates) = self.lifetime_elision_candidates {
|
||||
candidates.push((res, candidate));
|
||||
}
|
||||
@ -2558,9 +2606,14 @@ fn resolve_item(&mut self, item: &'ast Item) {
|
||||
|
||||
ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
|
||||
self.with_static_rib(def_kind, |this| {
|
||||
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
|
||||
this.visit_ty(ty);
|
||||
});
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::Elided(LifetimeRes::Static {
|
||||
suppress_elision_warning: true,
|
||||
}),
|
||||
|this| {
|
||||
this.visit_ty(ty);
|
||||
},
|
||||
);
|
||||
if let Some(expr) = expr {
|
||||
// We already forbid generic params because of the above item rib,
|
||||
// so it doesn't matter whether this is a trivial constant.
|
||||
@ -2589,7 +2642,9 @@ fn resolve_item(&mut self, item: &'ast Item) {
|
||||
this.visit_generics(generics);
|
||||
|
||||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::Elided(LifetimeRes::Static),
|
||||
LifetimeRibKind::Elided(LifetimeRes::Static {
|
||||
suppress_elision_warning: true,
|
||||
}),
|
||||
|this| this.visit_ty(ty),
|
||||
);
|
||||
|
||||
|
@ -102,6 +102,13 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str
|
||||
pub(super) struct MissingLifetime {
|
||||
/// Used to overwrite the resolution with the suggestion, to avoid cascading errors.
|
||||
pub id: NodeId,
|
||||
/// As we cannot yet emit lints in this crate and have to buffer them instead,
|
||||
/// we need to associate each lint with some `NodeId`,
|
||||
/// however for some `MissingLifetime`s their `NodeId`s are "fake",
|
||||
/// in a sense that they are temporary and not get preserved down the line,
|
||||
/// which means that the lints for those nodes will not get emitted.
|
||||
/// To combat this, we can try to use some other `NodeId`s as a fallback option.
|
||||
pub id_for_lint: NodeId,
|
||||
/// Where to suggest adding the lifetime.
|
||||
pub span: Span,
|
||||
/// How the lifetime was introduced, to have the correct space and comma.
|
||||
@ -3028,7 +3035,7 @@ fn add_missing_lifetime_specifiers_label(
|
||||
maybe_static = true;
|
||||
in_scope_lifetimes = vec![(
|
||||
Ident::with_dummy_span(kw::StaticLifetime),
|
||||
(DUMMY_NODE_ID, LifetimeRes::Static),
|
||||
(DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }),
|
||||
)];
|
||||
}
|
||||
} else if elided_len == 0 {
|
||||
@ -3040,7 +3047,7 @@ fn add_missing_lifetime_specifiers_label(
|
||||
maybe_static = true;
|
||||
in_scope_lifetimes = vec![(
|
||||
Ident::with_dummy_span(kw::StaticLifetime),
|
||||
(DUMMY_NODE_ID, LifetimeRes::Static),
|
||||
(DUMMY_NODE_ID, LifetimeRes::Static { suppress_elision_warning: false }),
|
||||
)];
|
||||
}
|
||||
} else if num_params == 1 {
|
||||
|
@ -2313,7 +2313,7 @@ fn is_suffix_of<'a>(self, haystack: &'a str) -> bool
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&str>
|
||||
fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str>
|
||||
where
|
||||
Self::Searcher<'a>: core::str::pattern::ReverseSearcher<'a>,
|
||||
{
|
||||
|
@ -122,7 +122,7 @@ pub const fn from_u32(i: u32) -> Option<char> {
|
||||
self::convert::from_u32(i)
|
||||
}
|
||||
|
||||
/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`].
|
||||
/// Converts a `u32` to a `char`, ignoring validity. Use [`char::from_u32_unchecked`]
|
||||
/// instead.
|
||||
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
|
||||
#[rustc_const_stable(feature = "const_char_from_u32_unchecked", since = "1.81.0")]
|
||||
|
@ -110,43 +110,43 @@ fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> Argument<'b>
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_display<'b, T: Display>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, Display::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_debug<'b, T: Debug>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, Debug::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_debug_noop<'b, T: Debug>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, |_, _| Ok(()))
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_octal<'b, T: Octal>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, Octal::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_lower_hex<'b, T: LowerHex>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, LowerHex::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_upper_hex<'b, T: UpperHex>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, UpperHex::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_pointer<'b, T: Pointer>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, Pointer::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_binary<'b, T: Binary>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, Binary::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_lower_exp<'b, T: LowerExp>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, LowerExp::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'_> {
|
||||
pub fn new_upper_exp<'b, T: UpperExp>(x: &'b T) -> Argument<'b> {
|
||||
Self::new(x, UpperExp::fmt)
|
||||
}
|
||||
#[inline(always)]
|
||||
|
@ -112,18 +112,18 @@ fn read_number<T: ReadNumberHelper + TryFrom<u32>>(
|
||||
max_digits: Option<usize>,
|
||||
allow_zero_prefix: bool,
|
||||
) -> Option<T> {
|
||||
// If max_digits.is_some(), then we are parsing a `u8` or `u16` and
|
||||
// don't need to use checked arithmetic since it fits within a `u32`.
|
||||
if let Some(max_digits) = max_digits {
|
||||
// u32::MAX = 4_294_967_295u32, which is 10 digits long.
|
||||
// `max_digits` must be less than 10 to not overflow a `u32`.
|
||||
debug_assert!(max_digits < 10);
|
||||
self.read_atomically(move |p| {
|
||||
let mut digit_count = 0;
|
||||
let has_leading_zero = p.peek_char() == Some('0');
|
||||
|
||||
// If max_digits.is_some(), then we are parsing a `u8` or `u16` and
|
||||
// don't need to use checked arithmetic since it fits within a `u32`.
|
||||
let result = if let Some(max_digits) = max_digits {
|
||||
// u32::MAX = 4_294_967_295u32, which is 10 digits long.
|
||||
// `max_digits` must be less than 10 to not overflow a `u32`.
|
||||
debug_assert!(max_digits < 10);
|
||||
|
||||
self.read_atomically(move |p| {
|
||||
let mut result = 0_u32;
|
||||
let mut digit_count = 0;
|
||||
let has_leading_zero = p.peek_char() == Some('0');
|
||||
|
||||
while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) {
|
||||
result *= radix;
|
||||
result += digit;
|
||||
@ -134,19 +134,9 @@ fn read_number<T: ReadNumberHelper + TryFrom<u32>>(
|
||||
}
|
||||
}
|
||||
|
||||
if digit_count == 0 {
|
||||
None
|
||||
} else if !allow_zero_prefix && has_leading_zero && digit_count > 1 {
|
||||
None
|
||||
} else {
|
||||
result.try_into().ok()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
self.read_atomically(move |p| {
|
||||
result.try_into().ok()
|
||||
} else {
|
||||
let mut result = T::ZERO;
|
||||
let mut digit_count = 0;
|
||||
let has_leading_zero = p.peek_char() == Some('0');
|
||||
|
||||
while let Some(digit) = p.read_atomically(|p| p.read_char()?.to_digit(radix)) {
|
||||
result = result.checked_mul(radix)?;
|
||||
@ -154,15 +144,17 @@ fn read_number<T: ReadNumberHelper + TryFrom<u32>>(
|
||||
digit_count += 1;
|
||||
}
|
||||
|
||||
if digit_count == 0 {
|
||||
None
|
||||
} else if !allow_zero_prefix && has_leading_zero && digit_count > 1 {
|
||||
None
|
||||
} else {
|
||||
Some(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(result)
|
||||
};
|
||||
|
||||
if digit_count == 0 {
|
||||
None
|
||||
} else if !allow_zero_prefix && has_leading_zero && digit_count > 1 {
|
||||
None
|
||||
} else {
|
||||
result
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Reads an IPv4 address.
|
||||
|
@ -3,7 +3,8 @@
|
||||
use super::{from_raw_parts, memchr};
|
||||
use crate::cmp::{self, BytewiseEq, Ordering};
|
||||
use crate::intrinsics::compare_bytes;
|
||||
use crate::mem;
|
||||
use crate::num::NonZero;
|
||||
use crate::{ascii, mem};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, U> PartialEq<[U]> for [T]
|
||||
@ -182,19 +183,41 @@ impl<A: Ord> SliceOrd for A {
|
||||
}
|
||||
}
|
||||
|
||||
// `compare_bytes` compares a sequence of unsigned bytes lexicographically.
|
||||
// this matches the order we want for [u8], but no others (not even [i8]).
|
||||
impl SliceOrd for u8 {
|
||||
/// Marks that a type should be treated as an unsigned byte for comparisons.
|
||||
///
|
||||
/// # Safety
|
||||
/// * The type must be readable as an `u8`, meaning it has to have the same
|
||||
/// layout as `u8` and always be initialized.
|
||||
/// * For every `x` and `y` of this type, `Ord(x, y)` must return the same
|
||||
/// value as `Ord::cmp(transmute::<_, u8>(x), transmute::<_, u8>(y))`.
|
||||
#[rustc_specialization_trait]
|
||||
unsafe trait UnsignedBytewiseOrd {}
|
||||
|
||||
unsafe impl UnsignedBytewiseOrd for bool {}
|
||||
unsafe impl UnsignedBytewiseOrd for u8 {}
|
||||
unsafe impl UnsignedBytewiseOrd for NonZero<u8> {}
|
||||
unsafe impl UnsignedBytewiseOrd for Option<NonZero<u8>> {}
|
||||
unsafe impl UnsignedBytewiseOrd for ascii::Char {}
|
||||
|
||||
// `compare_bytes` compares a sequence of unsigned bytes lexicographically, so
|
||||
// use it if the requirements for `UnsignedBytewiseOrd` are fulfilled.
|
||||
impl<A: Ord + UnsignedBytewiseOrd> SliceOrd for A {
|
||||
#[inline]
|
||||
fn compare(left: &[Self], right: &[Self]) -> Ordering {
|
||||
// Since the length of a slice is always less than or equal to isize::MAX, this never underflows.
|
||||
// Since the length of a slice is always less than or equal to
|
||||
// isize::MAX, this never underflows.
|
||||
let diff = left.len() as isize - right.len() as isize;
|
||||
// This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags.
|
||||
// This comparison gets optimized away (on x86_64 and ARM) because the
|
||||
// subtraction updates flags.
|
||||
let len = if left.len() < right.len() { left.len() } else { right.len() };
|
||||
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
|
||||
// We use the minimum of both lengths which guarantees that both regions are
|
||||
// valid for reads in that interval.
|
||||
let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr(), len) as isize };
|
||||
let left = left.as_ptr().cast();
|
||||
let right = right.as_ptr().cast();
|
||||
// SAFETY: `left` and `right` are references and are thus guaranteed to
|
||||
// be valid. `UnsignedBytewiseOrd` is only implemented for types that
|
||||
// are valid u8s and can be compared the same way. We use the minimum
|
||||
// of both lengths which guarantees that both regions are valid for
|
||||
// reads in that interval.
|
||||
let mut order = unsafe { compare_bytes(left, right, len) as isize };
|
||||
if order == 0 {
|
||||
order = diff;
|
||||
}
|
||||
|
@ -1,3 +1,14 @@
|
||||
error: elided lifetime has a name
|
||||
--> tests/ui/needless_lifetimes.rs:266:52
|
||||
|
|
||||
LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
|
||||
| -- ^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
|
||||
= note: `-D elided-named-lifetimes` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]`
|
||||
|
||||
error: the following explicit lifetimes could be elided: 'a, 'b
|
||||
--> tests/ui/needless_lifetimes.rs:17:23
|
||||
|
|
||||
@ -553,5 +564,5 @@ LL - fn one_input<'a>(x: &'a u8) -> &'a u8 {
|
||||
LL + fn one_input(x: &u8) -> &u8 {
|
||||
|
|
||||
|
||||
error: aborting due to 46 previous errors
|
||||
error: aborting due to 47 previous errors
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
error: elided lifetime has a name
|
||||
--> tests/ui/ptr_arg.rs:295:56
|
||||
|
|
||||
LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str {
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `-D elided-named-lifetimes` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]`
|
||||
|
||||
error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
|
||||
--> tests/ui/ptr_arg.rs:13:14
|
||||
|
|
||||
@ -212,5 +221,5 @@ error: using a reference to `Cow` is not recommended
|
||||
LL | fn cow_bad_ret_ty_2<'a, 'b>(input: &'a Cow<'a, str>) -> &'b str {
|
||||
| ^^^^^^^^^^^^^^^^ help: change this to: `&str`
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: reading memory at ALLOC[0x0..0x10], but memory is uninitialized at [0x4..0x10], and this operation requires initialized memory
|
||||
--> RUSTLIB/core/src/slice/cmp.rs:LL:CC
|
||||
|
|
||||
LL | let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr(), len) as isize };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x10], but memory is uninitialized at [0x4..0x10], and this operation requires initialized memory
|
||||
LL | let mut order = unsafe { compare_bytes(left, right, len) as isize };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x10], but memory is uninitialized at [0x4..0x10], and this operation requires initialized memory
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
|
||||
--> RUSTLIB/core/src/slice/cmp.rs:LL:CC
|
||||
|
|
||||
LL | let mut order = unsafe { compare_bytes(left.as_ptr(), right.as_ptr(), len) as isize };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
|
||||
LL | let mut order = unsafe { compare_bytes(left, right, len) as isize };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -117,7 +117,7 @@ pub(crate) fn fields_attrs_query(
|
||||
}
|
||||
|
||||
impl Attrs {
|
||||
pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'_> {
|
||||
pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'attrs> {
|
||||
AttrQuery { attrs: self, key }
|
||||
}
|
||||
|
||||
@ -594,7 +594,7 @@ pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
|
||||
/// #[doc(html_root_url = "url")]
|
||||
/// ^^^^^^^^^^^^^ key
|
||||
/// ```
|
||||
pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&str> {
|
||||
pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&'attr str> {
|
||||
self.tt_values().find_map(|tt| {
|
||||
let name = tt.token_trees.iter()
|
||||
.skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key))
|
||||
|
@ -197,7 +197,7 @@ pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body>
|
||||
pub fn blocks<'a>(
|
||||
&'a self,
|
||||
db: &'a dyn DefDatabase,
|
||||
) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ {
|
||||
) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + 'a {
|
||||
self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block)))
|
||||
}
|
||||
|
||||
|
8
tests/crashes/117460.rs
Normal file
8
tests/crashes/117460.rs
Normal file
@ -0,0 +1,8 @@
|
||||
//@ known-bug: #117460
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
struct Matrix<D = [(); 2 + 2]> {
|
||||
d: D,
|
||||
}
|
||||
|
||||
impl Matrix {}
|
48
tests/crashes/119095.rs
Normal file
48
tests/crashes/119095.rs
Normal file
@ -0,0 +1,48 @@
|
||||
//@ known-bug: #119095
|
||||
//@ compile-flags: --edition=2021
|
||||
|
||||
fn any<T>() -> T {
|
||||
loop {}
|
||||
}
|
||||
|
||||
trait Acquire {
|
||||
type Connection;
|
||||
}
|
||||
|
||||
impl Acquire for &'static () {
|
||||
type Connection = ();
|
||||
}
|
||||
|
||||
trait Unit {}
|
||||
impl Unit for () {}
|
||||
|
||||
fn get_connection<T>() -> impl Unit
|
||||
where
|
||||
T: Acquire,
|
||||
T::Connection: Unit,
|
||||
{
|
||||
any::<T::Connection>()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let future = async { async { get_connection::<&'static ()>() }.await };
|
||||
|
||||
future.resolve_me();
|
||||
}
|
||||
|
||||
trait ResolveMe {
|
||||
fn resolve_me(self);
|
||||
}
|
||||
|
||||
impl<S> ResolveMe for S
|
||||
where
|
||||
(): CheckSend<S>,
|
||||
{
|
||||
fn resolve_me(self) {}
|
||||
}
|
||||
|
||||
trait CheckSend<F> {}
|
||||
impl<F> CheckSend<F> for () where F: Send {}
|
||||
|
||||
trait NeverImplemented {}
|
||||
impl<E, F> CheckSend<F> for E where E: NeverImplemented {}
|
15
tests/crashes/126443.rs
Normal file
15
tests/crashes/126443.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//@ known-bug: #126443
|
||||
//@ compile-flags: -Copt-level=0
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
fn double_up<const M: usize>() -> [(); M * 2] {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn quadruple_up<const N: usize>() -> [(); N * 2 * 2] {
|
||||
double_up()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
quadruple_up::<0>();
|
||||
}
|
6
tests/crashes/128097.rs
Normal file
6
tests/crashes/128097.rs
Normal file
@ -0,0 +1,6 @@
|
||||
//@ known-bug: #128097
|
||||
#![feature(explicit_tail_calls)]
|
||||
fn f(x: &mut ()) {
|
||||
let _y: String;
|
||||
become f(x);
|
||||
}
|
@ -8,22 +8,22 @@
|
||||
// gdb-command:run
|
||||
|
||||
// gdb-command:print some
|
||||
// gdb-check:$1 = core::option::Option<&u32>::Some(0x12345678)
|
||||
// gdb-check:$1 = core::option::Option<&u32>::Some(0x[...])
|
||||
|
||||
// gdb-command:print none
|
||||
// gdb-check:$2 = core::option::Option<&u32>::None
|
||||
|
||||
// gdb-command:print full
|
||||
// gdb-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988)
|
||||
// gdb-check:$3 = option_like_enum::MoreFields::Full(454545, 0x[...], 9988)
|
||||
|
||||
// gdb-command:print empty_gdb.discr
|
||||
// gdb-check:$4 = (*mut isize) 0x1
|
||||
// gdb-command:print empty
|
||||
// gdb-check:$4 = option_like_enum::MoreFields::Empty
|
||||
|
||||
// gdb-command:print droid
|
||||
// gdb-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765}
|
||||
// gdb-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x[...]}
|
||||
|
||||
// gdb-command:print void_droid_gdb.internals
|
||||
// gdb-check:$6 = (*mut isize) 0x1
|
||||
// gdb-command:print void_droid
|
||||
// gdb-check:$6 = option_like_enum::NamedFields::Void
|
||||
|
||||
// gdb-command:print nested_non_zero_yep
|
||||
// gdb-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...]})
|
||||
@ -39,19 +39,19 @@
|
||||
// lldb-command:run
|
||||
|
||||
// lldb-command:v some
|
||||
// lldb-check:[...] Some(&0x12345678)
|
||||
// lldb-check:[...] Some(&0x[...])
|
||||
|
||||
// lldb-command:v none
|
||||
// lldb-check:[...] None
|
||||
|
||||
// lldb-command:v full
|
||||
// lldb-check:[...] Full(454545, &0x87654321, 9988)
|
||||
// lldb-check:[...] Full(454545, &0x[...], 9988)
|
||||
|
||||
// lldb-command:v empty
|
||||
// lldb-check:[...] Empty
|
||||
|
||||
// lldb-command:v droid
|
||||
// lldb-check:[...] Droid { id: 675675, range: 10000001, internals: &0x43218765 }
|
||||
// lldb-check:[...] Droid { id: 675675, range: 10000001, internals: &0x[...] }
|
||||
|
||||
// lldb-command:v void_droid
|
||||
// lldb-check:[...] Void
|
||||
@ -76,11 +76,6 @@
|
||||
// contains a non-nullable pointer, then this value is used as the discriminator.
|
||||
// The test cases in this file make sure that something readable is generated for
|
||||
// this kind of types.
|
||||
// If the non-empty variant contains a single non-nullable pointer than the whole
|
||||
// item is represented as just a pointer and not wrapped in a struct.
|
||||
// Unfortunately (for these test cases) the content of the non-discriminant fields
|
||||
// in the null-case is not defined. So we just read the discriminator field in
|
||||
// this case (by casting the value to a memory-equivalent struct).
|
||||
|
||||
enum MoreFields<'a> {
|
||||
Full(u32, &'a isize, i16),
|
||||
@ -120,32 +115,26 @@ fn main() {
|
||||
let some_str: Option<&'static str> = Some("abc");
|
||||
let none_str: Option<&'static str> = None;
|
||||
|
||||
let some: Option<&u32> = Some(unsafe { std::mem::transmute(0x12345678_usize) });
|
||||
let some: Option<&u32> = Some(&1234);
|
||||
let none: Option<&u32> = None;
|
||||
|
||||
let full = MoreFields::Full(454545, unsafe { std::mem::transmute(0x87654321_usize) }, 9988);
|
||||
|
||||
let full = MoreFields::Full(454545, &1234, 9988);
|
||||
let empty = MoreFields::Empty;
|
||||
let empty_gdb: &MoreFieldsRepr = unsafe { std::mem::transmute(&MoreFields::Empty) };
|
||||
|
||||
let droid = NamedFields::Droid {
|
||||
id: 675675,
|
||||
range: 10000001,
|
||||
internals: unsafe { std::mem::transmute(0x43218765_usize) }
|
||||
internals: &1234,
|
||||
};
|
||||
|
||||
let void_droid = NamedFields::Void;
|
||||
let void_droid_gdb: &NamedFieldsRepr = unsafe { std::mem::transmute(&NamedFields::Void) };
|
||||
|
||||
let x = 'x';
|
||||
let nested_non_zero_yep = NestedNonZero::Yep(
|
||||
10.5,
|
||||
NestedNonZeroField {
|
||||
a: 10,
|
||||
b: 20,
|
||||
c: &x
|
||||
c: &'x',
|
||||
});
|
||||
|
||||
let nested_non_zero_nope = NestedNonZero::Nope;
|
||||
|
||||
zzz(); // #break
|
||||
|
@ -3,14 +3,14 @@
|
||||
field_tys: {
|
||||
_0: CoroutineSavedTy {
|
||||
ty: Coroutine(
|
||||
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
|
||||
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
|
||||
[
|
||||
(),
|
||||
std::future::ResumeTy,
|
||||
(),
|
||||
(),
|
||||
CoroutineWitness(
|
||||
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
|
||||
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
|
||||
[],
|
||||
),
|
||||
(),
|
||||
@ -24,14 +24,14 @@
|
||||
},
|
||||
_1: CoroutineSavedTy {
|
||||
ty: Coroutine(
|
||||
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
|
||||
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
|
||||
[
|
||||
(),
|
||||
std::future::ResumeTy,
|
||||
(),
|
||||
(),
|
||||
CoroutineWitness(
|
||||
DefId(0:4 ~ async_await[ccf8]::a::{closure#0}),
|
||||
DefId(0:5 ~ async_await[ccf8]::a::{closure#0}),
|
||||
[],
|
||||
),
|
||||
(),
|
||||
|
@ -9,7 +9,7 @@ trait Foo {}
|
||||
impl Xyz {
|
||||
async fn do_sth<'a>(
|
||||
&'a self, foo: &dyn Foo
|
||||
) -> &dyn Foo
|
||||
) -> &dyn Foo //~ WARNING elided lifetime has a name
|
||||
{
|
||||
//~^ ERROR explicit lifetime required in the type of `foo` [E0621]
|
||||
foo
|
||||
|
@ -1,3 +1,14 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/issue-63388-1.rs:12:10
|
||||
|
|
||||
LL | async fn do_sth<'a>(
|
||||
| -- lifetime `'a` declared here
|
||||
LL | &'a self, foo: &dyn Foo
|
||||
LL | ) -> &dyn Foo
|
||||
| ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `foo`
|
||||
--> $DIR/issue-63388-1.rs:13:5
|
||||
|
|
||||
@ -10,6 +21,6 @@ LL | | foo
|
||||
LL | | }
|
||||
| |_____^ lifetime `'a` required
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0621`.
|
||||
|
@ -0,0 +1,10 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/issue-71348.rs:18:68
|
||||
|
|
||||
LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -1,3 +1,11 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/issue-71348.rs:18:68
|
||||
|
|
||||
LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error: `&'static str` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/issue-71348.rs:10:24
|
||||
|
|
||||
@ -30,5 +38,5 @@ help: add `#![feature(unsized_const_params)]` to the crate attributes to enable
|
||||
LL + #![feature(unsized_const_params)]
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
|
@ -17,6 +17,7 @@ trait Get<'a, const N: &'static str> {
|
||||
impl Foo {
|
||||
fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target
|
||||
//[min]~^ ERROR `&'static str` is forbidden as the type of a const generic parameter
|
||||
//~^^ WARNING elided lifetime has a name
|
||||
where
|
||||
Self: Get<'a, N>,
|
||||
{
|
||||
|
@ -44,8 +44,8 @@ const fn get_mut(&mut self) -> &mut T { &mut self.0 }
|
||||
impl<'a, T> Foo<T> {
|
||||
const fn new_lt(t: T) -> Self { Foo(t) }
|
||||
const fn into_inner_lt(self) -> T { self.0 } //~ destructor of
|
||||
const fn get_lt(&'a self) -> &T { &self.0 }
|
||||
const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
|
||||
const fn get_lt(&'a self) -> &T { &self.0 } //~ WARNING elided lifetime has a name
|
||||
const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 } //~ WARNING elided lifetime has a name
|
||||
//~^ mutable references
|
||||
//~| mutable references
|
||||
//~| mutable references
|
||||
|
@ -1,3 +1,23 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/min_const_fn.rs:47:34
|
||||
|
|
||||
LL | impl<'a, T> Foo<T> {
|
||||
| -- lifetime `'a` declared here
|
||||
...
|
||||
LL | const fn get_lt(&'a self) -> &T { &self.0 }
|
||||
| ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/min_const_fn.rs:48:42
|
||||
|
|
||||
LL | impl<'a, T> Foo<T> {
|
||||
| -- lifetime `'a` declared here
|
||||
...
|
||||
LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
|
||||
| ^ this elided lifetime gets resolved as `'a`
|
||||
|
||||
error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time
|
||||
--> $DIR/min_const_fn.rs:37:25
|
||||
|
|
||||
@ -228,7 +248,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {}
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
error: aborting due to 24 previous errors; 2 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0493, E0658.
|
||||
For more information about an error, try `rustc --explain E0493`.
|
||||
|
@ -10,7 +10,7 @@ note: coroutine is not `Send` as this value is used across a yield
|
||||
--> $DIR/coroutine-print-verbose-1.rs:35:9
|
||||
|
|
||||
LL | let _non_send_gen = make_non_send_coroutine();
|
||||
| ------------- has type `Opaque(DefId(0:34 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send`
|
||||
| ------------- has type `Opaque(DefId(0:24 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine::{opaque#0}), [])` which is not `Send`
|
||||
LL | yield;
|
||||
| ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
|
||||
note: required by a bound in `require_send`
|
||||
@ -33,12 +33,12 @@ note: required because it's used within this coroutine
|
||||
|
|
||||
LL | #[coroutine] || {
|
||||
| ^^
|
||||
note: required because it appears within the type `Opaque(DefId(0:35 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
|
||||
note: required because it appears within the type `Opaque(DefId(0:29 ~ coroutine_print_verbose_1[75fb]::make_gen2::{opaque#0}), [Arc<RefCell<i32>>])`
|
||||
--> $DIR/coroutine-print-verbose-1.rs:41:30
|
||||
|
|
||||
LL | pub fn make_gen2<T>(t: T) -> impl Coroutine<Return = T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: required because it appears within the type `Opaque(DefId(0:36 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])`
|
||||
note: required because it appears within the type `Opaque(DefId(0:32 ~ coroutine_print_verbose_1[75fb]::make_non_send_coroutine2::{opaque#0}), [])`
|
||||
--> $DIR/coroutine-print-verbose-1.rs:47:34
|
||||
|
|
||||
LL | fn make_non_send_coroutine2() -> impl Coroutine<Return = Arc<RefCell<i32>>> {
|
||||
|
@ -1,5 +1,5 @@
|
||||
//@ run-rustfix
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, elided_named_lifetimes)]
|
||||
#![deny(no_mangle_generic_items)]
|
||||
|
||||
pub fn foo<T>() {} //~ ERROR functions generic over types or consts must be mangled
|
||||
|
@ -1,5 +1,5 @@
|
||||
//@ run-rustfix
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, elided_named_lifetimes)]
|
||||
#![deny(no_mangle_generic_items)]
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -13,6 +13,7 @@ fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
|
||||
|
||||
fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
|
||||
//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
|
||||
//~| WARNING elided lifetime has a name
|
||||
|x| x
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/impl-fn-hrtb-bounds.rs:19:38
|
||||
--> $DIR/impl-fn-hrtb-bounds.rs:20:38
|
||||
|
|
||||
LL | fn d() -> impl Fn() -> (impl Debug + '_) {
|
||||
| ^^ expected named lifetime parameter
|
||||
@ -10,6 +10,14 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're
|
||||
LL | fn d() -> impl Fn() -> (impl Debug + 'static) {
|
||||
| ~~~~~~~
|
||||
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/impl-fn-hrtb-bounds.rs:14:52
|
||||
|
|
||||
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
|
||||
| -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
|
||||
--> $DIR/impl-fn-hrtb-bounds.rs:4:41
|
||||
|
|
||||
@ -46,7 +54,7 @@ note: lifetime declared here
|
||||
LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
|
||||
| ^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 4 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0106, E0657.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
||||
//~^ ERROR cannot resolve opaque type
|
||||
//~| WARNING elided lifetime has a name
|
||||
|x| x
|
||||
//~^ ERROR expected generic lifetime parameter, found `'_`
|
||||
}
|
||||
|
@ -1,9 +1,17 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/impl-fn-predefined-lifetimes.rs:4:48
|
||||
|
|
||||
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
||||
| -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||
--> $DIR/impl-fn-predefined-lifetimes.rs:6:9
|
||||
--> $DIR/impl-fn-predefined-lifetimes.rs:7:9
|
||||
|
|
||||
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
||||
| -- this generic parameter must be used with a generic lifetime parameter
|
||||
LL |
|
||||
...
|
||||
LL | |x| x
|
||||
| ^
|
||||
|
||||
@ -13,7 +21,7 @@ error[E0720]: cannot resolve opaque type
|
||||
LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
|
||||
| ^^^^^^^^^^^^^^^ cannot resolve opaque type
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0720, E0792.
|
||||
For more information about an error, try `rustc --explain E0720`.
|
||||
|
@ -1,6 +1,7 @@
|
||||
//@ check-pass
|
||||
|
||||
pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &u32)> {
|
||||
//~^ WARNING elided lifetime has a name
|
||||
v.into_iter()
|
||||
}
|
||||
|
||||
|
10
tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
Normal file
10
tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/rpit-assoc-pair-with-lifetime.rs:3:82
|
||||
|
|
||||
LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &u32)> {
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -47,5 +47,6 @@ fn l<'a>(_: &'a str, _: &'a str) -> &str { "" }
|
||||
|
||||
// This is ok because both `'a` are for the same parameter.
|
||||
fn m<'a>(_: &'a Foo<'a>) -> &str { "" }
|
||||
//~^ WARNING elided lifetime has a name
|
||||
|
||||
fn main() {}
|
||||
|
@ -105,6 +105,16 @@ help: consider using the `'a` lifetime
|
||||
LL | fn l<'a>(_: &'a str, _: &'a str) -> &'a str { "" }
|
||||
| ++
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:49:29
|
||||
|
|
||||
LL | fn m<'a>(_: &'a Foo<'a>) -> &str { "" }
|
||||
| -- ^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error: aborting due to 7 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
||||
|
@ -4,6 +4,7 @@ struct Foo {
|
||||
|
||||
impl Foo {
|
||||
fn foo<'a>(&'a self, x: &i32) -> &i32 {
|
||||
//~^ WARNING elided lifetime has a name
|
||||
|
||||
if true { &self.field } else { x } //~ ERROR explicit lifetime
|
||||
|
||||
|
@ -1,12 +1,22 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:6:36
|
||||
|
|
||||
LL | fn foo<'a>(&'a self, x: &i32) -> &i32 {
|
||||
| -- ^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error[E0621]: explicit lifetime required in the type of `x`
|
||||
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:8:36
|
||||
--> $DIR/ex1-return-one-existing-name-if-else-using-impl-3.rs:9:36
|
||||
|
|
||||
LL | fn foo<'a>(&'a self, x: &i32) -> &i32 {
|
||||
| ---- help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
|
||||
LL |
|
||||
...
|
||||
LL | if true { &self.field } else { x }
|
||||
| ^ lifetime `'a` required
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0621`.
|
||||
|
@ -0,0 +1,12 @@
|
||||
#![deny(elided_named_lifetimes)]
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
unsafe { &mut *(x as *mut _) }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,14 @@
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/example-from-issue48686.rs:6:50
|
||||
|
|
||||
LL | pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
|
||||
| ^ this elided lifetime gets resolved as `'static`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/example-from-issue48686.rs:1:9
|
||||
|
|
||||
LL | #![deny(elided_named_lifetimes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -0,0 +1,27 @@
|
||||
#![deny(elided_named_lifetimes)]
|
||||
|
||||
fn ampersand<'a>(x: &'a u8) -> &u8 {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
x
|
||||
}
|
||||
|
||||
struct Brackets<'a>(&'a u8);
|
||||
|
||||
fn brackets<'a>(x: &'a u8) -> Brackets {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
Brackets(x)
|
||||
}
|
||||
|
||||
struct Comma<'a, T>(&'a T);
|
||||
|
||||
fn comma<'a>(x: &'a u8) -> Comma<u8> {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
Comma(x)
|
||||
}
|
||||
|
||||
fn underscore<'a>(x: &'a u8) -> &'_ u8 {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,40 @@
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/missing-lifetime-kind.rs:3:32
|
||||
|
|
||||
LL | fn ampersand<'a>(x: &'a u8) -> &u8 {
|
||||
| -- ^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/missing-lifetime-kind.rs:1:9
|
||||
|
|
||||
LL | #![deny(elided_named_lifetimes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/missing-lifetime-kind.rs:10:31
|
||||
|
|
||||
LL | fn brackets<'a>(x: &'a u8) -> Brackets {
|
||||
| -- ^^^^^^^^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/missing-lifetime-kind.rs:17:33
|
||||
|
|
||||
LL | fn comma<'a>(x: &'a u8) -> Comma<u8> {
|
||||
| -- ^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/missing-lifetime-kind.rs:22:34
|
||||
|
|
||||
LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 {
|
||||
| -- ^^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
17
tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs
Normal file
17
tests/ui/lint/elided-named-lifetimes/not-tied-to-crate.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#![allow(elided_named_lifetimes)]
|
||||
|
||||
#[warn(elided_named_lifetimes)]
|
||||
mod foo {
|
||||
fn bar(x: &'static u8) -> &u8 {
|
||||
//~^ WARNING elided lifetime has a name
|
||||
x
|
||||
}
|
||||
|
||||
#[deny(elided_named_lifetimes)]
|
||||
fn baz(x: &'static u8) -> &u8 {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,26 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/not-tied-to-crate.rs:5:31
|
||||
|
|
||||
LL | fn bar(x: &'static u8) -> &u8 {
|
||||
| ^ this elided lifetime gets resolved as `'static`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/not-tied-to-crate.rs:3:8
|
||||
|
|
||||
LL | #[warn(elided_named_lifetimes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/not-tied-to-crate.rs:11:31
|
||||
|
|
||||
LL | fn baz(x: &'static u8) -> &u8 {
|
||||
| ^ this elided lifetime gets resolved as `'static`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/not-tied-to-crate.rs:10:12
|
||||
|
|
||||
LL | #[deny(elided_named_lifetimes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
46
tests/ui/lint/elided-named-lifetimes/static.rs
Normal file
46
tests/ui/lint/elided-named-lifetimes/static.rs
Normal file
@ -0,0 +1,46 @@
|
||||
#![deny(elided_named_lifetimes)]
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
const A: &[u8] = &[];
|
||||
static B: &str = "hello";
|
||||
|
||||
trait Trait {
|
||||
const C: &u8 = &0;
|
||||
}
|
||||
|
||||
impl Trait for () {
|
||||
const C: &u8 = &1;
|
||||
}
|
||||
|
||||
fn ampersand(x: &'static u8) -> &u8 {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
x
|
||||
}
|
||||
|
||||
struct Brackets<'a>(&'a u8);
|
||||
|
||||
fn brackets(x: &'static u8) -> Brackets {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
Brackets(x)
|
||||
}
|
||||
|
||||
struct Comma<'a, T>(&'a T);
|
||||
|
||||
fn comma(x: &'static u8) -> Comma<u8> {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
Comma(x)
|
||||
}
|
||||
|
||||
fn underscore(x: &'static u8) -> &'_ u8 {
|
||||
//~^ ERROR elided lifetime has a name
|
||||
x
|
||||
}
|
||||
|
||||
const NESTED: &Vec<&Box<Cow<str>>> = &vec![];
|
||||
|
||||
fn main() {
|
||||
const HELLO: &str = "Hello";
|
||||
static WORLD: &str = "world";
|
||||
println!("{HELLO}, {WORLD}!")
|
||||
}
|
32
tests/ui/lint/elided-named-lifetimes/static.stderr
Normal file
32
tests/ui/lint/elided-named-lifetimes/static.stderr
Normal file
@ -0,0 +1,32 @@
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/static.rs:16:33
|
||||
|
|
||||
LL | fn ampersand(x: &'static u8) -> &u8 {
|
||||
| ^ this elided lifetime gets resolved as `'static`
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/static.rs:1:9
|
||||
|
|
||||
LL | #![deny(elided_named_lifetimes)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/static.rs:23:32
|
||||
|
|
||||
LL | fn brackets(x: &'static u8) -> Brackets {
|
||||
| ^^^^^^^^ this elided lifetime gets resolved as `'static`
|
||||
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/static.rs:30:34
|
||||
|
|
||||
LL | fn comma(x: &'static u8) -> Comma<u8> {
|
||||
| ^ this elided lifetime gets resolved as `'static`
|
||||
|
||||
error: elided lifetime has a name
|
||||
--> $DIR/static.rs:35:35
|
||||
|
|
||||
LL | fn underscore(x: &'static u8) -> &'_ u8 {
|
||||
| ^^ this elided lifetime gets resolved as `'static`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -1,16 +1,16 @@
|
||||
error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds
|
||||
error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), ['a/#0, T, 'a/#0])` captures lifetime that does not appear in bounds
|
||||
--> $DIR/impl-trait-captures.rs:11:5
|
||||
|
|
||||
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
|
||||
| -- ------------ opaque type defined here
|
||||
| |
|
||||
| hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here
|
||||
| hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`
|
||||
help: add a `use<...>` bound to explicitly capture `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_))`
|
||||
|
|
||||
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> {
|
||||
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + use<'a, ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::'_), '_)), T> {
|
||||
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -46,6 +46,8 @@ fn load1(ss: &dyn SomeTrait) -> &dyn SomeTrait {
|
||||
}
|
||||
|
||||
fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait {
|
||||
//~^ WARNING elided lifetime has a name
|
||||
|
||||
// Same as `load1` but with an explicit name thrown in for fun.
|
||||
|
||||
ss
|
||||
|
@ -1,5 +1,15 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/object-lifetime-default-elision.rs:48:40
|
||||
|
|
||||
LL | fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait {
|
||||
| -- ^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/object-lifetime-default-elision.rs:71:5
|
||||
--> $DIR/object-lifetime-default-elision.rs:73:5
|
||||
|
|
||||
LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
|
||||
| -- -- lifetime `'b` defined here
|
||||
@ -11,5 +21,5 @@ LL | ss
|
||||
|
|
||||
= help: consider adding the following bound: `'a: 'b`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
impl<'b> Foo<'b> {
|
||||
fn a<'a>(self: Self, a: &'a str) -> &str {
|
||||
//~^ WARNING elided lifetime has a name
|
||||
a
|
||||
}
|
||||
fn b<'a>(self: Foo<'b>, a: &'a str) -> &str {
|
||||
//~^ WARNING elided lifetime has a name
|
||||
a
|
||||
}
|
||||
}
|
||||
|
16
tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
Normal file
16
tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/ignore-non-reference-lifetimes.rs:6:41
|
||||
|
|
||||
LL | fn a<'a>(self: Self, a: &'a str) -> &str {
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/ignore-non-reference-lifetimes.rs:10:44
|
||||
|
|
||||
LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str {
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -1,6 +1,6 @@
|
||||
//@ edition:2018
|
||||
//@ run-rustfix
|
||||
#![allow(non_snake_case, dead_code)]
|
||||
#![allow(non_snake_case, dead_code, elided_named_lifetimes)]
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//@ edition:2018
|
||||
//@ run-rustfix
|
||||
#![allow(non_snake_case, dead_code)]
|
||||
#![allow(non_snake_case, dead_code, elided_named_lifetimes)]
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
|
@ -4,11 +4,13 @@
|
||||
struct Foo<'a>(&'a ());
|
||||
impl<'a> Foo<'a> {
|
||||
async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
|
||||
//~^ WARNING elided lifetime has a name
|
||||
}
|
||||
|
||||
type Alias = Foo<'static>;
|
||||
impl Alias {
|
||||
async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
|
||||
//~^ WARNING elided lifetime has a name
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
18
tests/ui/self/self_lifetime-async.stderr
Normal file
18
tests/ui/self/self_lifetime-async.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/self_lifetime-async.rs:6:44
|
||||
|
|
||||
LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
|
||||
| -- ^ this elided lifetime gets resolved as `'b`
|
||||
| |
|
||||
| lifetime `'b` declared here
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/self_lifetime-async.rs:12:52
|
||||
|
|
||||
LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -5,11 +5,13 @@
|
||||
struct Foo<'a>(&'a ());
|
||||
impl<'a> Foo<'a> {
|
||||
fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
|
||||
//~^ WARNING elided lifetime has a name
|
||||
}
|
||||
|
||||
type Alias = Foo<'static>;
|
||||
impl Alias {
|
||||
fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
|
||||
//~^ WARNING elided lifetime has a name
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
18
tests/ui/self/self_lifetime.stderr
Normal file
18
tests/ui/self/self_lifetime.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/self_lifetime.rs:7:38
|
||||
|
|
||||
LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
|
||||
| -- ^ this elided lifetime gets resolved as `'b`
|
||||
| |
|
||||
| lifetime `'b` declared here
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/self_lifetime.rs:13:46
|
||||
|
|
||||
LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -64,6 +64,7 @@ fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
|
||||
|
||||
// This must not err, as the `&` actually resolves to `'a`.
|
||||
fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) {
|
||||
//~^ WARNING elided lifetime has a name
|
||||
f("f");
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,14 @@ LL - fn g(mut x: impl Foo<()>) -> Option<&()> { x.next() }
|
||||
LL + fn g(mut x: impl Foo<()>) -> Option<()> { x.next() }
|
||||
|
|
||||
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/impl-trait-missing-lifetime-gated.rs:66:57
|
||||
|
|
||||
LL | fn resolved_anonymous<'a, T: 'a>(f: impl Fn(&'a str) -> &T) {
|
||||
| -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
|
||||
--> $DIR/impl-trait-missing-lifetime-gated.rs:6:35
|
||||
|
|
||||
@ -244,7 +252,7 @@ help: consider introducing a named lifetime parameter
|
||||
LL | fn g<'a>(mut x: impl Foo<'a, ()>) -> Option<&()> { x.next() }
|
||||
| ++++ +++
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: aborting due to 16 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0106, E0658.
|
||||
For more information about an error, try `rustc --explain E0106`.
|
||||
|
@ -100,6 +100,7 @@ fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
|
||||
|
||||
// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions:
|
||||
fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
|
||||
//~^ WARNING elided lifetime has a name
|
||||
where
|
||||
G: Get<T>,
|
||||
{
|
||||
|
@ -6,6 +6,14 @@ LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
|
||||
| |
|
||||
| help: consider introducing lifetime `'a` here: `'a,`
|
||||
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:102:64
|
||||
|
|
||||
LL | fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
|
||||
| -- lifetime `'a` declared here ^^ this elided lifetime gets resolved as `'a`
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds
|
||||
--> $DIR/missing-lifetimes-in-signature.rs:19:5
|
||||
|
|
||||
@ -125,7 +133,7 @@ help: consider adding an explicit lifetime bound
|
||||
LL | G: Get<T> + 'a,
|
||||
| ++++
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 8 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700.
|
||||
For more information about an error, try `rustc --explain E0261`.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
type Opaque2<T> = impl Sized;
|
||||
type Opaque<'a, T> = Opaque2<T>;
|
||||
fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
|
||||
fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } //~ WARNING elided lifetime has a name
|
||||
//~^ ERROR: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,3 +1,13 @@
|
||||
warning: elided lifetime has a name
|
||||
--> $DIR/missing_lifetime_bound.rs:5:41
|
||||
|
|
||||
LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
|
||||
| -- ^ this elided lifetime gets resolved as `'a`
|
||||
| |
|
||||
| lifetime `'a` declared here
|
||||
|
|
||||
= note: `#[warn(elided_named_lifetimes)]` on by default
|
||||
|
||||
error[E0700]: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds
|
||||
--> $DIR/missing_lifetime_bound.rs:5:47
|
||||
|
|
||||
@ -9,6 +19,6 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
|
||||
| |
|
||||
| hidden type `&'a i32` captures the lifetime `'a` as defined here
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0700`.
|
||||
|
Loading…
Reference in New Issue
Block a user