mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-08 04:56:58 +00:00
Auto merge of #103562 - Dylan-DPC:rollup-sheepp5, r=Dylan-DPC
Rollup of 10 pull requests Successful merges: - #102951 (suggest type annotation for local statement initialed by ref expression) - #103209 (Diagnostic derives: allow specifying multiple alternative suggestions) - #103287 (Use a faster allocation size check in slice::from_raw_parts) - #103416 (Name the `impl Trait` in region bound suggestions) - #103430 (Workaround unstable stmt_expr_attributes for method receiver expressions) - #103444 (Remove extra type error after missing semicolon error) - #103520 (rustc_middle: Rearrange resolver outputs structures slightly) - #103533 (Use &self instead of &mut self for cast methods) - #103536 (Remove `rustc_driver::set_sigpipe_handler()`) - #103542 (Pinning tests for some `macro_rules!` errors discussed in the lang meeting) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
629a414d7b
@ -152,6 +152,12 @@ pub trait MutVisitor: Sized {
|
||||
noop_visit_expr(e, self);
|
||||
}
|
||||
|
||||
/// This method is a hack to workaround unstable of `stmt_expr_attributes`.
|
||||
/// It can be removed once that feature is stabilized.
|
||||
fn visit_method_receiver_expr(&mut self, ex: &mut P<Expr>) {
|
||||
self.visit_expr(ex)
|
||||
}
|
||||
|
||||
fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
|
||||
noop_filter_map_expr(e, self)
|
||||
}
|
||||
@ -1301,7 +1307,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_id(id);
|
||||
visit_opt(args, |args| vis.visit_generic_args(args));
|
||||
vis.visit_expr(receiver);
|
||||
vis.visit_method_receiver_expr(receiver);
|
||||
visit_exprs(exprs, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
@ -1589,3 +1595,9 @@ impl DummyAstNode for Crate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> {
|
||||
fn dummy() -> Self {
|
||||
crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized {
|
||||
fn visit_expr(&mut self, ex: &'ast Expr) {
|
||||
walk_expr(self, ex)
|
||||
}
|
||||
/// This method is a hack to workaround unstable of `stmt_expr_attributes`.
|
||||
/// It can be removed once that feature is stabilized.
|
||||
fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) {
|
||||
self.visit_expr(ex)
|
||||
}
|
||||
fn visit_expr_post(&mut self, _ex: &'ast Expr) {}
|
||||
fn visit_ty(&mut self, t: &'ast Ty) {
|
||||
walk_ty(self, t)
|
||||
|
@ -210,8 +210,15 @@ impl CfgEval<'_, '_> {
|
||||
}
|
||||
|
||||
impl MutVisitor for CfgEval<'_, '_> {
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
self.cfg.configure_expr(expr);
|
||||
self.cfg.configure_expr(expr, false);
|
||||
mut_visit::noop_visit_expr(expr, self);
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
self.cfg.configure_expr(expr, true);
|
||||
mut_visit::noop_visit_expr(expr, self);
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
pub fn int_to_int_or_float(
|
||||
&mut self,
|
||||
&self,
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
|
||||
@ -154,7 +154,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
pub fn float_to_float_or_int(
|
||||
&mut self,
|
||||
&self,
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
|
||||
@ -176,7 +176,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
/// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
|
||||
pub fn ptr_to_ptr(
|
||||
&mut self,
|
||||
&self,
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
|
||||
@ -226,7 +226,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
pub fn pointer_from_exposed_address_cast(
|
||||
&mut self,
|
||||
&self,
|
||||
src: &ImmTy<'tcx, M::Provenance>,
|
||||
cast_ty: Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
|
||||
|
@ -427,18 +427,6 @@ fn run_compiler(
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn set_sigpipe_handler() {
|
||||
unsafe {
|
||||
// Set the SIGPIPE signal handler, so that an EPIPE
|
||||
// will cause rustc to terminate, as expected.
|
||||
assert_ne!(libc::signal(libc::SIGPIPE, libc::SIG_DFL), libc::SIG_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn set_sigpipe_handler() {}
|
||||
|
||||
// Extract output directory and file from matches.
|
||||
fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
|
||||
let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
|
||||
|
@ -690,6 +690,24 @@ impl Diagnostic {
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestions: impl Iterator<Item = String>,
|
||||
applicability: Applicability,
|
||||
) -> &mut Self {
|
||||
self.span_suggestions_with_style(
|
||||
sp,
|
||||
msg,
|
||||
suggestions,
|
||||
applicability,
|
||||
SuggestionStyle::ShowCode,
|
||||
)
|
||||
}
|
||||
|
||||
/// [`Diagnostic::span_suggestions()`] but you can set the [`SuggestionStyle`].
|
||||
pub fn span_suggestions_with_style(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
suggestions: impl Iterator<Item = String>,
|
||||
applicability: Applicability,
|
||||
style: SuggestionStyle,
|
||||
) -> &mut Self {
|
||||
let mut suggestions: Vec<_> = suggestions.collect();
|
||||
suggestions.sort();
|
||||
@ -706,14 +724,15 @@ impl Diagnostic {
|
||||
self.push_suggestion(CodeSuggestion {
|
||||
substitutions,
|
||||
msg: self.subdiagnostic_message_to_diagnostic_message(msg),
|
||||
style: SuggestionStyle::ShowCode,
|
||||
style,
|
||||
applicability,
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Prints out a message with multiple suggested edits of the code.
|
||||
/// See also [`Diagnostic::span_suggestion()`].
|
||||
/// Prints out a message with multiple suggested edits of the code, where each edit consists of
|
||||
/// multiple parts.
|
||||
/// See also [`Diagnostic::multipart_suggestion()`].
|
||||
pub fn multipart_suggestions(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagnosticMessage>,
|
||||
@ -745,6 +764,7 @@ impl Diagnostic {
|
||||
});
|
||||
self
|
||||
}
|
||||
|
||||
/// Prints out a message with a suggested edit of the code. If the suggestion is presented
|
||||
/// inline, it will only show the message and not the suggestion.
|
||||
///
|
||||
|
@ -469,6 +469,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||
}
|
||||
|
||||
/// If attributes are not allowed on expressions, emit an error for `attr`
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
|
||||
if !self.features.map_or(true, |features| features.stmt_expr_attributes) {
|
||||
let mut err = feature_err(
|
||||
@ -486,9 +487,12 @@ impl<'a> StripUnconfigured<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configure_expr(&self, expr: &mut P<ast::Expr>) {
|
||||
for attr in expr.attrs.iter() {
|
||||
self.maybe_emit_expr_attr_err(attr);
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
pub fn configure_expr(&self, expr: &mut P<ast::Expr>, method_receiver: bool) {
|
||||
if !method_receiver {
|
||||
for attr in expr.attrs.iter() {
|
||||
self.maybe_emit_expr_attr_err(attr);
|
||||
}
|
||||
}
|
||||
|
||||
// If an expr is valid to cfg away it will have been removed by the
|
||||
|
@ -50,6 +50,7 @@ macro_rules! ast_fragments {
|
||||
/// Can also serve as an input and intermediate result for macro expansion operations.
|
||||
pub enum AstFragment {
|
||||
OptExpr(Option<P<ast::Expr>>),
|
||||
MethodReceiverExpr(P<ast::Expr>),
|
||||
$($Kind($AstTy),)*
|
||||
}
|
||||
|
||||
@ -57,6 +58,7 @@ macro_rules! ast_fragments {
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum AstFragmentKind {
|
||||
OptExpr,
|
||||
MethodReceiverExpr,
|
||||
$($Kind,)*
|
||||
}
|
||||
|
||||
@ -64,6 +66,7 @@ macro_rules! ast_fragments {
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
AstFragmentKind::OptExpr => "expression",
|
||||
AstFragmentKind::MethodReceiverExpr => "expression",
|
||||
$(AstFragmentKind::$Kind => $kind_name,)*
|
||||
}
|
||||
}
|
||||
@ -72,6 +75,8 @@ macro_rules! ast_fragments {
|
||||
match self {
|
||||
AstFragmentKind::OptExpr =>
|
||||
result.make_expr().map(Some).map(AstFragment::OptExpr),
|
||||
AstFragmentKind::MethodReceiverExpr =>
|
||||
result.make_expr().map(AstFragment::MethodReceiverExpr),
|
||||
$(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
|
||||
}
|
||||
}
|
||||
@ -98,6 +103,13 @@ macro_rules! ast_fragments {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_method_receiver_expr(self) -> P<ast::Expr> {
|
||||
match self {
|
||||
AstFragment::MethodReceiverExpr(expr) => expr,
|
||||
_ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
|
||||
}
|
||||
}
|
||||
|
||||
$(pub fn $make_ast(self) -> $AstTy {
|
||||
match self {
|
||||
AstFragment::$Kind(ast) => ast,
|
||||
@ -120,6 +132,7 @@ macro_rules! ast_fragments {
|
||||
}
|
||||
});
|
||||
}
|
||||
AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
|
||||
$($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
|
||||
$($(AstFragment::$Kind(ast) =>
|
||||
ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
|
||||
@ -130,6 +143,7 @@ macro_rules! ast_fragments {
|
||||
match *self {
|
||||
AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
|
||||
AstFragment::OptExpr(None) => {}
|
||||
AstFragment::MethodReceiverExpr(ref expr) => visitor.visit_method_receiver_expr(expr),
|
||||
$($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
|
||||
$($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
|
||||
visitor.$visit_ast_elt(ast_elt, $($args)*);
|
||||
@ -222,6 +236,7 @@ impl AstFragmentKind {
|
||||
match self {
|
||||
AstFragmentKind::OptExpr
|
||||
| AstFragmentKind::Expr
|
||||
| AstFragmentKind::MethodReceiverExpr
|
||||
| AstFragmentKind::Stmts
|
||||
| AstFragmentKind::Ty
|
||||
| AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
|
||||
@ -285,6 +300,9 @@ impl AstFragmentKind {
|
||||
AstFragmentKind::Expr => AstFragment::Expr(
|
||||
items.next().expect("expected exactly one expression").expect_expr(),
|
||||
),
|
||||
AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(
|
||||
items.next().expect("expected exactly one expression").expect_expr(),
|
||||
),
|
||||
AstFragmentKind::OptExpr => {
|
||||
AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
|
||||
}
|
||||
@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>(
|
||||
AstFragment::Stmts(stmts)
|
||||
}
|
||||
AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
|
||||
AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?),
|
||||
AstFragmentKind::OptExpr => {
|
||||
if this.token != token::Eof {
|
||||
AstFragment::OptExpr(Some(this.parse_expr()?))
|
||||
@ -1477,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
|
||||
/// It can be removed once that feature is stabilized.
|
||||
struct MethodReceiverTag;
|
||||
impl DummyAstNode for MethodReceiverTag {
|
||||
fn dummy() -> MethodReceiverTag {
|
||||
MethodReceiverTag
|
||||
}
|
||||
}
|
||||
impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
|
||||
type OutputTy = Self;
|
||||
type AttrsTy = ast::AttrVec;
|
||||
const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
|
||||
fn descr() -> &'static str {
|
||||
"an expression"
|
||||
}
|
||||
fn to_annotatable(self) -> Annotatable {
|
||||
Annotatable::Expr(self.wrapped)
|
||||
}
|
||||
fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
|
||||
AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
|
||||
}
|
||||
fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
|
||||
noop_visit_expr(&mut self.wrapped, visitor)
|
||||
}
|
||||
fn is_mac_call(&self) -> bool {
|
||||
matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
|
||||
}
|
||||
fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
|
||||
let node = self.wrapped.into_inner();
|
||||
match node.kind {
|
||||
ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct InvocationCollector<'a, 'b> {
|
||||
cx: &'a mut ExtCtxt<'b>,
|
||||
invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
|
||||
@ -1840,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
self.visit_node(node)
|
||||
}
|
||||
|
||||
fn visit_method_receiver_expr(&mut self, node: &mut P<ast::Expr>) {
|
||||
visit_clobber(node, |node| {
|
||||
let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag);
|
||||
self.visit_node(&mut wrapper);
|
||||
wrapper.wrapped
|
||||
})
|
||||
}
|
||||
|
||||
fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||
self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ pub fn placeholder(
|
||||
}),
|
||||
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
|
||||
AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
|
||||
AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()),
|
||||
AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
|
||||
id,
|
||||
span,
|
||||
@ -296,6 +297,13 @@ impl MutVisitor for PlaceholderExpander {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
match expr.kind {
|
||||
ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(),
|
||||
_ => noop_visit_expr(expr, self),
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||
match expr.kind {
|
||||
ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
|
||||
|
@ -714,7 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expr: &hir::Expr<'tcx>,
|
||||
checked_ty: Ty<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
) -> Option<(Span, String, String, Applicability, bool /* verbose */)> {
|
||||
) -> Option<(
|
||||
Span,
|
||||
String,
|
||||
String,
|
||||
Applicability,
|
||||
bool, /* verbose */
|
||||
bool, /* suggest `&` or `&mut` type annotation */
|
||||
)> {
|
||||
let sess = self.sess();
|
||||
let sp = expr.span;
|
||||
|
||||
@ -746,6 +753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -760,6 +768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
"b".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -817,6 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
sugg.2,
|
||||
Applicability::MachineApplicable,
|
||||
false,
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
@ -844,6 +854,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
format!("{prefix}&mut {sugg_expr}"),
|
||||
Applicability::MachineApplicable,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
hir::Mutability::Not => (
|
||||
sp,
|
||||
@ -851,6 +862,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
format!("{prefix}&{sugg_expr}"),
|
||||
Applicability::MachineApplicable,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
});
|
||||
}
|
||||
@ -880,6 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
true,
|
||||
true
|
||||
));
|
||||
}
|
||||
return None;
|
||||
@ -893,6 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
true,
|
||||
true,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -959,6 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
src,
|
||||
applicability,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -999,6 +1014,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Applicability::MachineApplicable
|
||||
},
|
||||
true,
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
@ -1050,6 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
suggestion,
|
||||
Applicability::MachineApplicable,
|
||||
true,
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||
) -> bool {
|
||||
let expr = expr.peel_blocks();
|
||||
if let Some((sp, msg, suggestion, applicability, verbose)) =
|
||||
if let Some((sp, msg, suggestion, applicability, verbose, annotation)) =
|
||||
self.check_ref(expr, found, expected)
|
||||
{
|
||||
if verbose {
|
||||
@ -335,9 +335,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
err.span_suggestion(sp, &msg, suggestion, applicability);
|
||||
}
|
||||
if annotation {
|
||||
let suggest_annotation = match expr.peel_drop_temps().kind {
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&",
|
||||
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ",
|
||||
_ => return true,
|
||||
};
|
||||
let mut tuple_indexes = Vec::new();
|
||||
let mut expr_id = expr.hir_id;
|
||||
for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) {
|
||||
match node {
|
||||
Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => {
|
||||
tuple_indexes.push(
|
||||
subs.iter()
|
||||
.enumerate()
|
||||
.find(|(_, sub_expr)| sub_expr.hir_id == expr_id)
|
||||
.unwrap()
|
||||
.0,
|
||||
);
|
||||
expr_id = parent_id;
|
||||
}
|
||||
Node::Local(local) => {
|
||||
if let Some(mut ty) = local.ty {
|
||||
while let Some(index) = tuple_indexes.pop() {
|
||||
match ty.kind {
|
||||
TyKind::Tup(tys) => ty = &tys[index],
|
||||
_ => return true,
|
||||
}
|
||||
}
|
||||
let annotation_span = ty.span;
|
||||
err.span_suggestion(
|
||||
annotation_span.with_hi(annotation_span.lo()),
|
||||
format!("alternatively, consider changing the type annotation"),
|
||||
suggest_annotation,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if self.suggest_else_fn_with_closure(err, expr, found, expected)
|
||||
{
|
||||
} else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
|
||||
return true;
|
||||
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
|
||||
&& let ty::FnDef(def_id, ..) = &found.kind()
|
||||
|
@ -286,8 +286,8 @@ pub fn suggest_new_region_bound(
|
||||
) {
|
||||
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
|
||||
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
|
||||
let consider = "consider changing the";
|
||||
let declare = "to declare that the";
|
||||
let consider = "consider changing";
|
||||
let declare = "to declare that";
|
||||
let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name);
|
||||
let explicit_static =
|
||||
arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg));
|
||||
@ -305,6 +305,10 @@ pub fn suggest_new_region_bound(
|
||||
return;
|
||||
};
|
||||
|
||||
// Get the identity type for this RPIT
|
||||
let did = item_id.def_id.to_def_id();
|
||||
let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did));
|
||||
|
||||
if let Some(span) = opaque
|
||||
.bounds
|
||||
.iter()
|
||||
@ -321,7 +325,7 @@ pub fn suggest_new_region_bound(
|
||||
if let Some(explicit_static) = &explicit_static {
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
&format!("{} `impl Trait`'s {}", consider, explicit_static),
|
||||
&format!("{consider} `{ty}`'s {explicit_static}"),
|
||||
&lifetime_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
@ -351,12 +355,7 @@ pub fn suggest_new_region_bound(
|
||||
} else {
|
||||
err.span_suggestion_verbose(
|
||||
fn_return.span.shrink_to_hi(),
|
||||
&format!(
|
||||
"{declare} `impl Trait` {captures}, {explicit}",
|
||||
declare = declare,
|
||||
captures = captures,
|
||||
explicit = explicit,
|
||||
),
|
||||
&format!("{declare} `{ty}` {captures}, {explicit}",),
|
||||
&plus_lt,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
@ -367,7 +366,7 @@ pub fn suggest_new_region_bound(
|
||||
err.span_suggestion_verbose(
|
||||
fn_return.span.shrink_to_hi(),
|
||||
&format!(
|
||||
"{declare} trait object {captures}, {explicit}",
|
||||
"{declare} the trait object {captures}, {explicit}",
|
||||
declare = declare,
|
||||
captures = captures,
|
||||
explicit = explicit,
|
||||
@ -384,7 +383,7 @@ pub fn suggest_new_region_bound(
|
||||
if let Some(explicit_static) = &explicit_static {
|
||||
err.span_suggestion_verbose(
|
||||
lt.span,
|
||||
&format!("{} trait object's {}", consider, explicit_static),
|
||||
&format!("{} the trait object's {}", consider, explicit_static),
|
||||
&lifetime_name,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
@ -16,7 +16,6 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
|
||||
use rustc_errors::{ErrorGuaranteed, PResult};
|
||||
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
|
||||
use rustc_hir::def_id::StableCrateId;
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore};
|
||||
use rustc_metadata::creader::CStore;
|
||||
use rustc_middle::arena::Arena;
|
||||
@ -30,7 +29,7 @@ use rustc_plugin_impl as plugin;
|
||||
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
|
||||
use rustc_resolve::{Resolver, ResolverArenas};
|
||||
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
|
||||
use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn};
|
||||
use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn};
|
||||
use rustc_session::output::filename_for_input;
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::{Limit, Session};
|
||||
@ -135,10 +134,7 @@ mod boxed_resolver {
|
||||
f((&mut *resolver).as_mut().unwrap())
|
||||
}
|
||||
|
||||
pub fn to_resolver_outputs(
|
||||
resolver: Rc<RefCell<BoxedResolver>>,
|
||||
) -> (Definitions, Box<CrateStoreDyn>, ty::ResolverOutputs, ty::ResolverAstLowering)
|
||||
{
|
||||
pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs {
|
||||
match Rc::try_unwrap(resolver) {
|
||||
Ok(resolver) => {
|
||||
let mut resolver = resolver.into_inner();
|
||||
@ -788,8 +784,7 @@ pub fn create_global_ctxt<'tcx>(
|
||||
// incr. comp. yet.
|
||||
dep_graph.assert_ignored();
|
||||
|
||||
let (definitions, cstore, resolver_outputs, resolver_for_lowering) =
|
||||
BoxedResolver::to_resolver_outputs(resolver);
|
||||
let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver);
|
||||
|
||||
let sess = &compiler.session();
|
||||
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
|
||||
@ -816,10 +811,7 @@ pub fn create_global_ctxt<'tcx>(
|
||||
lint_store,
|
||||
arena,
|
||||
hir_arena,
|
||||
definitions,
|
||||
cstore,
|
||||
resolver_outputs,
|
||||
resolver_for_lowering,
|
||||
krate,
|
||||
dep_graph,
|
||||
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
|
||||
|
@ -454,7 +454,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
|
||||
|
||||
self.formatting_init.extend(code_init);
|
||||
Ok(quote! {
|
||||
#diag.span_suggestion_with_style(
|
||||
#diag.span_suggestions_with_style(
|
||||
#span_field,
|
||||
rustc_errors::fluent::#slug,
|
||||
#code_field,
|
||||
|
@ -11,9 +11,11 @@ use crate::diagnostics::utils::{
|
||||
};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path};
|
||||
use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path};
|
||||
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||
|
||||
use super::utils::{build_suggestion_code, AllowMultipleAlternatives};
|
||||
|
||||
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
|
||||
pub(crate) struct SubdiagnosticDeriveBuilder {
|
||||
diag: syn::Ident,
|
||||
@ -414,15 +416,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||
let nested_name = meta.path().segments.last().unwrap().ident.to_string();
|
||||
let nested_name = nested_name.as_str();
|
||||
|
||||
let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else {
|
||||
throw_invalid_nested_attr!(attr, &nested_attr);
|
||||
};
|
||||
|
||||
match nested_name {
|
||||
"code" => {
|
||||
let formatted_str = self.build_format(&value.value(), value.span());
|
||||
let code_field = new_code_ident();
|
||||
code.set_once((code_field, formatted_str), span);
|
||||
let formatting_init = build_suggestion_code(
|
||||
&code_field,
|
||||
meta,
|
||||
self,
|
||||
AllowMultipleAlternatives::No,
|
||||
);
|
||||
code.set_once((code_field, formatting_init), span);
|
||||
}
|
||||
_ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
|
||||
diag.help("`code` is the only valid nested attribute")
|
||||
@ -430,14 +433,14 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||
}
|
||||
}
|
||||
|
||||
let Some((code_field, formatted_str)) = code.value() else {
|
||||
let Some((code_field, formatting_init)) = code.value() else {
|
||||
span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
|
||||
.emit();
|
||||
return Ok(quote! {});
|
||||
};
|
||||
let binding = info.binding;
|
||||
|
||||
self.formatting_init.extend(quote! { let #code_field = #formatted_str; });
|
||||
self.formatting_init.extend(formatting_init);
|
||||
let code_field = if clone_suggestion_code {
|
||||
quote! { #code_field.clone() }
|
||||
} else {
|
||||
|
@ -2,7 +2,7 @@ use crate::diagnostics::error::{
|
||||
span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
|
||||
};
|
||||
use proc_macro::Span;
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
@ -395,6 +395,82 @@ pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap<Stri
|
||||
fields_map
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub(super) enum AllowMultipleAlternatives {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
/// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or
|
||||
/// `#[suggestion*(code("foo", "bar"))]` attribute field
|
||||
pub(super) fn build_suggestion_code(
|
||||
code_field: &Ident,
|
||||
meta: &Meta,
|
||||
fields: &impl HasFieldMap,
|
||||
allow_multiple: AllowMultipleAlternatives,
|
||||
) -> TokenStream {
|
||||
let values = match meta {
|
||||
// `code = "foo"`
|
||||
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s],
|
||||
// `code("foo", "bar")`
|
||||
Meta::List(MetaList { nested, .. }) => {
|
||||
if let AllowMultipleAlternatives::No = allow_multiple {
|
||||
span_err(
|
||||
meta.span().unwrap(),
|
||||
"expected exactly one string literal for `code = ...`",
|
||||
)
|
||||
.emit();
|
||||
vec![]
|
||||
} else if nested.is_empty() {
|
||||
span_err(
|
||||
meta.span().unwrap(),
|
||||
"expected at least one string literal for `code(...)`",
|
||||
)
|
||||
.emit();
|
||||
vec![]
|
||||
} else {
|
||||
nested
|
||||
.into_iter()
|
||||
.filter_map(|item| {
|
||||
if let NestedMeta::Lit(syn::Lit::Str(s)) = item {
|
||||
Some(s)
|
||||
} else {
|
||||
span_err(
|
||||
item.span().unwrap(),
|
||||
"`code(...)` must contain only string literals",
|
||||
)
|
||||
.emit();
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
span_err(
|
||||
meta.span().unwrap(),
|
||||
r#"`code = "..."`/`code(...)` must contain only string literals"#,
|
||||
)
|
||||
.emit();
|
||||
vec![]
|
||||
}
|
||||
};
|
||||
|
||||
if let AllowMultipleAlternatives::Yes = allow_multiple {
|
||||
let formatted_strings: Vec<_> = values
|
||||
.into_iter()
|
||||
.map(|value| fields.build_format(&value.value(), value.span()))
|
||||
.collect();
|
||||
quote! { let #code_field = [#(#formatted_strings),*].into_iter(); }
|
||||
} else if let [value] = values.as_slice() {
|
||||
let formatted_str = fields.build_format(&value.value(), value.span());
|
||||
quote! { let #code_field = #formatted_str; }
|
||||
} else {
|
||||
// error handled previously
|
||||
quote! { let #code_field = String::new(); }
|
||||
}
|
||||
}
|
||||
|
||||
/// Possible styles for suggestion subdiagnostics.
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) enum SuggestionKind {
|
||||
@ -571,21 +647,23 @@ impl SubdiagnosticKind {
|
||||
let nested_name = meta.path().segments.last().unwrap().ident.to_string();
|
||||
let nested_name = nested_name.as_str();
|
||||
|
||||
let value = match meta {
|
||||
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value,
|
||||
let string_value = match meta {
|
||||
Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value),
|
||||
|
||||
Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
|
||||
diag.help("a diagnostic slug must be the first argument to the attribute")
|
||||
}),
|
||||
_ => {
|
||||
invalid_nested_attr(attr, &nested_attr).emit();
|
||||
continue;
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
match (nested_name, &mut kind) {
|
||||
("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
|
||||
let formatted_str = fields.build_format(&value.value(), value.span());
|
||||
let code_init = quote! { let #code_field = #formatted_str; };
|
||||
let code_init = build_suggestion_code(
|
||||
code_field,
|
||||
meta,
|
||||
fields,
|
||||
AllowMultipleAlternatives::Yes,
|
||||
);
|
||||
code.set_once(code_init, span);
|
||||
}
|
||||
(
|
||||
@ -593,6 +671,11 @@ impl SubdiagnosticKind {
|
||||
SubdiagnosticKind::Suggestion { ref mut applicability, .. }
|
||||
| SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. },
|
||||
) => {
|
||||
let Some(value) = string_value else {
|
||||
invalid_nested_attr(attr, &nested_attr).emit();
|
||||
continue;
|
||||
};
|
||||
|
||||
let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
|
||||
span_err(span, "invalid applicability").emit();
|
||||
Applicability::Unspecified
|
||||
@ -623,7 +706,7 @@ impl SubdiagnosticKind {
|
||||
init
|
||||
} else {
|
||||
span_err(span, "suggestion without `code = \"...\"`").emit();
|
||||
quote! { let #code_field: String = unreachable!(); }
|
||||
quote! { let #code_field = std::iter::empty(); }
|
||||
};
|
||||
}
|
||||
SubdiagnosticKind::Label
|
||||
@ -644,7 +727,7 @@ impl quote::IdentFragment for SubdiagnosticKind {
|
||||
SubdiagnosticKind::Note => write!(f, "note"),
|
||||
SubdiagnosticKind::Help => write!(f, "help"),
|
||||
SubdiagnosticKind::Warn => write!(f, "warn"),
|
||||
SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"),
|
||||
SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"),
|
||||
SubdiagnosticKind::MultipartSuggestion { .. } => {
|
||||
write!(f, "multipart_suggestion_with_style")
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ rustc_queries! {
|
||||
desc { "triggering a delay span bug" }
|
||||
}
|
||||
|
||||
query resolutions(_: ()) -> &'tcx ty::ResolverOutputs {
|
||||
query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
|
||||
eval_always
|
||||
no_hash
|
||||
desc { "getting the resolver outputs" }
|
||||
|
@ -79,7 +79,7 @@ use std::mem;
|
||||
use std::ops::{Bound, Deref};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::{ImplPolarity, RvalueScopes};
|
||||
use super::{ImplPolarity, ResolverOutputs, RvalueScopes};
|
||||
|
||||
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
|
||||
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
|
||||
@ -1067,10 +1067,9 @@ pub struct GlobalCtxt<'tcx> {
|
||||
pub consts: CommonConsts<'tcx>,
|
||||
|
||||
definitions: RwLock<Definitions>,
|
||||
cstore: Box<CrateStoreDyn>,
|
||||
|
||||
/// Output of the resolver.
|
||||
pub(crate) untracked_resolutions: ty::ResolverOutputs,
|
||||
pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
|
||||
untracked_resolver_for_lowering: Steal<ty::ResolverAstLowering>,
|
||||
/// The entire crate as AST. This field serves as the input for the hir_crate query,
|
||||
/// which lowers it from AST to HIR. It must not be read or used by anything else.
|
||||
@ -1233,10 +1232,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
|
||||
arena: &'tcx WorkerLocal<Arena<'tcx>>,
|
||||
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
|
||||
definitions: Definitions,
|
||||
cstore: Box<CrateStoreDyn>,
|
||||
untracked_resolutions: ty::ResolverOutputs,
|
||||
untracked_resolver_for_lowering: ty::ResolverAstLowering,
|
||||
resolver_outputs: ResolverOutputs,
|
||||
krate: Lrc<ast::Crate>,
|
||||
dep_graph: DepGraph,
|
||||
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
|
||||
@ -1245,6 +1241,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
crate_name: &str,
|
||||
output_filenames: OutputFilenames,
|
||||
) -> GlobalCtxt<'tcx> {
|
||||
let ResolverOutputs {
|
||||
definitions,
|
||||
global_ctxt: untracked_resolutions,
|
||||
ast_lowering: untracked_resolver_for_lowering,
|
||||
} = resolver_outputs;
|
||||
let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| {
|
||||
s.emit_fatal(err);
|
||||
});
|
||||
@ -1253,7 +1254,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
&interners,
|
||||
s,
|
||||
&definitions,
|
||||
&*cstore,
|
||||
&*untracked_resolutions.cstore,
|
||||
// This is only used to create a stable hashing context.
|
||||
&untracked_resolutions.source_span,
|
||||
);
|
||||
@ -1268,7 +1269,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
interners,
|
||||
dep_graph,
|
||||
definitions: RwLock::new(definitions),
|
||||
cstore,
|
||||
prof: s.prof.clone(),
|
||||
types: common_types,
|
||||
lifetimes: common_lifetimes,
|
||||
@ -1369,7 +1369,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
if let Some(id) = id.as_local() {
|
||||
self.definitions_untracked().def_key(id)
|
||||
} else {
|
||||
self.cstore.def_key(id)
|
||||
self.untracked_resolutions.cstore.def_key(id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1383,7 +1383,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
if let Some(id) = id.as_local() {
|
||||
self.definitions_untracked().def_path(id)
|
||||
} else {
|
||||
self.cstore.def_path(id)
|
||||
self.untracked_resolutions.cstore.def_path(id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1393,7 +1393,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
if let Some(def_id) = def_id.as_local() {
|
||||
self.definitions_untracked().def_path_hash(def_id)
|
||||
} else {
|
||||
self.cstore.def_path_hash(def_id)
|
||||
self.untracked_resolutions.cstore.def_path_hash(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1402,7 +1402,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
if crate_num == LOCAL_CRATE {
|
||||
self.sess.local_stable_crate_id()
|
||||
} else {
|
||||
self.cstore.stable_crate_id(crate_num)
|
||||
self.untracked_resolutions.cstore.stable_crate_id(crate_num)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1413,7 +1413,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
if stable_crate_id == self.sess.local_stable_crate_id() {
|
||||
LOCAL_CRATE
|
||||
} else {
|
||||
self.cstore.stable_crate_id_to_crate_num(stable_crate_id)
|
||||
self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1432,8 +1432,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
} else {
|
||||
// If this is a DefPathHash from an upstream crate, let the CrateStore map
|
||||
// it to a DefId.
|
||||
let cnum = self.cstore.stable_crate_id_to_crate_num(stable_crate_id);
|
||||
self.cstore.def_path_hash_to_def_id(cnum, hash)
|
||||
let cstore = &*self.untracked_resolutions.cstore;
|
||||
let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
|
||||
cstore.def_path_hash_to_def_id(cnum, hash)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1445,7 +1446,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
let (crate_name, stable_crate_id) = if def_id.is_local() {
|
||||
(self.crate_name, self.sess.local_stable_crate_id())
|
||||
} else {
|
||||
let cstore = &self.cstore;
|
||||
let cstore = &*self.untracked_resolutions.cstore;
|
||||
(cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
|
||||
};
|
||||
|
||||
@ -1520,7 +1521,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Note that this is *untracked* and should only be used within the query
|
||||
/// system if the result is otherwise tracked through queries
|
||||
pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn {
|
||||
&*self.cstore
|
||||
&*self.untracked_resolutions.cstore
|
||||
}
|
||||
|
||||
/// Note that this is *untracked* and should only be used within the query
|
||||
@ -1546,7 +1547,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
let hcx = StableHashingContext::new(
|
||||
self.sess,
|
||||
&*definitions,
|
||||
&*self.cstore,
|
||||
&*self.untracked_resolutions.cstore,
|
||||
&self.untracked_resolutions.source_span,
|
||||
);
|
||||
f(hcx)
|
||||
@ -2364,7 +2365,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
st,
|
||||
self.sess,
|
||||
&self.definitions.read(),
|
||||
&*self.cstore,
|
||||
&*self.untracked_resolutions.cstore,
|
||||
// This is only used to create a stable hashing context.
|
||||
&self.untracked_resolutions.source_span,
|
||||
)
|
||||
|
@ -38,11 +38,13 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
|
||||
use rustc_hir::definitions::Definitions;
|
||||
use rustc_hir::Node;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_serialize::{Decodable, Encodable};
|
||||
use rustc_session::cstore::CrateStoreDyn;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{ExpnId, Span};
|
||||
@ -142,8 +144,15 @@ mod sty;
|
||||
|
||||
pub type RegisteredTools = FxHashSet<Ident>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ResolverOutputs {
|
||||
pub definitions: Definitions,
|
||||
pub global_ctxt: ResolverGlobalCtxt,
|
||||
pub ast_lowering: ResolverAstLowering,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ResolverGlobalCtxt {
|
||||
pub cstore: Box<CrateStoreDyn>,
|
||||
pub visibilities: FxHashMap<LocalDefId, Visibility>,
|
||||
/// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
|
||||
pub has_pub_restricted: bool,
|
||||
|
@ -553,39 +553,46 @@ impl<'a> Parser<'a> {
|
||||
match stmt.kind {
|
||||
// Expression without semicolon.
|
||||
StmtKind::Expr(ref mut expr)
|
||||
if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) =>
|
||||
{
|
||||
if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => {
|
||||
// Just check for errors and recover; do not eat semicolon yet.
|
||||
if let Err(mut e) =
|
||||
self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)])
|
||||
{
|
||||
if let TokenKind::DocComment(..) = self.token.kind {
|
||||
if let Ok(snippet) = self.span_to_snippet(self.token.span) {
|
||||
let sp = self.token.span;
|
||||
let marker = &snippet[..3];
|
||||
let (comment_marker, doc_comment_marker) = marker.split_at(2);
|
||||
// `expect_one_of` returns PResult<'a, bool /* recovered */>
|
||||
let replace_with_err =
|
||||
match self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) {
|
||||
// Recover from parser, skip type error to avoid extra errors.
|
||||
Ok(true) => true,
|
||||
Err(mut e) => {
|
||||
if let TokenKind::DocComment(..) = self.token.kind &&
|
||||
let Ok(snippet) = self.span_to_snippet(self.token.span) {
|
||||
let sp = self.token.span;
|
||||
let marker = &snippet[..3];
|
||||
let (comment_marker, doc_comment_marker) = marker.split_at(2);
|
||||
|
||||
e.span_suggestion(
|
||||
sp.with_hi(sp.lo() + BytePos(marker.len() as u32)),
|
||||
&format!(
|
||||
"add a space before `{}` to use a regular comment",
|
||||
doc_comment_marker,
|
||||
),
|
||||
format!("{} {}", comment_marker, doc_comment_marker),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
e.span_suggestion(
|
||||
sp.with_hi(sp.lo() + BytePos(marker.len() as u32)),
|
||||
&format!(
|
||||
"add a space before `{}` to use a regular comment",
|
||||
doc_comment_marker,
|
||||
),
|
||||
format!("{} {}", comment_marker, doc_comment_marker),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Err(mut e) =
|
||||
self.check_mistyped_turbofish_with_multiple_type_params(e, expr)
|
||||
{
|
||||
if recover.no() {
|
||||
return Err(e);
|
||||
|
||||
if let Err(mut e) =
|
||||
self.check_mistyped_turbofish_with_multiple_type_params(e, expr)
|
||||
{
|
||||
if recover.no() {
|
||||
return Err(e);
|
||||
}
|
||||
e.emit();
|
||||
self.recover_stmt();
|
||||
}
|
||||
e.emit();
|
||||
self.recover_stmt();
|
||||
true
|
||||
}
|
||||
// Don't complain about type errors in body tail after parse error (#57383).
|
||||
_ => false
|
||||
};
|
||||
if replace_with_err {
|
||||
// We already emitted an error, so don't emit another type error
|
||||
let sp = expr.span.to(self.prev_token.span);
|
||||
*expr = self.mk_expr_err(sp);
|
||||
}
|
||||
|
@ -42,9 +42,10 @@ use rustc_metadata::creader::{CStore, CrateLoader};
|
||||
use rustc_middle::metadata::ModChild;
|
||||
use rustc_middle::middle::privacy::AccessLevels;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, ResolverOutputs};
|
||||
use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools};
|
||||
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_session::cstore::{CrateStore, CrateStoreDyn, MetadataLoaderDyn};
|
||||
use rustc_session::cstore::{CrateStore, MetadataLoaderDyn};
|
||||
use rustc_session::lint::LintBuffer;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
|
||||
@ -1376,9 +1377,7 @@ impl<'a> Resolver<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
pub fn into_outputs(
|
||||
self,
|
||||
) -> (Definitions, Box<CrateStoreDyn>, ResolverOutputs, ty::ResolverAstLowering) {
|
||||
pub fn into_outputs(self) -> ResolverOutputs {
|
||||
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
|
||||
let definitions = self.definitions;
|
||||
let cstore = Box::new(self.crate_loader.into_cstore());
|
||||
@ -1394,7 +1393,8 @@ impl<'a> Resolver<'a> {
|
||||
let main_def = self.main_def;
|
||||
let confused_type_with_std_module = self.confused_type_with_std_module;
|
||||
let access_levels = self.access_levels;
|
||||
let resolutions = ResolverOutputs {
|
||||
let global_ctxt = ResolverGlobalCtxt {
|
||||
cstore,
|
||||
source_span,
|
||||
expn_that_defined,
|
||||
visibilities,
|
||||
@ -1416,7 +1416,7 @@ impl<'a> Resolver<'a> {
|
||||
confused_type_with_std_module,
|
||||
registered_tools: self.registered_tools,
|
||||
};
|
||||
let resolutions_lowering = ty::ResolverAstLowering {
|
||||
let ast_lowering = ty::ResolverAstLowering {
|
||||
legacy_const_generic_args: self.legacy_const_generic_args,
|
||||
partial_res_map: self.partial_res_map,
|
||||
import_res_map: self.import_res_map,
|
||||
@ -1429,16 +1429,15 @@ impl<'a> Resolver<'a> {
|
||||
trait_map: self.trait_map,
|
||||
builtin_macro_kinds: self.builtin_macro_kinds,
|
||||
};
|
||||
(definitions, cstore, resolutions, resolutions_lowering)
|
||||
ResolverOutputs { definitions, global_ctxt, ast_lowering }
|
||||
}
|
||||
|
||||
pub fn clone_outputs(
|
||||
&self,
|
||||
) -> (Definitions, Box<CrateStoreDyn>, ResolverOutputs, ty::ResolverAstLowering) {
|
||||
pub fn clone_outputs(&self) -> ResolverOutputs {
|
||||
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
|
||||
let definitions = self.definitions.clone();
|
||||
let cstore = Box::new(self.cstore().clone());
|
||||
let resolutions = ResolverOutputs {
|
||||
let global_ctxt = ResolverGlobalCtxt {
|
||||
cstore,
|
||||
source_span: self.source_span.clone(),
|
||||
expn_that_defined: self.expn_that_defined.clone(),
|
||||
visibilities: self.visibilities.clone(),
|
||||
@ -1460,7 +1459,7 @@ impl<'a> Resolver<'a> {
|
||||
registered_tools: self.registered_tools.clone(),
|
||||
access_levels: self.access_levels.clone(),
|
||||
};
|
||||
let resolutions_lowering = ty::ResolverAstLowering {
|
||||
let ast_lowering = ty::ResolverAstLowering {
|
||||
legacy_const_generic_args: self.legacy_const_generic_args.clone(),
|
||||
partial_res_map: self.partial_res_map.clone(),
|
||||
import_res_map: self.import_res_map.clone(),
|
||||
@ -1473,7 +1472,7 @@ impl<'a> Resolver<'a> {
|
||||
trait_map: self.trait_map.clone(),
|
||||
builtin_macro_kinds: self.builtin_macro_kinds.clone(),
|
||||
};
|
||||
(definitions, cstore, resolutions, resolutions_lowering)
|
||||
ResolverOutputs { definitions, global_ctxt, ast_lowering }
|
||||
}
|
||||
|
||||
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
|
||||
|
@ -2229,6 +2229,16 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
|
||||
!ptr.is_null() && ptr.is_aligned()
|
||||
}
|
||||
|
||||
/// Checks whether an allocation of `len` instances of `T` exceeds
|
||||
/// the maximum allowed allocation size.
|
||||
pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
|
||||
let max_len = const {
|
||||
let size = crate::mem::size_of::<T>();
|
||||
if size == 0 { usize::MAX } else { isize::MAX as usize / size }
|
||||
};
|
||||
len <= max_len
|
||||
}
|
||||
|
||||
/// Checks whether the regions of memory starting at `src` and `dst` of size
|
||||
/// `count * size_of::<T>()` do *not* overlap.
|
||||
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
|
||||
|
@ -192,6 +192,7 @@
|
||||
#![feature(extern_types)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(intra_doc_pointers)]
|
||||
#![feature(intrinsics)]
|
||||
#![feature(lang_items)]
|
||||
|
@ -1,7 +1,9 @@
|
||||
//! Free functions to create `&[T]` and `&mut [T]`.
|
||||
|
||||
use crate::array;
|
||||
use crate::intrinsics::{assert_unsafe_precondition, is_aligned_and_not_null};
|
||||
use crate::intrinsics::{
|
||||
assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size,
|
||||
};
|
||||
use crate::ops::Range;
|
||||
use crate::ptr;
|
||||
|
||||
@ -91,8 +93,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
|
||||
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
|
||||
unsafe {
|
||||
assert_unsafe_precondition!([T](data: *const T, len: usize) =>
|
||||
is_aligned_and_not_null(data)
|
||||
&& crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
|
||||
is_aligned_and_not_null(data) && is_valid_allocation_size::<T>(len)
|
||||
);
|
||||
&*ptr::slice_from_raw_parts(data, len)
|
||||
}
|
||||
@ -135,8 +136,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m
|
||||
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
|
||||
unsafe {
|
||||
assert_unsafe_precondition!([T](data: *mut T, len: usize) =>
|
||||
is_aligned_and_not_null(data)
|
||||
&& crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
|
||||
is_aligned_and_not_null(data) && is_valid_allocation_size::<T>(len)
|
||||
);
|
||||
&mut *ptr::slice_from_raw_parts_mut(data, len)
|
||||
}
|
||||
|
@ -758,3 +758,41 @@ struct WithDocComment {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(compiletest_example)]
|
||||
struct SuggestionsGood {
|
||||
#[suggestion(code("foo", "bar"))]
|
||||
sub: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(compiletest_example)]
|
||||
struct SuggestionsSingleItem {
|
||||
#[suggestion(code("foo"))]
|
||||
sub: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(compiletest_example)]
|
||||
struct SuggestionsNoItem {
|
||||
#[suggestion(code())]
|
||||
//~^ ERROR expected at least one string literal for `code(...)`
|
||||
sub: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(compiletest_example)]
|
||||
struct SuggestionsInvalidItem {
|
||||
#[suggestion(code(foo))]
|
||||
//~^ ERROR `code(...)` must contain only string literals
|
||||
sub: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(compiletest_example)]
|
||||
struct SuggestionsInvalidLiteral {
|
||||
#[suggestion(code = 3)]
|
||||
//~^ ERROR `code = "..."`/`code(...)` must contain only string literals
|
||||
sub: Span,
|
||||
}
|
||||
|
@ -573,6 +573,24 @@ LL | #[subdiagnostic(eager)]
|
||||
|
|
||||
= help: eager subdiagnostics are not supported on lints
|
||||
|
||||
error: expected at least one string literal for `code(...)`
|
||||
--> $DIR/diagnostic-derive.rs:779:18
|
||||
|
|
||||
LL | #[suggestion(code())]
|
||||
| ^^^^^^
|
||||
|
||||
error: `code(...)` must contain only string literals
|
||||
--> $DIR/diagnostic-derive.rs:787:23
|
||||
|
|
||||
LL | #[suggestion(code(foo))]
|
||||
| ^^^
|
||||
|
||||
error: `code = "..."`/`code(...)` must contain only string literals
|
||||
--> $DIR/diagnostic-derive.rs:795:18
|
||||
|
|
||||
LL | #[suggestion(code = 3)]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: cannot find attribute `nonsense` in this scope
|
||||
--> $DIR/diagnostic-derive.rs:55:3
|
||||
|
|
||||
@ -647,7 +665,7 @@ LL | arg: impl IntoDiagnosticArg,
|
||||
| ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
||||
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 80 previous errors
|
||||
error: aborting due to 83 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0425.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -661,3 +661,48 @@ enum BL {
|
||||
span: Span,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(parser_add_paren)]
|
||||
struct BM {
|
||||
#[suggestion_part(code("foo"))]
|
||||
//~^ ERROR expected exactly one string literal for `code = ...`
|
||||
span: Span,
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(parser_add_paren)]
|
||||
struct BN {
|
||||
#[suggestion_part(code("foo", "bar"))]
|
||||
//~^ ERROR expected exactly one string literal for `code = ...`
|
||||
span: Span,
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(parser_add_paren)]
|
||||
struct BO {
|
||||
#[suggestion_part(code(3))]
|
||||
//~^ ERROR expected exactly one string literal for `code = ...`
|
||||
span: Span,
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(parser_add_paren)]
|
||||
struct BP {
|
||||
#[suggestion_part(code())]
|
||||
//~^ ERROR expected exactly one string literal for `code = ...`
|
||||
span: Span,
|
||||
r#type: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(parser_add_paren)]
|
||||
struct BQ {
|
||||
#[suggestion_part(code = 3)]
|
||||
//~^ ERROR `code = "..."`/`code(...)` must contain only string literals
|
||||
span: Span,
|
||||
r#type: String,
|
||||
}
|
||||
|
@ -415,6 +415,36 @@ error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_sugg
|
||||
LL | #[applicability]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: expected exactly one string literal for `code = ...`
|
||||
--> $DIR/subdiagnostic-derive.rs:668:23
|
||||
|
|
||||
LL | #[suggestion_part(code("foo"))]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: expected exactly one string literal for `code = ...`
|
||||
--> $DIR/subdiagnostic-derive.rs:677:23
|
||||
|
|
||||
LL | #[suggestion_part(code("foo", "bar"))]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: expected exactly one string literal for `code = ...`
|
||||
--> $DIR/subdiagnostic-derive.rs:686:23
|
||||
|
|
||||
LL | #[suggestion_part(code(3))]
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected exactly one string literal for `code = ...`
|
||||
--> $DIR/subdiagnostic-derive.rs:695:23
|
||||
|
|
||||
LL | #[suggestion_part(code())]
|
||||
| ^^^^^^
|
||||
|
||||
error: `code = "..."`/`code(...)` must contain only string literals
|
||||
--> $DIR/subdiagnostic-derive.rs:704:23
|
||||
|
|
||||
LL | #[suggestion_part(code = 3)]
|
||||
| ^^^^^^^^
|
||||
|
||||
error: cannot find attribute `foo` in this scope
|
||||
--> $DIR/subdiagnostic-derive.rs:63:3
|
||||
|
|
||||
@ -475,6 +505,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
|
||||
LL | #[label(slug)]
|
||||
| ^^^^ not found in `rustc_errors::fluent`
|
||||
|
||||
error: aborting due to 67 previous errors
|
||||
error: aborting due to 72 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0425`.
|
||||
|
@ -25,7 +25,7 @@ LL | | (a, b)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
|
||||
| ++++
|
||||
|
14
src/test/ui/cfg/cfg-method-receiver-ok.rs
Normal file
14
src/test/ui/cfg/cfg-method-receiver-ok.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// check-pass
|
||||
|
||||
macro_rules! foo {
|
||||
() => {
|
||||
#[allow(unreachable_patterns)]
|
||||
{
|
||||
123i32
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = foo!().abs();
|
||||
}
|
@ -7,6 +7,5 @@ macro_rules! cbor_map {
|
||||
|
||||
fn main() {
|
||||
cbor_map! { #[cfg(test)] 4};
|
||||
//~^ ERROR attributes on expressions are experimental
|
||||
//~| ERROR removing an expression is not supported in this position
|
||||
//~^ ERROR removing an expression is not supported in this position
|
||||
}
|
||||
|
@ -1,12 +1,3 @@
|
||||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/cfg-method-receiver.rs:9:17
|
||||
|
|
||||
LL | cbor_map! { #[cfg(test)] 4};
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
error: removing an expression is not supported in this position
|
||||
--> $DIR/cfg-method-receiver.rs:9:17
|
||||
|
|
||||
@ -28,7 +19,6 @@ help: you must specify a concrete type for this numeric value, like `i32`
|
||||
LL | cbor_map! { #[cfg(test)] 4_i32};
|
||||
| ~~~~~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0658, E0689.
|
||||
For more information about an error, try `rustc --explain E0658`.
|
||||
For more information about this error, try `rustc --explain E0689`.
|
||||
|
@ -6,7 +6,7 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
|
||||
| ++++
|
||||
@ -19,7 +19,7 @@ LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl S
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + 'b {
|
||||
| ++++
|
||||
|
@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> im
|
||||
LL | if condition() { a } else { b }
|
||||
| ^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
|
||||
| ++++
|
||||
|
@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a,
|
||||
LL | if condition() { a } else { b }
|
||||
| ^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
|
||||
| ++++
|
||||
|
@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x }
|
||||
| |
|
||||
| hidden type `&i32` captures the anonymous lifetime defined here
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn elided(x: &i32) -> impl Copy + '_ { x }
|
||||
| ++++
|
||||
@ -19,7 +19,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
|
||||
| |
|
||||
| hidden type `&'a i32` captures the lifetime `'a` as defined here
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
|
||||
help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
|
||||
| ++++
|
||||
@ -32,7 +32,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
|
||||
| |
|
||||
| let's call the lifetime of this reference `'1`
|
||||
|
|
||||
help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
|
||||
help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
|
||||
| ~~
|
||||
@ -47,7 +47,7 @@ error: lifetime may not live long enough
|
||||
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
|
||||
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
|
||||
help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
|
||||
help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
|
||||
| ~~
|
||||
@ -76,7 +76,7 @@ help: to declare that the trait object captures data from argument `x`, you can
|
||||
|
|
||||
LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) }
|
||||
| ++++
|
||||
help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl Debug` captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
|
||||
| ++++
|
||||
@ -87,7 +87,7 @@ error: lifetime may not live long enough
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
|
||||
|
|
||||
help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
|
||||
help: consider changing `impl LifetimeTrait<'a> + 'static`'s explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
|
||||
| ~~
|
||||
@ -104,7 +104,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
|
||||
LL | move |_| println!("{}", y)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound
|
||||
|
|
||||
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b {
|
||||
| ++++
|
||||
|
@ -7,7 +7,7 @@ LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound
|
||||
help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `'x` lifetime bound
|
||||
|
|
||||
LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
|
||||
| ++++
|
||||
|
@ -6,7 +6,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
|
||||
LL | self.x.iter().map(|a| a.0)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl Iterator<Item = u32>` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
|
||||
| ++++
|
||||
@ -19,7 +19,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
|
||||
LL | self.x.iter().map(|a| a.0)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl Iterator<Item = u32>` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
|
||||
| ++++
|
||||
@ -32,7 +32,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
|
||||
LL | self.x.iter().map(|a| a.0)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
|
||||
help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
|
||||
| ++++
|
||||
@ -45,7 +45,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
|
||||
LL | self.x.iter().map(|a| a.0)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
|
||||
help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
|
||||
| ++++
|
||||
|
14
src/test/ui/macros/macro_rules-unmatchable-literals.rs
Normal file
14
src/test/ui/macros/macro_rules-unmatchable-literals.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// Pinning tests for things that don't work to make sure we notice if that changes
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
macro_rules! octal_with_bad_digit {
|
||||
( 0o1238 ) => {}; //~ ERROR invalid digit
|
||||
}
|
||||
|
||||
macro_rules! binary_with_bad_digit {
|
||||
( 0b012 ) => {}; //~ ERROR invalid digit
|
||||
}
|
||||
|
||||
// This can't happen for Hex and Decimal as things like `123A` and `0xFFG`
|
||||
// get treated as unknown *suffixes*, rather than digits.
|
14
src/test/ui/macros/macro_rules-unmatchable-literals.stderr
Normal file
14
src/test/ui/macros/macro_rules-unmatchable-literals.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: invalid digit for a base 8 literal
|
||||
--> $DIR/macro_rules-unmatchable-literals.rs:6:12
|
||||
|
|
||||
LL | ( 0o1238 ) => {};
|
||||
| ^
|
||||
|
||||
error: invalid digit for a base 2 literal
|
||||
--> $DIR/macro_rules-unmatchable-literals.rs:10:11
|
||||
|
|
||||
LL | ( 0b012 ) => {};
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -6,7 +6,7 @@ LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
|
||||
help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
|
||||
|
|
||||
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
|
||||
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
15
src/test/ui/parser/issue-103425.rs
Normal file
15
src/test/ui/parser/issue-103425.rs
Normal file
@ -0,0 +1,15 @@
|
||||
fn f() -> f32 {
|
||||
3
|
||||
//~^ ERROR expected `;`
|
||||
5.0
|
||||
}
|
||||
|
||||
fn k() -> f32 {
|
||||
2_u32
|
||||
//~^ ERROR expected `;`
|
||||
3_i8
|
||||
//~^ ERROR expected `;`
|
||||
5.0
|
||||
}
|
||||
|
||||
fn main() {}
|
29
src/test/ui/parser/issue-103425.stderr
Normal file
29
src/test/ui/parser/issue-103425.stderr
Normal file
@ -0,0 +1,29 @@
|
||||
error: expected `;`, found `5.0`
|
||||
--> $DIR/issue-103425.rs:2:6
|
||||
|
|
||||
LL | 3
|
||||
| ^ help: add `;` here
|
||||
LL |
|
||||
LL | 5.0
|
||||
| --- unexpected token
|
||||
|
||||
error: expected `;`, found `3_i8`
|
||||
--> $DIR/issue-103425.rs:8:10
|
||||
|
|
||||
LL | 2_u32
|
||||
| ^ help: add `;` here
|
||||
LL |
|
||||
LL | 3_i8
|
||||
| ---- unexpected token
|
||||
|
||||
error: expected `;`, found `5.0`
|
||||
--> $DIR/issue-103425.rs:10:9
|
||||
|
|
||||
LL | 3_i8
|
||||
| ^ help: add `;` here
|
||||
LL |
|
||||
LL | 5.0
|
||||
| --- unexpected token
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -6,7 +6,7 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
|
||||
| |
|
||||
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
|
||||
| ++++
|
||||
|
@ -6,7 +6,7 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self }
|
||||
| |
|
||||
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
|
||||
| ++++
|
||||
|
@ -11,6 +11,10 @@ help: consider removing the borrow
|
||||
LL - let a: String = &String::from("a");
|
||||
LL + let a: String = String::from("a");
|
||||
|
|
||||
help: alternatively, consider changing the type annotation
|
||||
|
|
||||
LL | let a: &String = &String::from("a");
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/format-borrow.rs:4:21
|
||||
@ -25,6 +29,10 @@ help: consider removing the borrow
|
||||
LL - let b: String = &format!("b");
|
||||
LL + let b: String = format!("b");
|
||||
|
|
||||
help: alternatively, consider changing the type annotation
|
||||
|
|
||||
LL | let b: &String = &format!("b");
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/format-borrow.rs:6:21
|
||||
@ -39,6 +47,10 @@ help: consider removing the borrow
|
||||
LL - let c: String = &mut format!("c");
|
||||
LL + let c: String = format!("c");
|
||||
|
|
||||
help: alternatively, consider changing the type annotation
|
||||
|
|
||||
LL | let c: &mut String = &mut format!("c");
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/format-borrow.rs:8:21
|
||||
@ -53,6 +65,10 @@ help: consider removing the borrow
|
||||
LL - let d: String = &mut (format!("d"));
|
||||
LL + let d: String = format!("d"));
|
||||
|
|
||||
help: alternatively, consider changing the type annotation
|
||||
|
|
||||
LL | let d: &mut String = &mut (format!("d"));
|
||||
| ++++
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
25
src/test/ui/suggestions/issue-102892.rs
Normal file
25
src/test/ui/suggestions/issue-102892.rs
Normal file
@ -0,0 +1,25 @@
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct A;
|
||||
#[derive(Debug)]
|
||||
struct B;
|
||||
|
||||
fn process_without_annot(arc: &Arc<(A, B)>) {
|
||||
let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
|
||||
}
|
||||
|
||||
fn process_with_annot(arc: &Arc<(A, B)>) {
|
||||
let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) {
|
||||
let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
57
src/test/ui/suggestions/issue-102892.stderr
Normal file
57
src/test/ui/suggestions/issue-102892.stderr
Normal file
@ -0,0 +1,57 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-102892.rs:15:26
|
||||
|
|
||||
LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
|
||||
| ------ ^^^^^^ expected tuple, found `&(A, B)`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected tuple `(A, B)`
|
||||
found reference `&(A, B)`
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
|
||||
LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too
|
||||
|
|
||||
help: alternatively, consider changing the type annotation
|
||||
|
|
||||
LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too
|
||||
| +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-102892.rs:20:32
|
||||
|
|
||||
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
| ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)`
|
||||
|
|
||||
= note: expected tuple `(A, B)`
|
||||
found mutable reference `&mut (A, B)`
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
|
|
||||
help: alternatively, consider changing the type annotation
|
||||
|
|
||||
LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
| ++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-102892.rs:20:48
|
||||
|
|
||||
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
| ^^^^^^^^^^ expected struct `A`, found `&A`
|
||||
|
|
||||
help: consider removing the borrow
|
||||
|
|
||||
LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too
|
||||
|
|
||||
help: alternatively, consider changing the type annotation
|
||||
|
|
||||
LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||
| +
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -18,7 +18,7 @@ LL | | *dest = g.get();
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
|
||||
| ++++
|
||||
|
@ -10,7 +10,7 @@ LL | | remaining: self.0.iter(),
|
||||
LL | | }
|
||||
| |_________^ returning this value requires that `'1` must outlive `'static`
|
||||
|
|
||||
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
||||
help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
||||
| ++++
|
||||
@ -65,7 +65,7 @@ LL | | remaining: self.0.iter(),
|
||||
LL | | }
|
||||
| |_________^ returning this value requires that `'a` must outlive `'static`
|
||||
|
|
||||
help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
|
||||
help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
||||
| ++++
|
||||
|
Loading…
Reference in New Issue
Block a user