Auto merge of #126951 - matthiaskrgr:rollup-xg0o4mc, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #126618 (Mark assoc tys live only if the corresponding trait is live) - #126746 (Deny `use<>` for RPITITs) - #126868 (not use offset when there is not ends with brace) - #126884 (Do not ICE when suggesting dereferencing closure arg) - #126893 (Eliminate the distinction between PREC_POSTFIX and PREC_PAREN precedence level) - #126915 (Don't suggest awaiting in closure patterns) - #126943 (De-duplicate all consecutive native libs regardless of their options) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
31f8b70d2e
46 changed files with 499 additions and 152 deletions
|
@ -233,8 +233,7 @@ pub const PREC_JUMP: i8 = -30;
|
||||||
pub const PREC_RANGE: i8 = -10;
|
pub const PREC_RANGE: i8 = -10;
|
||||||
// The range 2..=14 is reserved for AssocOp binary operator precedences.
|
// The range 2..=14 is reserved for AssocOp binary operator precedences.
|
||||||
pub const PREC_PREFIX: i8 = 50;
|
pub const PREC_PREFIX: i8 = 50;
|
||||||
pub const PREC_POSTFIX: i8 = 60;
|
pub const PREC_UNAMBIGUOUS: i8 = 60;
|
||||||
pub const PREC_PAREN: i8 = 99;
|
|
||||||
pub const PREC_FORCE_PAREN: i8 = 100;
|
pub const PREC_FORCE_PAREN: i8 = 100;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
@ -325,37 +324,35 @@ impl ExprPrecedence {
|
||||||
| ExprPrecedence::Let
|
| ExprPrecedence::Let
|
||||||
| ExprPrecedence::Unary => PREC_PREFIX,
|
| ExprPrecedence::Unary => PREC_PREFIX,
|
||||||
|
|
||||||
// Unary, postfix
|
|
||||||
ExprPrecedence::Await
|
|
||||||
| ExprPrecedence::Call
|
|
||||||
| ExprPrecedence::MethodCall
|
|
||||||
| ExprPrecedence::Field
|
|
||||||
| ExprPrecedence::Index
|
|
||||||
| ExprPrecedence::Try
|
|
||||||
| ExprPrecedence::InlineAsm
|
|
||||||
| ExprPrecedence::Mac
|
|
||||||
| ExprPrecedence::FormatArgs
|
|
||||||
| ExprPrecedence::OffsetOf
|
|
||||||
| ExprPrecedence::PostfixMatch => PREC_POSTFIX,
|
|
||||||
|
|
||||||
// Never need parens
|
// Never need parens
|
||||||
ExprPrecedence::Array
|
ExprPrecedence::Array
|
||||||
| ExprPrecedence::Repeat
|
| ExprPrecedence::Await
|
||||||
| ExprPrecedence::Tup
|
|
||||||
| ExprPrecedence::Lit
|
|
||||||
| ExprPrecedence::Path
|
|
||||||
| ExprPrecedence::Paren
|
|
||||||
| ExprPrecedence::If
|
|
||||||
| ExprPrecedence::While
|
|
||||||
| ExprPrecedence::ForLoop
|
|
||||||
| ExprPrecedence::Loop
|
|
||||||
| ExprPrecedence::Match
|
|
||||||
| ExprPrecedence::ConstBlock
|
|
||||||
| ExprPrecedence::Block
|
| ExprPrecedence::Block
|
||||||
| ExprPrecedence::TryBlock
|
| ExprPrecedence::Call
|
||||||
|
| ExprPrecedence::ConstBlock
|
||||||
|
| ExprPrecedence::Field
|
||||||
|
| ExprPrecedence::ForLoop
|
||||||
|
| ExprPrecedence::FormatArgs
|
||||||
| ExprPrecedence::Gen
|
| ExprPrecedence::Gen
|
||||||
|
| ExprPrecedence::If
|
||||||
|
| ExprPrecedence::Index
|
||||||
|
| ExprPrecedence::InlineAsm
|
||||||
|
| ExprPrecedence::Lit
|
||||||
|
| ExprPrecedence::Loop
|
||||||
|
| ExprPrecedence::Mac
|
||||||
|
| ExprPrecedence::Match
|
||||||
|
| ExprPrecedence::MethodCall
|
||||||
|
| ExprPrecedence::OffsetOf
|
||||||
|
| ExprPrecedence::Paren
|
||||||
|
| ExprPrecedence::Path
|
||||||
|
| ExprPrecedence::PostfixMatch
|
||||||
|
| ExprPrecedence::Repeat
|
||||||
| ExprPrecedence::Struct
|
| ExprPrecedence::Struct
|
||||||
| ExprPrecedence::Err => PREC_PAREN,
|
| ExprPrecedence::Try
|
||||||
|
| ExprPrecedence::TryBlock
|
||||||
|
| ExprPrecedence::Tup
|
||||||
|
| ExprPrecedence::While
|
||||||
|
| ExprPrecedence::Err => PREC_UNAMBIGUOUS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,9 @@ ast_lowering_never_pattern_with_guard =
|
||||||
|
|
||||||
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
|
ast_lowering_no_precise_captures_on_apit = `use<...>` precise capturing syntax not allowed in argument-position `impl Trait`
|
||||||
|
|
||||||
|
ast_lowering_no_precise_captures_on_rpitit = `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
|
.note = currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
|
||||||
|
|
||||||
ast_lowering_previously_used_here = previously used here
|
ast_lowering_previously_used_here = previously used here
|
||||||
|
|
||||||
ast_lowering_register1 = register `{$reg1_name}`
|
ast_lowering_register1 = register `{$reg1_name}`
|
||||||
|
|
|
@ -424,6 +424,14 @@ pub(crate) struct NoPreciseCapturesOnApit {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(ast_lowering_no_precise_captures_on_rpitit)]
|
||||||
|
#[note]
|
||||||
|
pub(crate) struct NoPreciseCapturesOnRpitit {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_lowering_yield_in_closure)]
|
#[diag(ast_lowering_yield_in_closure)]
|
||||||
pub(crate) struct YieldInClosure {
|
pub(crate) struct YieldInClosure {
|
||||||
|
|
|
@ -1594,6 +1594,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
};
|
};
|
||||||
debug!(?captured_lifetimes_to_duplicate);
|
debug!(?captured_lifetimes_to_duplicate);
|
||||||
|
|
||||||
|
match fn_kind {
|
||||||
|
// Deny `use<>` on RPITIT in trait/trait-impl for now.
|
||||||
|
Some(FnDeclKind::Trait | FnDeclKind::Impl) => {
|
||||||
|
if let Some(span) = bounds.iter().find_map(|bound| match *bound {
|
||||||
|
ast::GenericBound::Use(_, span) => Some(span),
|
||||||
|
_ => None,
|
||||||
|
}) {
|
||||||
|
self.tcx.dcx().emit_err(errors::NoPreciseCapturesOnRpitit { span });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
| Some(
|
||||||
|
FnDeclKind::Fn
|
||||||
|
| FnDeclKind::Inherent
|
||||||
|
| FnDeclKind::ExternFn
|
||||||
|
| FnDeclKind::Closure
|
||||||
|
| FnDeclKind::Pointer,
|
||||||
|
) => {}
|
||||||
|
}
|
||||||
|
|
||||||
self.lower_opaque_inner(
|
self.lower_opaque_inner(
|
||||||
opaque_ty_node_id,
|
opaque_ty_node_id,
|
||||||
origin,
|
origin,
|
||||||
|
|
|
@ -217,7 +217,7 @@ impl<'a> State<'a> {
|
||||||
fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
|
fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
|
||||||
let prec = match func.kind {
|
let prec = match func.kind {
|
||||||
ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
|
ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
|
||||||
_ => parser::PREC_POSTFIX,
|
_ => parser::PREC_UNAMBIGUOUS,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Independent of parenthesization related to precedence, we must
|
// Independent of parenthesization related to precedence, we must
|
||||||
|
@ -257,7 +257,7 @@ impl<'a> State<'a> {
|
||||||
// boundaries, `$receiver.method()` can be parsed back as a statement
|
// boundaries, `$receiver.method()` can be parsed back as a statement
|
||||||
// containing an expression if and only if `$receiver` can be parsed as
|
// containing an expression if and only if `$receiver` can be parsed as
|
||||||
// a statement containing an expression.
|
// a statement containing an expression.
|
||||||
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS, fixup);
|
||||||
|
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(segment.ident);
|
self.print_ident(segment.ident);
|
||||||
|
@ -489,7 +489,7 @@ impl<'a> State<'a> {
|
||||||
self.space();
|
self.space();
|
||||||
}
|
}
|
||||||
MatchKind::Postfix => {
|
MatchKind::Postfix => {
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup);
|
||||||
self.word_nbsp(".match");
|
self.word_nbsp(".match");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,7 +549,7 @@ impl<'a> State<'a> {
|
||||||
self.print_block_with_attrs(blk, attrs);
|
self.print_block_with_attrs(blk, attrs);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Await(expr, _) => {
|
ast::ExprKind::Await(expr, _) => {
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup);
|
||||||
self.word(".await");
|
self.word(".await");
|
||||||
}
|
}
|
||||||
ast::ExprKind::Assign(lhs, rhs, _) => {
|
ast::ExprKind::Assign(lhs, rhs, _) => {
|
||||||
|
@ -568,14 +568,14 @@ impl<'a> State<'a> {
|
||||||
self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression());
|
self.print_expr_maybe_paren(rhs, prec, fixup.subsequent_subexpression());
|
||||||
}
|
}
|
||||||
ast::ExprKind::Field(expr, ident) => {
|
ast::ExprKind::Field(expr, ident) => {
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS, fixup);
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(*ident);
|
self.print_ident(*ident);
|
||||||
}
|
}
|
||||||
ast::ExprKind::Index(expr, index, _) => {
|
ast::ExprKind::Index(expr, index, _) => {
|
||||||
self.print_expr_maybe_paren(
|
self.print_expr_maybe_paren(
|
||||||
expr,
|
expr,
|
||||||
parser::PREC_POSTFIX,
|
parser::PREC_UNAMBIGUOUS,
|
||||||
fixup.leftmost_subexpression(),
|
fixup.leftmost_subexpression(),
|
||||||
);
|
);
|
||||||
self.word("[");
|
self.word("[");
|
||||||
|
@ -713,7 +713,7 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprKind::Try(e) => {
|
ast::ExprKind::Try(e) => {
|
||||||
self.print_expr_maybe_paren(e, parser::PREC_POSTFIX, fixup);
|
self.print_expr_maybe_paren(e, parser::PREC_UNAMBIGUOUS, fixup);
|
||||||
self.word("?")
|
self.word("?")
|
||||||
}
|
}
|
||||||
ast::ExprKind::TryBlock(blk) => {
|
ast::ExprKind::TryBlock(blk) => {
|
||||||
|
|
|
@ -1151,7 +1151,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||||
// Get the arguments for the found method, only specifying that `Self` is the receiver type.
|
// Get the arguments for the found method, only specifying that `Self` is the receiver type.
|
||||||
let Some(possible_rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id) else { return };
|
let Some(possible_rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id) else { return };
|
||||||
let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
|
let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
|
||||||
if param.index == 0 {
|
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||||
|
tcx.lifetimes.re_erased.into()
|
||||||
|
} else if param.index == 0 && param.name == kw::SelfUpper {
|
||||||
possible_rcvr_ty.into()
|
possible_rcvr_ty.into()
|
||||||
} else if param.index == closure_param.index {
|
} else if param.index == closure_param.index {
|
||||||
closure_ty.into()
|
closure_ty.into()
|
||||||
|
@ -1168,7 +1170,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||||
Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred)
|
Obligation::misc(tcx, span, self.mir_def_id(), self.param_env, pred)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if ocx.select_all_or_error().is_empty() {
|
if ocx.select_all_or_error().is_empty() && count > 0 {
|
||||||
diag.span_suggestion_verbose(
|
diag.span_suggestion_verbose(
|
||||||
tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
|
tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
|
||||||
"dereference the return value",
|
"dereference the return value",
|
||||||
|
|
|
@ -1490,11 +1490,6 @@ fn print_native_static_libs(
|
||||||
let mut lib_args: Vec<_> = all_native_libs
|
let mut lib_args: Vec<_> = all_native_libs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|l| relevant_lib(sess, l))
|
.filter(|l| relevant_lib(sess, l))
|
||||||
// Deduplication of successive repeated libraries, see rust-lang/rust#113209
|
|
||||||
//
|
|
||||||
// note: we don't use PartialEq/Eq because NativeLib transitively depends on local
|
|
||||||
// elements like spans, which we don't care about and would make the deduplication impossible
|
|
||||||
.dedup_by(|l1, l2| l1.name == l2.name && l1.kind == l2.kind && l1.verbatim == l2.verbatim)
|
|
||||||
.filter_map(|lib| {
|
.filter_map(|lib| {
|
||||||
let name = lib.name;
|
let name = lib.name;
|
||||||
match lib.kind {
|
match lib.kind {
|
||||||
|
@ -1521,6 +1516,8 @@ fn print_native_static_libs(
|
||||||
| NativeLibKind::RawDylib => None,
|
| NativeLibKind::RawDylib => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// deduplication of consecutive repeated libraries, see rust-lang/rust#113209
|
||||||
|
.dedup()
|
||||||
.collect();
|
.collect();
|
||||||
for path in all_rust_dylibs {
|
for path in all_rust_dylibs {
|
||||||
// FIXME deduplicate with add_dynamic_crate
|
// FIXME deduplicate with add_dynamic_crate
|
||||||
|
|
|
@ -211,11 +211,18 @@ fn missing_items_err(
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("`, `");
|
.join("`, `");
|
||||||
|
|
||||||
// `Span` before impl block closing brace.
|
let sugg_sp = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(full_impl_span)
|
||||||
let hi = full_impl_span.hi() - BytePos(1);
|
&& snippet.ends_with("}")
|
||||||
// Point at the place right before the closing brace of the relevant `impl` to suggest
|
{
|
||||||
// adding the associated item at the end of its body.
|
// `Span` before impl block closing brace.
|
||||||
let sugg_sp = full_impl_span.with_lo(hi).with_hi(hi);
|
let hi = full_impl_span.hi() - BytePos(1);
|
||||||
|
// Point at the place right before the closing brace of the relevant `impl` to suggest
|
||||||
|
// adding the associated item at the end of its body.
|
||||||
|
full_impl_span.with_lo(hi).with_hi(hi)
|
||||||
|
} else {
|
||||||
|
full_impl_span.shrink_to_hi()
|
||||||
|
};
|
||||||
|
|
||||||
// Obtain the level of indentation ending in `sugg_sp`.
|
// Obtain the level of indentation ending in `sugg_sp`.
|
||||||
let padding =
|
let padding =
|
||||||
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
|
tcx.sess.source_map().indentation_before(sugg_sp).unwrap_or_else(|| String::new());
|
||||||
|
|
|
@ -1120,7 +1120,7 @@ impl<'a> State<'a> {
|
||||||
fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
|
fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
|
||||||
let prec = match func.kind {
|
let prec = match func.kind {
|
||||||
hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
|
hir::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
|
||||||
_ => parser::PREC_POSTFIX,
|
_ => parser::PREC_UNAMBIGUOUS,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.print_expr_maybe_paren(func, prec);
|
self.print_expr_maybe_paren(func, prec);
|
||||||
|
@ -1134,7 +1134,7 @@ impl<'a> State<'a> {
|
||||||
args: &[hir::Expr<'_>],
|
args: &[hir::Expr<'_>],
|
||||||
) {
|
) {
|
||||||
let base_args = args;
|
let base_args = args;
|
||||||
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
|
self.print_expr_maybe_paren(receiver, parser::PREC_UNAMBIGUOUS);
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(segment.ident);
|
self.print_ident(segment.ident);
|
||||||
|
|
||||||
|
@ -1478,12 +1478,12 @@ impl<'a> State<'a> {
|
||||||
self.print_expr_maybe_paren(rhs, prec);
|
self.print_expr_maybe_paren(rhs, prec);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Field(expr, ident) => {
|
hir::ExprKind::Field(expr, ident) => {
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
|
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS);
|
||||||
self.word(".");
|
self.word(".");
|
||||||
self.print_ident(ident);
|
self.print_ident(ident);
|
||||||
}
|
}
|
||||||
hir::ExprKind::Index(expr, index, _) => {
|
hir::ExprKind::Index(expr, index, _) => {
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
|
self.print_expr_maybe_paren(expr, parser::PREC_UNAMBIGUOUS);
|
||||||
self.word("[");
|
self.word("[");
|
||||||
self.print_expr(index);
|
self.print_expr(index);
|
||||||
self.word("]");
|
self.word("]");
|
||||||
|
|
|
@ -3,7 +3,7 @@ use super::method::MethodCallee;
|
||||||
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
|
||||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
|
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
|
||||||
use rustc_hir::def::{self, CtorKind, Namespace, Res};
|
use rustc_hir::def::{self, CtorKind, Namespace, Res};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -656,7 +656,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(rest_snippet) = rest_snippet {
|
if let Ok(rest_snippet) = rest_snippet {
|
||||||
let sugg = if callee_expr.precedence().order() >= PREC_POSTFIX {
|
let sugg = if callee_expr.precedence().order() >= PREC_UNAMBIGUOUS {
|
||||||
vec![
|
vec![
|
||||||
(up_to_rcvr_span, "".to_string()),
|
(up_to_rcvr_span, "".to_string()),
|
||||||
(rest_span, format!(".{}({rest_snippet}", segment.ident)),
|
(rest_span, format!(".{}({rest_snippet}", segment.ident)),
|
||||||
|
|
|
@ -946,7 +946,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
|
|
||||||
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
|
fn lossy_provenance_ptr2int_lint(&self, fcx: &FnCtxt<'a, 'tcx>, t_c: ty::cast::IntTy) {
|
||||||
let expr_prec = self.expr.precedence().order();
|
let expr_prec = self.expr.precedence().order();
|
||||||
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_POSTFIX;
|
let needs_parens = expr_prec < rustc_ast::util::parser::PREC_UNAMBIGUOUS;
|
||||||
|
|
||||||
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
|
let needs_cast = !matches!(t_c, ty::cast::IntTy::U(ty::UintTy::Usize));
|
||||||
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
|
let cast_span = self.expr_span.shrink_to_hi().to(self.cast_span);
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope};
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
use core::iter;
|
use core::iter;
|
||||||
use hir::def_id::LocalDefId;
|
use hir::def_id::LocalDefId;
|
||||||
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
|
use rustc_ast::util::parser::{ExprPrecedence, PREC_UNAMBIGUOUS};
|
||||||
use rustc_data_structures::packed::Pu128;
|
use rustc_data_structures::packed::Pu128;
|
||||||
use rustc_errors::{Applicability, Diag, MultiSpan};
|
use rustc_errors::{Applicability, Diag, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -1329,7 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
let span = expr.span.find_oldest_ancestor_in_same_ctxt();
|
||||||
|
|
||||||
let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
|
let mut sugg = if expr.precedence().order() >= PREC_UNAMBIGUOUS {
|
||||||
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
vec![(span.shrink_to_hi(), ".into()".to_owned())]
|
||||||
} else {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
|
@ -2868,7 +2868,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
"change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
|
"change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`",
|
||||||
);
|
);
|
||||||
|
|
||||||
let close_paren = if expr.precedence().order() < PREC_POSTFIX {
|
let close_paren = if expr.precedence().order() < PREC_UNAMBIGUOUS {
|
||||||
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
||||||
")"
|
")"
|
||||||
} else {
|
} else {
|
||||||
|
@ -2893,7 +2893,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let len = src.trim_end_matches(&checked_ty.to_string()).len();
|
let len = src.trim_end_matches(&checked_ty.to_string()).len();
|
||||||
expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
|
expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
|
||||||
},
|
},
|
||||||
if expr.precedence().order() < PREC_POSTFIX {
|
if expr.precedence().order() < PREC_UNAMBIGUOUS {
|
||||||
// Readd `)`
|
// Readd `)`
|
||||||
format!("{expected_ty})")
|
format!("{expected_ty})")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -209,8 +209,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
|
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
|
||||||
{
|
{
|
||||||
ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
|
ObligationCauseCode::Pattern { span: Some(then_span), origin_expr, .. } => {
|
||||||
Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
|
origin_expr.then_some(ConsiderAddingAwait::FutureSugg {
|
||||||
|
span: then_span.shrink_to_hi(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
|
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
|
||||||
let then_span = self.find_block_span_from_hir_id(*then_id);
|
let then_span = self.find_block_span_from_hir_id(*then_id);
|
||||||
|
|
|
@ -155,7 +155,10 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
|
|
||||||
fn handle_res(&mut self, res: Res) {
|
fn handle_res(&mut self, res: Res) {
|
||||||
match res {
|
match res {
|
||||||
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
|
Res::Def(
|
||||||
|
DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias,
|
||||||
|
def_id,
|
||||||
|
) => {
|
||||||
self.check_def_id(def_id);
|
self.check_def_id(def_id);
|
||||||
}
|
}
|
||||||
_ if self.in_pat => {}
|
_ if self.in_pat => {}
|
||||||
|
@ -466,7 +469,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
intravisit::walk_item(self, item)
|
intravisit::walk_item(self, item)
|
||||||
}
|
}
|
||||||
hir::ItemKind::ForeignMod { .. } => {}
|
hir::ItemKind::ForeignMod { .. } => {}
|
||||||
hir::ItemKind::Trait(..) => {
|
hir::ItemKind::Trait(_, _, _, _, trait_item_refs) => {
|
||||||
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
|
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
|
||||||
if let Some(local_def_id) = impl_def_id.as_local()
|
if let Some(local_def_id) = impl_def_id.as_local()
|
||||||
&& let ItemKind::Impl(impl_ref) =
|
&& let ItemKind::Impl(impl_ref) =
|
||||||
|
@ -479,7 +482,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
|
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// mark assoc ty live if the trait is live
|
||||||
|
for trait_item in trait_item_refs {
|
||||||
|
if let hir::AssocItemKind::Type = trait_item.kind {
|
||||||
|
self.check_def_id(trait_item.id.owner_id.to_def_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
intravisit::walk_item(self, item)
|
intravisit::walk_item(self, item)
|
||||||
}
|
}
|
||||||
_ => intravisit::walk_item(self, item),
|
_ => intravisit::walk_item(self, item),
|
||||||
|
@ -496,9 +504,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
&& let ItemKind::Impl(impl_ref) =
|
&& let ItemKind::Impl(impl_ref) =
|
||||||
self.tcx.hir().expect_item(local_impl_id).kind
|
self.tcx.hir().expect_item(local_impl_id).kind
|
||||||
{
|
{
|
||||||
if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
|
if !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
|
||||||
&& !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
|
.ty_and_all_fields_are_public
|
||||||
.ty_and_all_fields_are_public
|
|
||||||
{
|
{
|
||||||
// skip impl-items of non pure pub ty,
|
// skip impl-items of non pure pub ty,
|
||||||
// cause we don't know the ty is constructed or not,
|
// cause we don't know the ty is constructed or not,
|
||||||
|
@ -837,9 +844,8 @@ fn check_item<'tcx>(
|
||||||
// for trait impl blocks,
|
// for trait impl blocks,
|
||||||
// mark the method live if the self_ty is public,
|
// mark the method live if the self_ty is public,
|
||||||
// or the method is public and may construct self
|
// or the method is public and may construct self
|
||||||
if of_trait && matches!(tcx.def_kind(local_def_id), DefKind::AssocTy)
|
if tcx.visibility(local_def_id).is_public()
|
||||||
|| tcx.visibility(local_def_id).is_public()
|
&& (ty_and_all_fields_are_public || may_construct_self)
|
||||||
&& (ty_and_all_fields_are_public || may_construct_self)
|
|
||||||
{
|
{
|
||||||
// if the impl item is public,
|
// if the impl item is public,
|
||||||
// and the ty may be constructed or can be constructed in foreign crates,
|
// and the ty may be constructed or can be constructed in foreign crates,
|
||||||
|
@ -876,10 +882,13 @@ fn check_trait_item(
|
||||||
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
|
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
|
||||||
id: hir::TraitItemId,
|
id: hir::TraitItemId,
|
||||||
) {
|
) {
|
||||||
use hir::TraitItemKind::{Const, Fn};
|
use hir::TraitItemKind::{Const, Fn, Type};
|
||||||
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
|
if matches!(
|
||||||
|
tcx.def_kind(id.owner_id),
|
||||||
|
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn
|
||||||
|
) {
|
||||||
let trait_item = tcx.hir().trait_item(id);
|
let trait_item = tcx.hir().trait_item(id);
|
||||||
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
|
if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..))
|
||||||
&& let Some(comes_from_allow) =
|
&& let Some(comes_from_allow) =
|
||||||
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
|
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
|
||||||
{
|
{
|
||||||
|
@ -921,7 +930,7 @@ fn create_and_seed_worklist(
|
||||||
// checks impls, impl-items and pub structs with all public fields later
|
// checks impls, impl-items and pub structs with all public fields later
|
||||||
match tcx.def_kind(id) {
|
match tcx.def_kind(id) {
|
||||||
DefKind::Impl { .. } => false,
|
DefKind::Impl { .. } => false,
|
||||||
DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
|
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
|
||||||
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
|
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
|
||||||
_ => true
|
_ => true
|
||||||
})
|
})
|
||||||
|
@ -1208,6 +1217,7 @@ impl<'tcx> DeadVisitor<'tcx> {
|
||||||
}
|
}
|
||||||
match self.tcx.def_kind(def_id) {
|
match self.tcx.def_kind(def_id) {
|
||||||
DefKind::AssocConst
|
DefKind::AssocConst
|
||||||
|
| DefKind::AssocTy
|
||||||
| DefKind::AssocFn
|
| DefKind::AssocFn
|
||||||
| DefKind::Fn
|
| DefKind::Fn
|
||||||
| DefKind::Static { .. }
|
| DefKind::Static { .. }
|
||||||
|
@ -1249,15 +1259,14 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
|
||||||
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
|
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
|
||||||
{
|
{
|
||||||
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
|
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
|
||||||
// We have diagnosed unused assoc consts and fns in traits
|
// We have diagnosed unused assocs in traits
|
||||||
if matches!(def_kind, DefKind::Impl { of_trait: true })
|
if matches!(def_kind, DefKind::Impl { of_trait: true })
|
||||||
&& matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocFn)
|
&& matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn)
|
||||||
// skip unused public inherent methods,
|
// skip unused public inherent methods,
|
||||||
// cause we have diagnosed unconstructed struct
|
// cause we have diagnosed unconstructed struct
|
||||||
|| matches!(def_kind, DefKind::Impl { of_trait: false })
|
|| matches!(def_kind, DefKind::Impl { of_trait: false })
|
||||||
&& tcx.visibility(def_id).is_public()
|
&& tcx.visibility(def_id).is_public()
|
||||||
&& ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public
|
&& ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public
|
||||||
|| def_kind == DefKind::Trait && tcx.def_kind(def_id) == DefKind::AssocTy
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use clippy_utils::{
|
||||||
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode,
|
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode,
|
||||||
};
|
};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
|
use rustc_ast::util::parser::{PREC_UNAMBIGUOUS, PREC_PREFIX};
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::{walk_ty, Visitor};
|
use rustc_hir::intravisit::{walk_ty, Visitor};
|
||||||
|
@ -1013,7 +1013,7 @@ fn report<'tcx>(
|
||||||
let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
|
let (precedence, calls_field) = match cx.tcx.parent_hir_node(data.first_expr.hir_id) {
|
||||||
Node::Expr(e) => match e.kind {
|
Node::Expr(e) => match e.kind {
|
||||||
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
|
ExprKind::Call(callee, _) if callee.hir_id != data.first_expr.hir_id => (0, false),
|
||||||
ExprKind::Call(..) => (PREC_POSTFIX, matches!(expr.kind, ExprKind::Field(..))),
|
ExprKind::Call(..) => (PREC_UNAMBIGUOUS, matches!(expr.kind, ExprKind::Field(..))),
|
||||||
_ => (e.precedence().order(), false),
|
_ => (e.precedence().order(), false),
|
||||||
},
|
},
|
||||||
_ => (0, false),
|
_ => (0, false),
|
||||||
|
@ -1160,7 +1160,7 @@ impl<'tcx> Dereferencing<'tcx> {
|
||||||
},
|
},
|
||||||
Some(parent) if !parent.span.from_expansion() => {
|
Some(parent) if !parent.span.from_expansion() => {
|
||||||
// Double reference might be needed at this point.
|
// Double reference might be needed at this point.
|
||||||
if parent.precedence().order() == PREC_POSTFIX {
|
if parent.precedence().order() == PREC_UNAMBIGUOUS {
|
||||||
// Parentheses would be needed here, don't lint.
|
// Parentheses would be needed here, don't lint.
|
||||||
*outer_pat = None;
|
*outer_pat = None;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use clippy_utils::{
|
||||||
can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
|
can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
|
||||||
peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
|
peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
|
||||||
};
|
};
|
||||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
use rustc_ast::util::parser::PREC_UNAMBIGUOUS;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||||
|
@ -117,7 +117,7 @@ where
|
||||||
// it's being passed by value.
|
// it's being passed by value.
|
||||||
let scrutinee = peel_hir_expr_refs(scrutinee).0;
|
let scrutinee = peel_hir_expr_refs(scrutinee).0;
|
||||||
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
|
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
|
||||||
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_POSTFIX {
|
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_UNAMBIGUOUS {
|
||||||
format!("({scrutinee_str})")
|
format!("({scrutinee_str})")
|
||||||
} else {
|
} else {
|
||||||
scrutinee_str.into()
|
scrutinee_str.into()
|
||||||
|
|
|
@ -17,3 +17,9 @@ extern "C" {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn g_free2(p: *mut ());
|
fn g_free2(p: *mut ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[link(name = "glib-2.0", kind = "raw-dylib")]
|
||||||
|
extern "C" {
|
||||||
|
fn g_free3(p: *mut ());
|
||||||
|
}
|
||||||
|
|
|
@ -71,4 +71,11 @@ async fn suggest_await_in_generic_pattern() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #126903
|
||||||
|
async fn do_async() {}
|
||||||
|
fn dont_suggest_awaiting_closure_patterns() {
|
||||||
|
Some(do_async()).map(|()| {});
|
||||||
|
//~^ ERROR mismatched types [E0308]
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -133,6 +133,18 @@ help: consider `await`ing on the `Future`
|
||||||
LL | match dummy_result().await {
|
LL | match dummy_result().await {
|
||||||
| ++++++
|
| ++++++
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/suggest-missing-await.rs:77:27
|
||||||
|
|
|
||||||
|
LL | Some(do_async()).map(|()| {});
|
||||||
|
| ^^
|
||||||
|
| |
|
||||||
|
| expected future, found `()`
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected opaque type `impl Future<Output = ()>`
|
||||||
|
found unit type `()`
|
||||||
|
|
||||||
|
error: aborting due to 8 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -11,6 +11,7 @@ async fn foo() {
|
||||||
async_in_foo(async_out_foo::<4>().await).await;
|
async_in_foo(async_out_foo::<4>().await).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct Faz<const N: usize>;
|
struct Faz<const N: usize>;
|
||||||
|
|
||||||
impl<const N: usize> Foo<N> for Faz<N> {}
|
impl<const N: usize> Foo<N> for Faz<N> {}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct A<B>(B);
|
struct A<B>(B);
|
||||||
|
|
||||||
impl<B> Add for A<B> where B: Add<Output = B> {
|
impl<B> Add for A<B> where B: Add<Output = B> {
|
||||||
|
@ -12,6 +13,7 @@ impl<B> Add for A<B> where B: Add<Output = B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct C<B>(B);
|
struct C<B>(B);
|
||||||
|
|
||||||
impl<B: Add<Output = B>> Add for C<B> {
|
impl<B: Add<Output = B>> Add for C<B> {
|
||||||
|
@ -22,6 +24,7 @@ impl<B: Add<Output = B>> Add for C<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct D<B>(B);
|
struct D<B>(B);
|
||||||
|
|
||||||
impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
||||||
|
@ -32,6 +35,7 @@ impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct E<B>(B);
|
struct E<B>(B);
|
||||||
|
|
||||||
impl<B: Add<Output = B>> Add for E<B> where B: Add<Output = B> {
|
impl<B: Add<Output = B>> Add for E<B> where B: Add<Output = B> {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct A<B>(B);
|
struct A<B>(B);
|
||||||
|
|
||||||
impl<B> Add for A<B> where B: Add {
|
impl<B> Add for A<B> where B: Add {
|
||||||
|
@ -12,6 +13,7 @@ impl<B> Add for A<B> where B: Add {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct C<B>(B);
|
struct C<B>(B);
|
||||||
|
|
||||||
impl<B: Add> Add for C<B> {
|
impl<B: Add> Add for C<B> {
|
||||||
|
@ -22,6 +24,7 @@ impl<B: Add> Add for C<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct D<B>(B);
|
struct D<B>(B);
|
||||||
|
|
||||||
impl<B> Add for D<B> {
|
impl<B> Add for D<B> {
|
||||||
|
@ -32,6 +35,7 @@ impl<B> Add for D<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
struct E<B>(B);
|
struct E<B>(B);
|
||||||
|
|
||||||
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: equality constraints are not yet supported in `where` clauses
|
error: equality constraints are not yet supported in `where` clauses
|
||||||
--> $DIR/missing-bounds.rs:37:33
|
--> $DIR/missing-bounds.rs:41:33
|
||||||
|
|
|
|
||||||
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
|
| ^^^^^^^^^^^^^^^^^^^^^^ not supported
|
||||||
|
@ -11,7 +11,7 @@ LL | impl<B: Add> Add for E<B> where B: Add<Output = B> {
|
||||||
| ~~~~~~~~~~~~~~~~~~
|
| ~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/missing-bounds.rs:11:11
|
--> $DIR/missing-bounds.rs:12:11
|
||||||
|
|
|
|
||||||
LL | impl<B> Add for A<B> where B: Add {
|
LL | impl<B> Add for A<B> where B: Add {
|
||||||
| - expected this type parameter
|
| - expected this type parameter
|
||||||
|
@ -24,14 +24,14 @@ LL | A(self.0 + rhs.0)
|
||||||
= note: expected type parameter `B`
|
= note: expected type parameter `B`
|
||||||
found associated type `<B as Add>::Output`
|
found associated type `<B as Add>::Output`
|
||||||
help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
|
help: the type constructed contains `<B as Add>::Output` due to the type of the argument passed
|
||||||
--> $DIR/missing-bounds.rs:11:9
|
--> $DIR/missing-bounds.rs:12:9
|
||||||
|
|
|
|
||||||
LL | A(self.0 + rhs.0)
|
LL | A(self.0 + rhs.0)
|
||||||
| ^^--------------^
|
| ^^--------------^
|
||||||
| |
|
| |
|
||||||
| this argument influences the type of `A`
|
| this argument influences the type of `A`
|
||||||
note: tuple struct defined here
|
note: tuple struct defined here
|
||||||
--> $DIR/missing-bounds.rs:5:8
|
--> $DIR/missing-bounds.rs:6:8
|
||||||
|
|
|
|
||||||
LL | struct A<B>(B);
|
LL | struct A<B>(B);
|
||||||
| ^
|
| ^
|
||||||
|
@ -41,7 +41,7 @@ LL | impl<B> Add for A<B> where B: Add<Output = B> {
|
||||||
| ++++++++++++
|
| ++++++++++++
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/missing-bounds.rs:21:14
|
--> $DIR/missing-bounds.rs:23:14
|
||||||
|
|
|
|
||||||
LL | impl<B: Add> Add for C<B> {
|
LL | impl<B: Add> Add for C<B> {
|
||||||
| - expected this type parameter
|
| - expected this type parameter
|
||||||
|
@ -54,7 +54,7 @@ LL | Self(self.0 + rhs.0)
|
||||||
= note: expected type parameter `B`
|
= note: expected type parameter `B`
|
||||||
found associated type `<B as Add>::Output`
|
found associated type `<B as Add>::Output`
|
||||||
note: tuple struct defined here
|
note: tuple struct defined here
|
||||||
--> $DIR/missing-bounds.rs:15:8
|
--> $DIR/missing-bounds.rs:17:8
|
||||||
|
|
|
|
||||||
LL | struct C<B>(B);
|
LL | struct C<B>(B);
|
||||||
| ^
|
| ^
|
||||||
|
@ -64,7 +64,7 @@ LL | impl<B: Add<Output = B>> Add for C<B> {
|
||||||
| ++++++++++++
|
| ++++++++++++
|
||||||
|
|
||||||
error[E0369]: cannot add `B` to `B`
|
error[E0369]: cannot add `B` to `B`
|
||||||
--> $DIR/missing-bounds.rs:31:21
|
--> $DIR/missing-bounds.rs:34:21
|
||||||
|
|
|
|
||||||
LL | Self(self.0 + rhs.0)
|
LL | Self(self.0 + rhs.0)
|
||||||
| ------ ^ ----- B
|
| ------ ^ ----- B
|
||||||
|
@ -77,7 +77,7 @@ LL | impl<B: std::ops::Add<Output = B>> Add for D<B> {
|
||||||
| +++++++++++++++++++++++++++
|
| +++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/missing-bounds.rs:42:14
|
--> $DIR/missing-bounds.rs:46:14
|
||||||
|
|
|
|
||||||
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
LL | impl<B: Add> Add for E<B> where <B as Add>::Output = B {
|
||||||
| - expected this type parameter
|
| - expected this type parameter
|
||||||
|
@ -90,7 +90,7 @@ LL | Self(self.0 + rhs.0)
|
||||||
= note: expected type parameter `B`
|
= note: expected type parameter `B`
|
||||||
found associated type `<B as Add>::Output`
|
found associated type `<B as Add>::Output`
|
||||||
note: tuple struct defined here
|
note: tuple struct defined here
|
||||||
--> $DIR/missing-bounds.rs:35:8
|
--> $DIR/missing-bounds.rs:39:8
|
||||||
|
|
|
|
||||||
LL | struct E<B>(B);
|
LL | struct E<B>(B);
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -6,6 +6,7 @@ fn type_param<T>() -> impl Sized + use<> {}
|
||||||
trait Foo {
|
trait Foo {
|
||||||
fn bar() -> impl Sized + use<>;
|
fn bar() -> impl Sized + use<>;
|
||||||
//~^ ERROR `impl Trait` must mention the `Self` type of the trait
|
//~^ ERROR `impl Trait` must mention the `Self` type of the trait
|
||||||
|
//~| ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
|
--> $DIR/forgot-to-capture-type.rs:7:30
|
||||||
|
|
|
||||||
|
LL | fn bar() -> impl Sized + use<>;
|
||||||
|
| ^^^^^
|
||||||
|
|
|
||||||
|
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
|
||||||
|
|
||||||
error: `impl Trait` must mention all type parameters in scope in `use<...>`
|
error: `impl Trait` must mention all type parameters in scope in `use<...>`
|
||||||
--> $DIR/forgot-to-capture-type.rs:3:23
|
--> $DIR/forgot-to-capture-type.rs:3:23
|
||||||
|
|
|
|
||||||
|
@ -18,5 +26,5 @@ LL | fn bar() -> impl Sized + use<>;
|
||||||
|
|
|
|
||||||
= note: currently, all type parameters are required to be mentioned in the precise captures list
|
= note: currently, all type parameters are required to be mentioned in the precise captures list
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
|
||||||
|
--> $DIR/redundant.rs:7:19
|
||||||
|
|
|
||||||
|
LL | fn hello<'a>() -> impl Sized + use<'a> {}
|
||||||
|
| ^^^^^^^^^^^^^-------
|
||||||
|
| |
|
||||||
|
| help: remove the `use<...>` syntax
|
||||||
|
|
|
||||||
|
= note: `#[warn(impl_trait_redundant_captures)]` on by default
|
||||||
|
|
||||||
|
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
|
||||||
|
--> $DIR/redundant.rs:12:27
|
||||||
|
|
|
||||||
|
LL | fn inherent(&self) -> impl Sized + use<'_> {}
|
||||||
|
| ^^^^^^^^^^^^^-------
|
||||||
|
| |
|
||||||
|
| help: remove the `use<...>` syntax
|
||||||
|
|
||||||
|
warning: 2 warnings emitted
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
|
--> $DIR/redundant.rs:18:35
|
||||||
|
|
|
||||||
|
LL | fn in_trait() -> impl Sized + use<'a, Self>;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
|
||||||
|
|
||||||
|
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
|
--> $DIR/redundant.rs:23:35
|
||||||
|
|
|
||||||
|
LL | fn in_trait() -> impl Sized + use<'a> {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
|
||||||
|
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,24 +1,27 @@
|
||||||
//@ compile-flags: -Zunstable-options --edition=2024
|
//@ compile-flags: -Zunstable-options --edition=2024
|
||||||
//@ check-pass
|
//@ revisions: normal rpitit
|
||||||
|
//@[normal] check-pass
|
||||||
|
|
||||||
#![feature(precise_capturing)]
|
#![feature(precise_capturing)]
|
||||||
|
|
||||||
fn hello<'a>() -> impl Sized + use<'a> {}
|
fn hello<'a>() -> impl Sized + use<'a> {}
|
||||||
//~^ WARN all possible in-scope parameters are already captured
|
//[normal]~^ WARN all possible in-scope parameters are already captured
|
||||||
|
|
||||||
struct Inherent;
|
struct Inherent;
|
||||||
impl Inherent {
|
impl Inherent {
|
||||||
fn inherent(&self) -> impl Sized + use<'_> {}
|
fn inherent(&self) -> impl Sized + use<'_> {}
|
||||||
//~^ WARN all possible in-scope parameters are already captured
|
//[normal]~^ WARN all possible in-scope parameters are already captured
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(rpitit)]
|
||||||
trait Test<'a> {
|
trait Test<'a> {
|
||||||
fn in_trait() -> impl Sized + use<'a, Self>;
|
fn in_trait() -> impl Sized + use<'a, Self>;
|
||||||
//~^ WARN all possible in-scope parameters are already captured
|
//[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
}
|
}
|
||||||
|
#[cfg(rpitit)]
|
||||||
impl<'a> Test<'a> for () {
|
impl<'a> Test<'a> for () {
|
||||||
fn in_trait() -> impl Sized + use<'a> {}
|
fn in_trait() -> impl Sized + use<'a> {}
|
||||||
//~^ WARN all possible in-scope parameters are already captured
|
//[rpitit]~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
|
|
||||||
--> $DIR/redundant.rs:6:19
|
|
||||||
|
|
|
||||||
LL | fn hello<'a>() -> impl Sized + use<'a> {}
|
|
||||||
| ^^^^^^^^^^^^^-------
|
|
||||||
| |
|
|
||||||
| help: remove the `use<...>` syntax
|
|
||||||
|
|
|
||||||
= note: `#[warn(impl_trait_redundant_captures)]` on by default
|
|
||||||
|
|
||||||
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
|
|
||||||
--> $DIR/redundant.rs:11:27
|
|
||||||
|
|
|
||||||
LL | fn inherent(&self) -> impl Sized + use<'_> {}
|
|
||||||
| ^^^^^^^^^^^^^-------
|
|
||||||
| |
|
|
||||||
| help: remove the `use<...>` syntax
|
|
||||||
|
|
||||||
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
|
|
||||||
--> $DIR/redundant.rs:16:22
|
|
||||||
|
|
|
||||||
LL | fn in_trait() -> impl Sized + use<'a, Self>;
|
|
||||||
| ^^^^^^^^^^^^^-------------
|
|
||||||
| |
|
|
||||||
| help: remove the `use<...>` syntax
|
|
||||||
|
|
||||||
warning: all possible in-scope parameters are already captured, so `use<...>` syntax is redundant
|
|
||||||
--> $DIR/redundant.rs:20:22
|
|
||||||
|
|
|
||||||
LL | fn in_trait() -> impl Sized + use<'a> {}
|
|
||||||
| ^^^^^^^^^^^^^-------
|
|
||||||
| |
|
|
||||||
| help: remove the `use<...>` syntax
|
|
||||||
|
|
||||||
warning: 4 warnings emitted
|
|
||||||
|
|
21
tests/ui/impl-trait/precise-capturing/rpitit.rs
Normal file
21
tests/ui/impl-trait/precise-capturing/rpitit.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
//@ known-bug: unknown
|
||||||
|
|
||||||
|
// RPITITs don't have variances in their GATs, so they always relate invariantly
|
||||||
|
// and act as if they capture all their args.
|
||||||
|
// To fix this soundly, we need to make sure that all the trait header args
|
||||||
|
// remain captured, since they affect trait selection.
|
||||||
|
|
||||||
|
#![feature(precise_capturing)]
|
||||||
|
|
||||||
|
trait Foo<'a> {
|
||||||
|
fn hello() -> impl PartialEq + use<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test<'a, 'b, T: for<'r> Foo<'r>>() {
|
||||||
|
PartialEq::eq(
|
||||||
|
&<T as Foo<'a>>::hello(),
|
||||||
|
&<T as Foo<'b>>::hello(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
50
tests/ui/impl-trait/precise-capturing/rpitit.stderr
Normal file
50
tests/ui/impl-trait/precise-capturing/rpitit.stderr
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
|
--> $DIR/rpitit.rs:11:36
|
||||||
|
|
|
||||||
|
LL | fn hello() -> impl PartialEq + use<Self>;
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
|
||||||
|
|
||||||
|
error: `impl Trait` captures lifetime parameter, but it is not mentioned in `use<...>` precise captures list
|
||||||
|
--> $DIR/rpitit.rs:11:19
|
||||||
|
|
|
||||||
|
LL | trait Foo<'a> {
|
||||||
|
| -- this lifetime parameter is captured
|
||||||
|
LL | fn hello() -> impl PartialEq + use<Self>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime captured due to being mentioned in the bounds of the `impl Trait`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/rpitit.rs:15:5
|
||||||
|
|
|
||||||
|
LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | / PartialEq::eq(
|
||||||
|
LL | | &<T as Foo<'a>>::hello(),
|
||||||
|
LL | | &<T as Foo<'b>>::hello(),
|
||||||
|
LL | | );
|
||||||
|
| |_____^ argument requires that `'a` must outlive `'b`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'a: 'b`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/rpitit.rs:15:5
|
||||||
|
|
|
||||||
|
LL | fn test<'a, 'b, T: for<'r> Foo<'r>>() {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | / PartialEq::eq(
|
||||||
|
LL | | &<T as Foo<'a>>::hello(),
|
||||||
|
LL | | &<T as Foo<'b>>::hello(),
|
||||||
|
LL | | );
|
||||||
|
| |_____^ argument requires that `'b` must outlive `'a`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
|
|
||||||
|
help: `'a` and `'b` must be the same: replace one with the other
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
//@ check-pass
|
|
||||||
|
|
||||||
#![feature(precise_capturing)]
|
#![feature(precise_capturing)]
|
||||||
|
|
||||||
trait Foo {
|
trait Foo {
|
||||||
fn bar<'a>() -> impl Sized + use<Self>;
|
fn bar<'a>() -> impl Sized + use<Self>;
|
||||||
|
//~^ ERROR `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
10
tests/ui/impl-trait/precise-capturing/self-capture.stderr
Normal file
10
tests/ui/impl-trait/precise-capturing/self-capture.stderr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
error: `use<...>` precise capturing syntax is currently not allowed in return-position `impl Trait` in traits
|
||||||
|
--> $DIR/self-capture.rs:4:34
|
||||||
|
|
|
||||||
|
LL | fn bar<'a>() -> impl Sized + use<Self>;
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: currently, return-position `impl Trait` in traits and trait implementations capture all lifetimes in scope
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
11
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs
Normal file
11
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#![deny(dead_code)]
|
||||||
|
|
||||||
|
struct T1; //~ ERROR struct `T1` is never constructed
|
||||||
|
|
||||||
|
trait Foo { type Unused; } //~ ERROR trait `Foo` is never used
|
||||||
|
impl Foo for T1 { type Unused = Self; }
|
||||||
|
|
||||||
|
pub trait Bar { type Used; }
|
||||||
|
impl Bar for T1 { type Used = Self; }
|
||||||
|
|
||||||
|
fn main() {}
|
20
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr
Normal file
20
tests/ui/lint/dead-code/unused-trait-with-assoc-ty.stderr
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
error: struct `T1` is never constructed
|
||||||
|
--> $DIR/unused-trait-with-assoc-ty.rs:3:8
|
||||||
|
|
|
||||||
|
LL | struct T1;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/unused-trait-with-assoc-ty.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(dead_code)]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: trait `Foo` is never used
|
||||||
|
--> $DIR/unused-trait-with-assoc-ty.rs:5:7
|
||||||
|
|
|
||||||
|
LL | trait Foo { type Unused; }
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl<T: ::std::fmt::Display> Foo<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Tr { //~ WARN trait `Tr` is never used
|
trait Tr {
|
||||||
type U;
|
type U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
warning: trait `Tr` is never used
|
|
||||||
--> $DIR/issue-22546.rs:18:7
|
|
||||||
|
|
|
||||||
LL | trait Tr {
|
|
||||||
| ^^
|
|
||||||
|
|
|
||||||
= note: `#[warn(dead_code)]` on by default
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// #125634
|
||||||
|
struct Thing;
|
||||||
|
|
||||||
|
// Invariant in 'a, Covariant in 'b
|
||||||
|
struct TwoThings<'a, 'b>(*mut &'a (), &'b mut ());
|
||||||
|
|
||||||
|
impl Thing {
|
||||||
|
fn enter_scope<'a>(self, _scope: impl for<'b> FnOnce(TwoThings<'a, 'b>)) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo() {
|
||||||
|
Thing.enter_scope(|ctx| {
|
||||||
|
SameLifetime(ctx); //~ ERROR lifetime may not live long enough
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SameLifetime<'a>(TwoThings<'a, 'a>);
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,17 @@
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/account-for-lifetimes-in-closure-suggestion.rs:13:22
|
||||||
|
|
|
||||||
|
LL | Thing.enter_scope(|ctx| {
|
||||||
|
| ---
|
||||||
|
| |
|
||||||
|
| has type `TwoThings<'_, '1>`
|
||||||
|
| has type `TwoThings<'2, '_>`
|
||||||
|
LL | SameLifetime(ctx);
|
||||||
|
| ^^^ this usage requires that `'1` must outlive `'2`
|
||||||
|
|
|
||||||
|
= note: requirement occurs because of the type `TwoThings<'_, '_>`, which makes the generic argument `'_` invariant
|
||||||
|
= note: the struct `TwoThings<'a, 'b>` is invariant over the parameter `'a`
|
||||||
|
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//@ known-bug: rust-lang/rust#124563
|
// #124563
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub trait Trait {}
|
pub trait Trait {}
|
||||||
|
@ -17,11 +16,11 @@ where
|
||||||
T: Trait,
|
T: Trait,
|
||||||
{
|
{
|
||||||
type Trait = T;
|
type Trait = T;
|
||||||
type Bar = BarImpl<'a, 'b, T>;
|
type Bar = BarImpl<'a, 'b, T>; //~ ERROR lifetime bound not satisfied
|
||||||
|
|
||||||
fn foo(&mut self) {
|
fn foo(&mut self) {
|
||||||
self.enter_scope(|ctx| {
|
self.enter_scope(|ctx| { //~ ERROR lifetime may not live long enough
|
||||||
BarImpl(ctx);
|
BarImpl(ctx); //~ ERROR lifetime may not live long enough
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,3 +43,5 @@ where
|
||||||
{
|
{
|
||||||
type Foo = FooImpl<'a, 'b, T>;
|
type Foo = FooImpl<'a, 'b, T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,49 @@
|
||||||
|
error[E0478]: lifetime bound not satisfied
|
||||||
|
--> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:19:16
|
||||||
|
|
|
||||||
|
LL | type Bar = BarImpl<'a, 'b, T>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
|
||||||
|
--> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:14:6
|
||||||
|
|
|
||||||
|
LL | impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T>
|
||||||
|
| ^^
|
||||||
|
note: but lifetime parameter must outlive the lifetime `'b` as defined here
|
||||||
|
--> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:14:10
|
||||||
|
|
|
||||||
|
LL | impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T>
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:23:21
|
||||||
|
|
|
||||||
|
LL | self.enter_scope(|ctx| {
|
||||||
|
| ---
|
||||||
|
| |
|
||||||
|
| has type `&'1 mut FooImpl<'_, '_, T>`
|
||||||
|
| has type `&mut FooImpl<'2, '_, T>`
|
||||||
|
LL | BarImpl(ctx);
|
||||||
|
| ^^^ this usage requires that `'1` must outlive `'2`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:22:9
|
||||||
|
|
|
||||||
|
LL | impl<'a, 'b, T> Foo for FooImpl<'a, 'b, T>
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | / self.enter_scope(|ctx| {
|
||||||
|
LL | | BarImpl(ctx);
|
||||||
|
LL | | });
|
||||||
|
| |__________^ argument requires that `'a` must outlive `'b`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'a: 'b`
|
||||||
|
= note: requirement occurs because of a mutable reference to `FooImpl<'_, '_, T>`
|
||||||
|
= note: mutable references are invariant over their type parameter
|
||||||
|
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0478`.
|
17
tests/ui/regions/regions-escape-method.fixed
Normal file
17
tests/ui/regions/regions-escape-method.fixed
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// Test a method call where the parameter `B` would (illegally) be
|
||||||
|
// inferred to a region bound in the method argument. If this program
|
||||||
|
// were accepted, then the closure passed to `s.f` could escape its
|
||||||
|
// argument.
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
fn f<B, F>(&self, _: F) where F: FnOnce(&i32) -> B {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let s = S;
|
||||||
|
s.f(|p| *p) //~ ERROR lifetime may not live long enough
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
// inferred to a region bound in the method argument. If this program
|
// inferred to a region bound in the method argument. If this program
|
||||||
// were accepted, then the closure passed to `s.f` could escape its
|
// were accepted, then the closure passed to `s.f` could escape its
|
||||||
// argument.
|
// argument.
|
||||||
|
//@ run-rustfix
|
||||||
|
|
||||||
struct S;
|
struct S;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/regions-escape-method.rs:15:13
|
--> $DIR/regions-escape-method.rs:16:13
|
||||||
|
|
|
|
||||||
LL | s.f(|p| p)
|
LL | s.f(|p| p)
|
||||||
| -- ^ returning this value requires that `'1` must outlive `'2`
|
| -- ^ returning this value requires that `'1` must outlive `'2`
|
||||||
| ||
|
| ||
|
||||||
| |return type of closure is &'2 i32
|
| |return type of closure is &'2 i32
|
||||||
| has type `&'1 i32`
|
| has type `&'1 i32`
|
||||||
|
|
|
||||||
|
help: dereference the return value
|
||||||
|
|
|
||||||
|
LL | s.f(|p| *p)
|
||||||
|
| +
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
// issue#126764
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
trait T {
|
||||||
|
fn f();
|
||||||
|
}
|
||||||
|
impl T for S;
|
||||||
|
//~^ ERROR: unknown start of token
|
||||||
|
//~| ERROR: expected `{}`
|
||||||
|
//~| ERROR: not all trait items implemented, missing: `f`
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,31 @@
|
||||||
|
error: unknown start of token: \u{ff1b}
|
||||||
|
--> $DIR/missing-impl-trait-block-but-not-ascii.rs:8:13
|
||||||
|
|
|
||||||
|
LL | impl T for S;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
help: Unicode character ';' (Fullwidth Semicolon) looks like ';' (Semicolon), but it is not
|
||||||
|
|
|
||||||
|
LL | impl T for S;
|
||||||
|
| ~
|
||||||
|
|
||||||
|
error: expected `{}`, found `;`
|
||||||
|
--> $DIR/missing-impl-trait-block-but-not-ascii.rs:8:13
|
||||||
|
|
|
||||||
|
LL | impl T for S;
|
||||||
|
| ^^
|
||||||
|
|
|
||||||
|
= help: try using `{}` instead
|
||||||
|
|
||||||
|
error[E0046]: not all trait items implemented, missing: `f`
|
||||||
|
--> $DIR/missing-impl-trait-block-but-not-ascii.rs:8:1
|
||||||
|
|
|
||||||
|
LL | fn f();
|
||||||
|
| ------- `f` from trait
|
||||||
|
LL | }
|
||||||
|
LL | impl T for S;
|
||||||
|
| ^^^^^^^^^^^^ missing `f` in implementation
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0046`.
|
Loading…
Add table
Add a link
Reference in a new issue