Auto merge of #100151 - matthiaskrgr:rollup-irqwvj2, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #98796 (Do not exclusively suggest `;` when `,` is also a choice) - #99772 (Re-enable submodule archive downloads.) - #100058 (Suggest a positional formatting argument instead of a captured argument) - #100093 (Enable unused_parens for match arms) - #100095 (More EarlyBinder cleanups) - #100138 (Remove more Clean trait implementations) - #100148 (RustWrapper: update for TypedPointerType in LLVM) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f6f9d5e73d
@ -377,7 +377,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
||||
|
||||
fn print_string(&mut self, st: &str, style: ast::StrStyle) {
|
||||
let st = match style {
|
||||
ast::StrStyle::Cooked => (format!("\"{}\"", st.escape_debug())),
|
||||
ast::StrStyle::Cooked => format!("\"{}\"", st.escape_debug()),
|
||||
ast::StrStyle::Raw(n) => {
|
||||
format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = st)
|
||||
}
|
||||
|
@ -16,9 +16,7 @@ use rustc_middle::mir::{
|
||||
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
|
||||
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
|
||||
};
|
||||
use rustc_middle::ty::{
|
||||
self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty,
|
||||
};
|
||||
use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
@ -461,23 +459,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
// Find out if the predicates show that the type is a Fn or FnMut
|
||||
let find_fn_kind_from_did = |predicates: &[(ty::Predicate<'tcx>, Span)], substs| {
|
||||
predicates.iter().find_map(|(pred, _)| {
|
||||
let pred = if let Some(substs) = substs {
|
||||
EarlyBinder(*pred).subst(tcx, substs).kind().skip_binder()
|
||||
} else {
|
||||
pred.kind().skip_binder()
|
||||
};
|
||||
if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty {
|
||||
let find_fn_kind_from_did =
|
||||
|predicates: ty::EarlyBinder<&[(ty::Predicate<'tcx>, Span)]>, substs| {
|
||||
predicates.0.iter().find_map(|(pred, _)| {
|
||||
let pred = if let Some(substs) = substs {
|
||||
predicates.rebind(*pred).subst(tcx, substs).kind().skip_binder()
|
||||
} else {
|
||||
pred.kind().skip_binder()
|
||||
};
|
||||
if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty {
|
||||
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
|
||||
return Some(hir::Mutability::Not);
|
||||
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
|
||||
return Some(hir::Mutability::Mut);
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
};
|
||||
None
|
||||
})
|
||||
};
|
||||
|
||||
// If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
|
||||
// borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
|
||||
@ -485,11 +484,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// borrowed variants in a function body when we see a move error.
|
||||
let borrow_level = match ty.kind() {
|
||||
ty::Param(_) => find_fn_kind_from_did(
|
||||
tcx.explicit_predicates_of(self.mir_def_id().to_def_id()).predicates,
|
||||
tcx.bound_explicit_predicates_of(self.mir_def_id().to_def_id())
|
||||
.map_bound(|p| p.predicates),
|
||||
None,
|
||||
),
|
||||
ty::Opaque(did, substs) => {
|
||||
find_fn_kind_from_did(tcx.explicit_item_bounds(*did), Some(*substs))
|
||||
find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*did), Some(*substs))
|
||||
}
|
||||
ty::Closure(_, substs) => match substs.as_closure().kind() {
|
||||
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
|
||||
|
@ -839,7 +839,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
hir::Node::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
|
||||
..
|
||||
}) => (tcx.sess.source_map().end_point(fn_decl_span)),
|
||||
}) => tcx.sess.source_map().end_point(fn_decl_span),
|
||||
_ => self.body.span,
|
||||
};
|
||||
|
||||
|
@ -280,6 +280,11 @@ struct Context<'a, 'b> {
|
||||
unused_names_lint: PositionalNamedArgsLint,
|
||||
}
|
||||
|
||||
pub struct FormatArg {
|
||||
expr: P<ast::Expr>,
|
||||
named: bool,
|
||||
}
|
||||
|
||||
/// Parses the arguments from the given list of tokens, returning the diagnostic
|
||||
/// if there's a parse error so we can continue parsing other format!
|
||||
/// expressions.
|
||||
@ -293,8 +298,8 @@ fn parse_args<'a>(
|
||||
ecx: &mut ExtCtxt<'a>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> PResult<'a, (P<ast::Expr>, Vec<P<ast::Expr>>, FxHashMap<Symbol, (usize, Span)>)> {
|
||||
let mut args = Vec::<P<ast::Expr>>::new();
|
||||
) -> PResult<'a, (P<ast::Expr>, Vec<FormatArg>, FxHashMap<Symbol, (usize, Span)>)> {
|
||||
let mut args = Vec::<FormatArg>::new();
|
||||
let mut names = FxHashMap::<Symbol, (usize, Span)>::default();
|
||||
|
||||
let mut p = ecx.new_parser_from_tts(tts);
|
||||
@ -362,7 +367,7 @@ fn parse_args<'a>(
|
||||
let e = p.parse_expr()?;
|
||||
if let Some((prev, _)) = names.get(&ident.name) {
|
||||
ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", ident))
|
||||
.span_label(args[*prev].span, "previously here")
|
||||
.span_label(args[*prev].expr.span, "previously here")
|
||||
.span_label(e.span, "duplicate argument")
|
||||
.emit();
|
||||
continue;
|
||||
@ -374,7 +379,7 @@ fn parse_args<'a>(
|
||||
// args. And remember the names.
|
||||
let slot = args.len();
|
||||
names.insert(ident.name, (slot, ident.span));
|
||||
args.push(e);
|
||||
args.push(FormatArg { expr: e, named: true });
|
||||
}
|
||||
_ => {
|
||||
let e = p.parse_expr()?;
|
||||
@ -385,11 +390,11 @@ fn parse_args<'a>(
|
||||
);
|
||||
err.span_label(e.span, "positional arguments must be before named arguments");
|
||||
for pos in names.values() {
|
||||
err.span_label(args[pos.0].span, "named argument");
|
||||
err.span_label(args[pos.0].expr.span, "named argument");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
args.push(e);
|
||||
args.push(FormatArg { expr: e, named: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1214,7 +1219,7 @@ pub fn expand_preparsed_format_args(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
efmt: P<ast::Expr>,
|
||||
args: Vec<P<ast::Expr>>,
|
||||
args: Vec<FormatArg>,
|
||||
names: FxHashMap<Symbol, (usize, Span)>,
|
||||
append_newline: bool,
|
||||
) -> P<ast::Expr> {
|
||||
@ -1304,6 +1309,25 @@ pub fn expand_preparsed_format_args(
|
||||
e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
|
||||
}
|
||||
}
|
||||
if err.should_be_replaced_with_positional_argument {
|
||||
let captured_arg_span =
|
||||
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
|
||||
let positional_args = args.iter().filter(|arg| !arg.named).collect::<Vec<_>>();
|
||||
if let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) {
|
||||
let span = match positional_args.last() {
|
||||
Some(arg) => arg.expr.span,
|
||||
None => fmt_sp,
|
||||
};
|
||||
e.multipart_suggestion_verbose(
|
||||
"consider using a positional formatting argument instead",
|
||||
vec![
|
||||
(captured_arg_span, positional_args.len().to_string()),
|
||||
(span.shrink_to_hi(), format!(", {}", arg)),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
e.emit();
|
||||
return DummyResult::raw_expr(sp, true);
|
||||
}
|
||||
@ -1318,7 +1342,7 @@ pub fn expand_preparsed_format_args(
|
||||
|
||||
let mut cx = Context {
|
||||
ecx,
|
||||
args,
|
||||
args: args.into_iter().map(|arg| arg.expr).collect(),
|
||||
num_captured_args: 0,
|
||||
arg_types,
|
||||
arg_unique_types,
|
||||
|
@ -13,7 +13,7 @@ use rustc_middle::mir::pretty::display_allocation;
|
||||
use rustc_middle::traits::Reveal;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, subst::Subst, EarlyBinder, TyCtxt};
|
||||
use rustc_middle::ty::{self, subst::Subst, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_target::abi::{self, Abi};
|
||||
use std::borrow::Cow;
|
||||
@ -45,7 +45,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
||||
"Unexpected DefKind: {:?}",
|
||||
ecx.tcx.def_kind(cid.instance.def_id())
|
||||
);
|
||||
let layout = ecx.layout_of(EarlyBinder(body.return_ty()).subst(tcx, cid.instance.substs))?;
|
||||
let layout = ecx.layout_of(body.bound_return_ty().subst(tcx, cid.instance.substs))?;
|
||||
assert!(!layout.is_unsized());
|
||||
let ret = ecx.allocate(layout, MemoryKind::Stack)?;
|
||||
|
||||
|
@ -396,6 +396,7 @@ enum UnusedDelimsCtx {
|
||||
LetScrutineeExpr,
|
||||
ArrayLenExpr,
|
||||
AnonConst,
|
||||
MatchArmExpr,
|
||||
}
|
||||
|
||||
impl From<UnusedDelimsCtx> for &'static str {
|
||||
@ -414,6 +415,7 @@ impl From<UnusedDelimsCtx> for &'static str {
|
||||
UnusedDelimsCtx::BlockRetValue => "block return value",
|
||||
UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression",
|
||||
UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression",
|
||||
UnusedDelimsCtx::MatchArmExpr => "match arm expression",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -805,6 +807,18 @@ impl EarlyLintPass for UnusedParens {
|
||||
}
|
||||
return;
|
||||
}
|
||||
ExprKind::Match(ref _expr, ref arm) => {
|
||||
for a in arm {
|
||||
self.check_unused_delims_expr(
|
||||
cx,
|
||||
&a.body,
|
||||
UnusedDelimsCtx::MatchArmExpr,
|
||||
false,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -1311,10 +1311,15 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
|
||||
return LLVMBFloatTypeKind;
|
||||
case Type::X86_AMXTyID:
|
||||
return LLVMX86_AMXTypeKind;
|
||||
#if LLVM_VERSION_GE(15, 0)
|
||||
#if LLVM_VERSION_GE(15, 0) && LLVM_VERSION_LT(16, 0)
|
||||
case Type::DXILPointerTyID:
|
||||
report_fatal_error("Rust does not support DirectX typed pointers.");
|
||||
break;
|
||||
#endif
|
||||
#if LLVM_VERSION_GE(16, 0)
|
||||
case Type::TypedPointerTyID:
|
||||
report_fatal_error("Rust does not support typed pointers.");
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
report_fatal_error("Unhandled TypeID.");
|
||||
|
@ -431,6 +431,12 @@ impl<'tcx> Body<'tcx> {
|
||||
self.local_decls[RETURN_PLACE].ty
|
||||
}
|
||||
|
||||
/// Returns the return type; it always return first element from `local_decls` array.
|
||||
#[inline]
|
||||
pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> {
|
||||
ty::EarlyBinder(self.local_decls[RETURN_PLACE].ty)
|
||||
}
|
||||
|
||||
/// Gets the location of the terminator for the given block.
|
||||
#[inline]
|
||||
pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
|
||||
|
@ -563,7 +563,7 @@ impl<'tcx> AdtDef<'tcx> {
|
||||
///
|
||||
/// Due to normalization being eager, this applies even if
|
||||
/// the associated type is behind a pointer (e.g., issue #31299).
|
||||
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
|
||||
tcx.adt_sized_constraint(self.did()).0
|
||||
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
|
||||
ty::EarlyBinder(tcx.adt_sized_constraint(self.did()).0)
|
||||
}
|
||||
}
|
||||
|
@ -2191,7 +2191,7 @@ impl<'tcx> Ty<'tcx> {
|
||||
|
||||
ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)),
|
||||
|
||||
ty::Adt(def, _substs) => def.sized_constraint(tcx).is_empty(),
|
||||
ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),
|
||||
|
||||
ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
|
||||
|
||||
|
@ -680,6 +680,24 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
|
||||
ty::EarlyBinder(self.const_param_default(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_predicates_of(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> {
|
||||
ty::EarlyBinder(self.predicates_of(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_explicit_predicates_of(
|
||||
self,
|
||||
def_id: DefId,
|
||||
) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> {
|
||||
ty::EarlyBinder(self.explicit_predicates_of(def_id))
|
||||
}
|
||||
|
||||
pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
|
||||
ty::EarlyBinder(self.impl_subject(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
struct OpaqueTypeExpander<'tcx> {
|
||||
|
@ -617,7 +617,7 @@ impl SplitVarLenSlice {
|
||||
// The only admissible fixed-length slice is one of the array size. Whether `max_slice`
|
||||
// is fixed-length or variable-length, it will be the only relevant slice to output
|
||||
// here.
|
||||
Some(_) => (0..0), // empty range
|
||||
Some(_) => 0..0, // empty range
|
||||
// We cover all arities in the range `(self.arity..infinity)`. We split that range into
|
||||
// two: lengths smaller than `max_slice.arity()` are treated independently as
|
||||
// fixed-lengths slices, and lengths above are captured by `max_slice`.
|
||||
|
@ -18,9 +18,7 @@ use rustc_middle::mir::{
|
||||
};
|
||||
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::{
|
||||
self, ConstKind, EarlyBinder, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable,
|
||||
};
|
||||
use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_span::{def_id::DefId, Span};
|
||||
use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
|
||||
use rustc_target::spec::abi::Abi as CallAbi;
|
||||
@ -387,7 +385,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
);
|
||||
|
||||
let ret_layout = ecx
|
||||
.layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
|
||||
.layout_of(body.bound_return_ty().subst(tcx, substs))
|
||||
.ok()
|
||||
// Don't bother allocating memory for large values.
|
||||
// I don't know how return types can seem to be unsized but this happens in the
|
||||
|
@ -23,8 +23,7 @@ use rustc_middle::mir::{
|
||||
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||
use rustc_middle::ty::{
|
||||
self, ConstInt, ConstKind, EarlyBinder, Instance, ParamEnv, ScalarInt, Ty, TyCtxt,
|
||||
TypeVisitable,
|
||||
self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable,
|
||||
};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::Span;
|
||||
@ -196,7 +195,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
);
|
||||
|
||||
let ret_layout = ecx
|
||||
.layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
|
||||
.layout_of(body.bound_return_ty().subst(tcx, substs))
|
||||
.ok()
|
||||
// Don't bother allocating memory for large values.
|
||||
// I don't know how return types can seem to be unsized but this happens in the
|
||||
|
@ -560,7 +560,8 @@ impl<'a> Parser<'a> {
|
||||
|| (sm.is_multiline(
|
||||
self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo())
|
||||
) && t == &token::Pound)
|
||||
}) {
|
||||
}) && !expected.contains(&TokenType::Token(token::Comma))
|
||||
{
|
||||
// Missing semicolon typo. This is triggered if the next token could either start a
|
||||
// new statement or is a block close. For example:
|
||||
//
|
||||
|
@ -175,6 +175,7 @@ pub struct ParseError {
|
||||
pub label: string::String,
|
||||
pub span: InnerSpan,
|
||||
pub secondary_label: Option<(string::String, InnerSpan)>,
|
||||
pub should_be_replaced_with_positional_argument: bool,
|
||||
}
|
||||
|
||||
/// The parser structure for interpreting the input format string. This is
|
||||
@ -236,6 +237,8 @@ impl<'a> Iterator for Parser<'a> {
|
||||
lbrace_inner_offset.to(InnerOffset(rbrace_inner_offset.0 + 1)),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
self.suggest_positional_arg_instead_of_captured_arg(arg);
|
||||
}
|
||||
Some(NextArgument(arg))
|
||||
}
|
||||
@ -313,6 +316,7 @@ impl<'a> Parser<'a> {
|
||||
label: label.into(),
|
||||
span,
|
||||
secondary_label: None,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
});
|
||||
}
|
||||
|
||||
@ -336,6 +340,7 @@ impl<'a> Parser<'a> {
|
||||
label: label.into(),
|
||||
span,
|
||||
secondary_label: None,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
});
|
||||
}
|
||||
|
||||
@ -407,6 +412,7 @@ impl<'a> Parser<'a> {
|
||||
label,
|
||||
span: pos.to(pos),
|
||||
secondary_label,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
});
|
||||
None
|
||||
}
|
||||
@ -434,6 +440,7 @@ impl<'a> Parser<'a> {
|
||||
label,
|
||||
span: pos.to(pos),
|
||||
secondary_label,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
});
|
||||
} else {
|
||||
self.err(description, format!("expected `{:?}`", c), pos.to(pos));
|
||||
@ -750,6 +757,34 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
if found { Some(cur) } else { None }
|
||||
}
|
||||
|
||||
fn suggest_positional_arg_instead_of_captured_arg(&mut self, arg: Argument<'a>) {
|
||||
if let Some(end) = self.consume_pos('.') {
|
||||
let byte_pos = self.to_span_index(end);
|
||||
let start = InnerOffset(byte_pos.0 + 1);
|
||||
let field = self.argument(start);
|
||||
// We can only parse `foo.bar` field access, any deeper nesting,
|
||||
// or another type of expression, like method calls, are not supported
|
||||
if !self.consume('}') {
|
||||
return;
|
||||
}
|
||||
if let ArgumentNamed(_) = arg.position {
|
||||
if let ArgumentNamed(_) = field.position {
|
||||
self.errors.insert(
|
||||
0,
|
||||
ParseError {
|
||||
description: "field access isn't supported".to_string(),
|
||||
note: None,
|
||||
label: "not supported".to_string(),
|
||||
span: InnerSpan::new(arg.position_span.start, field.position_span.end),
|
||||
secondary_label: None,
|
||||
should_be_replaced_with_positional_argument: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the indices of all characters that have been processed and differ between the actual
|
||||
|
@ -32,7 +32,7 @@ use rustc_middle::traits::select::OverflowError;
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
|
||||
use rustc_middle::ty::{self, EarlyBinder, Term, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
@ -2005,16 +2005,16 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
|
||||
let substs =
|
||||
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
|
||||
let ty = tcx.type_of(assoc_ty.item.def_id);
|
||||
let ty = tcx.bound_type_of(assoc_ty.item.def_id);
|
||||
let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
|
||||
let term: ty::Term<'tcx> = if is_const {
|
||||
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
|
||||
let identity_substs =
|
||||
crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
|
||||
let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
|
||||
let kind = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs));
|
||||
tcx.mk_const(ty::ConstS { ty, kind }).into()
|
||||
ty.map_bound(|ty| tcx.mk_const(ty::ConstS { ty, kind }).into())
|
||||
} else {
|
||||
ty.into()
|
||||
ty.map_bound(|ty| ty.into())
|
||||
};
|
||||
if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
|
||||
let err = tcx.ty_error_with_message(
|
||||
@ -2024,7 +2024,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
|
||||
Progress { term: err.into(), obligations: nested }
|
||||
} else {
|
||||
assoc_ty_own_obligations(selcx, obligation, &mut nested);
|
||||
Progress { term: EarlyBinder(term).subst(tcx, substs), obligations: nested }
|
||||
Progress { term: term.subst(tcx, substs), obligations: nested }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1886,7 +1886,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
let sized_crit = def.sized_constraint(self.tcx());
|
||||
// (*) binder moved here
|
||||
Where(obligation.predicate.rebind({
|
||||
sized_crit.iter().map(|ty| EarlyBinder(*ty).subst(self.tcx(), substs)).collect()
|
||||
sized_crit
|
||||
.0
|
||||
.iter()
|
||||
.map(|ty| sized_crit.rebind(*ty).subst(self.tcx(), substs))
|
||||
.collect()
|
||||
}))
|
||||
}
|
||||
|
||||
@ -2357,11 +2361,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// obligation will normalize to `<$0 as Iterator>::Item = $1` and
|
||||
// `$1: Copy`, so we must ensure the obligations are emitted in
|
||||
// that order.
|
||||
let predicates = tcx.predicates_of(def_id);
|
||||
let predicates = tcx.bound_predicates_of(def_id);
|
||||
debug!(?predicates);
|
||||
assert_eq!(predicates.parent, None);
|
||||
let mut obligations = Vec::with_capacity(predicates.predicates.len());
|
||||
for (predicate, span) in predicates.predicates {
|
||||
assert_eq!(predicates.0.parent, None);
|
||||
let mut obligations = Vec::with_capacity(predicates.0.predicates.len());
|
||||
for (predicate, span) in predicates.0.predicates {
|
||||
let span = *span;
|
||||
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
|
||||
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
|
||||
@ -2375,7 +2379,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
param_env,
|
||||
cause.clone(),
|
||||
recursion_depth,
|
||||
EarlyBinder(*predicate).subst(tcx, substs),
|
||||
predicates.rebind(*predicate).subst(tcx, substs),
|
||||
&mut obligations,
|
||||
);
|
||||
obligations.push(Obligation { cause, recursion_depth, param_env, predicate });
|
||||
|
@ -6,7 +6,7 @@ use smallvec::SmallVec;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
|
||||
use rustc_middle::ty::{self, EarlyBinder, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};
|
||||
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};
|
||||
|
||||
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
|
||||
pub use rustc_infer::traits::{self, util::*};
|
||||
@ -200,8 +200,8 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
|
||||
impl_def_id: DefId,
|
||||
impl_substs: SubstsRef<'tcx>,
|
||||
) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
|
||||
let subject = selcx.tcx().impl_subject(impl_def_id);
|
||||
let subject = EarlyBinder(subject).subst(selcx.tcx(), impl_substs);
|
||||
let subject = selcx.tcx().bound_impl_subject(impl_def_id);
|
||||
let subject = subject.subst(selcx.tcx(), impl_substs);
|
||||
let Normalized { value: subject, obligations: normalization_obligations1 } =
|
||||
super::normalize(selcx, param_env, ObligationCause::dummy(), subject);
|
||||
|
||||
|
@ -51,11 +51,11 @@ impl<'tcx> RustIrDatabase<'tcx> {
|
||||
where
|
||||
ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option<T>>,
|
||||
{
|
||||
self.interner
|
||||
.tcx
|
||||
.explicit_item_bounds(def_id)
|
||||
let bounds = self.interner.tcx.bound_explicit_item_bounds(def_id);
|
||||
bounds
|
||||
.0
|
||||
.iter()
|
||||
.map(|(bound, _)| EarlyBinder(*bound).subst(self.interner.tcx, &bound_vars))
|
||||
.map(|(bound, _)| bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars))
|
||||
.filter_map(|bound| LowerInto::<Option<_>>::lower_into(bound, self.interner))
|
||||
.collect()
|
||||
}
|
||||
@ -268,21 +268,20 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
|
||||
|
||||
let where_clauses = self.where_clauses_for(def_id, bound_vars);
|
||||
|
||||
let sig = self.interner.tcx.fn_sig(def_id);
|
||||
let sig = self.interner.tcx.bound_fn_sig(def_id);
|
||||
let (inputs_and_output, iobinders, _) = crate::chalk::lowering::collect_bound_vars(
|
||||
self.interner,
|
||||
self.interner.tcx,
|
||||
EarlyBinder(sig.inputs_and_output()).subst(self.interner.tcx, bound_vars),
|
||||
sig.map_bound(|s| s.inputs_and_output()).subst(self.interner.tcx, bound_vars),
|
||||
);
|
||||
|
||||
let argument_types = inputs_and_output[..inputs_and_output.len() - 1]
|
||||
.iter()
|
||||
.map(|t| {
|
||||
EarlyBinder(*t).subst(self.interner.tcx, &bound_vars).lower_into(self.interner)
|
||||
})
|
||||
.map(|t| sig.rebind(*t).subst(self.interner.tcx, &bound_vars).lower_into(self.interner))
|
||||
.collect();
|
||||
|
||||
let return_type = EarlyBinder(inputs_and_output[inputs_and_output.len() - 1])
|
||||
let return_type = sig
|
||||
.rebind(inputs_and_output[inputs_and_output.len() - 1])
|
||||
.subst(self.interner.tcx, &bound_vars)
|
||||
.lower_into(self.interner);
|
||||
|
||||
@ -295,7 +294,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
|
||||
};
|
||||
Arc::new(chalk_solve::rust_ir::FnDefDatum {
|
||||
id: fn_def_id,
|
||||
sig: sig.lower_into(self.interner),
|
||||
sig: sig.0.lower_into(self.interner),
|
||||
binders: chalk_ir::Binders::new(binders, bound),
|
||||
})
|
||||
}
|
||||
@ -503,12 +502,14 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
|
||||
|
||||
let identity_substs = InternalSubsts::identity_for_item(self.interner.tcx, opaque_ty_id.0);
|
||||
|
||||
let explicit_item_bounds = self.interner.tcx.bound_explicit_item_bounds(opaque_ty_id.0);
|
||||
let bounds =
|
||||
self.interner
|
||||
.tcx
|
||||
.explicit_item_bounds(opaque_ty_id.0)
|
||||
explicit_item_bounds
|
||||
.0
|
||||
.iter()
|
||||
.map(|(bound, _)| EarlyBinder(*bound).subst(self.interner.tcx, &bound_vars))
|
||||
.map(|(bound, _)| {
|
||||
explicit_item_bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars)
|
||||
})
|
||||
.map(|bound| {
|
||||
bound.fold_with(&mut ReplaceOpaqueTyFolder {
|
||||
tcx: self.interner.tcx,
|
||||
|
@ -2,9 +2,7 @@ use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::subst::Subst;
|
||||
use rustc_middle::ty::{
|
||||
self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt,
|
||||
};
|
||||
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
fn sized_constraint_for_ty<'tcx>(
|
||||
@ -33,8 +31,9 @@ fn sized_constraint_for_ty<'tcx>(
|
||||
let adt_tys = adt.sized_constraint(tcx);
|
||||
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
|
||||
adt_tys
|
||||
.0
|
||||
.iter()
|
||||
.map(|ty| EarlyBinder(*ty).subst(tcx, substs))
|
||||
.map(|ty| adt_tys.rebind(*ty).subst(tcx, substs))
|
||||
.flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
|
||||
.collect()
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{
|
||||
self, AdtKind, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt,
|
||||
TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
|
||||
TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
@ -1295,7 +1295,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
let infcx = wfcx.infcx;
|
||||
let tcx = wfcx.tcx();
|
||||
|
||||
let predicates = tcx.predicates_of(def_id);
|
||||
let predicates = tcx.bound_predicates_of(def_id.to_def_id());
|
||||
let generics = tcx.generics_of(def_id);
|
||||
|
||||
let is_our_default = |def: &ty::GenericParamDef| match def.kind {
|
||||
@ -1392,6 +1392,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
|
||||
// Now we build the substituted predicates.
|
||||
let default_obligations = predicates
|
||||
.0
|
||||
.predicates
|
||||
.iter()
|
||||
.flat_map(|&(pred, sp)| {
|
||||
@ -1422,7 +1423,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
}
|
||||
let mut param_count = CountParams::default();
|
||||
let has_region = pred.visit_with(&mut param_count).is_break();
|
||||
let substituted_pred = EarlyBinder(pred).subst(tcx, substs);
|
||||
let substituted_pred = predicates.rebind(pred).subst(tcx, substs);
|
||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||
// or preds with multiple params.
|
||||
if substituted_pred.has_param_types_or_consts()
|
||||
@ -1430,7 +1431,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
|| has_region
|
||||
{
|
||||
None
|
||||
} else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
|
||||
} else if predicates.0.predicates.iter().any(|&(p, _)| p == substituted_pred) {
|
||||
// Avoid duplication of predicates that contain no parameters, for example.
|
||||
None
|
||||
} else {
|
||||
@ -1456,7 +1457,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
||||
traits::Obligation::new(cause, wfcx.param_env, pred)
|
||||
});
|
||||
|
||||
let predicates = predicates.instantiate_identity(tcx);
|
||||
let predicates = predicates.0.instantiate_identity(tcx);
|
||||
|
||||
let predicates = wfcx.normalize(span, None, predicates);
|
||||
|
||||
|
@ -36,10 +36,7 @@ function fetch_github_commit_archive {
|
||||
rm $cached
|
||||
}
|
||||
|
||||
# Archive downloads are temporarily disabled due to sudden 504
|
||||
# gateway timeout errors.
|
||||
# included="src/llvm-project src/doc/book src/doc/rust-by-example"
|
||||
included=""
|
||||
included="src/llvm-project src/doc/book src/doc/rust-by-example"
|
||||
modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
|
||||
modules=($modules)
|
||||
use_git=""
|
||||
@ -63,9 +60,9 @@ done
|
||||
retry sh -c "git submodule deinit -f $use_git && \
|
||||
git submodule sync && \
|
||||
git submodule update -j 16 --init --recursive --depth 1 $use_git"
|
||||
# STATUS=0
|
||||
# for pid in ${bg_pids[*]}
|
||||
# do
|
||||
# wait $pid || STATUS=1
|
||||
# done
|
||||
# exit ${STATUS}
|
||||
STATUS=0
|
||||
for pid in ${bg_pids[*]}
|
||||
do
|
||||
wait $pid || STATUS=1
|
||||
done
|
||||
exit ${STATUS}
|
||||
|
@ -956,7 +956,11 @@ fn clean_fn_decl_with_args<'tcx>(
|
||||
decl: &hir::FnDecl<'tcx>,
|
||||
args: Arguments,
|
||||
) -> FnDecl {
|
||||
FnDecl { inputs: args, output: decl.output.clean(cx), c_variadic: decl.c_variadic }
|
||||
let output = match decl.output {
|
||||
hir::FnRetTy::Return(typ) => Return(clean_ty(typ, cx)),
|
||||
hir::FnRetTy::DefaultReturn(..) => DefaultReturn,
|
||||
};
|
||||
FnDecl { inputs: args, output, c_variadic: decl.c_variadic }
|
||||
}
|
||||
|
||||
fn clean_fn_decl_from_did_and_sig<'tcx>(
|
||||
@ -991,27 +995,16 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<'tcx, FnRetTy> for hir::FnRetTy<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> FnRetTy {
|
||||
match *self {
|
||||
Self::Return(typ) => Return(clean_ty(typ, cx)),
|
||||
Self::DefaultReturn(..) => DefaultReturn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<'tcx, Path> for hir::TraitRef<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
|
||||
let path = clean_path(self.path, cx);
|
||||
register_res(cx, path.res);
|
||||
path
|
||||
}
|
||||
fn clean_trait_ref<'tcx>(trait_ref: &hir::TraitRef<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
|
||||
let path = clean_path(trait_ref.path, cx);
|
||||
register_res(cx, path.res);
|
||||
path
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<'tcx, PolyTrait> for hir::PolyTraitRef<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> PolyTrait {
|
||||
PolyTrait {
|
||||
trait_: self.trait_ref.clean(cx),
|
||||
trait_: clean_trait_ref(&self.trait_ref, cx),
|
||||
generic_params: self
|
||||
.bound_generic_params
|
||||
.iter()
|
||||
@ -2000,7 +1993,7 @@ fn clean_impl<'tcx>(
|
||||
) -> Vec<Item> {
|
||||
let tcx = cx.tcx;
|
||||
let mut ret = Vec::new();
|
||||
let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx));
|
||||
let trait_ = impl_.of_trait.as_ref().map(|t| clean_trait_ref(t, cx));
|
||||
let items =
|
||||
impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
|
||||
let def_id = tcx.hir().local_def_id(hir_id);
|
||||
|
18
src/test/ui/fmt/struct-field-as-captured-argument.fixed
Normal file
18
src/test/ui/fmt/struct-field-as-captured-argument.fixed
Normal file
@ -0,0 +1,18 @@
|
||||
// run-rustfix
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo {
|
||||
field: usize,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo { field: 0 };
|
||||
let bar = 3;
|
||||
format!("{0}", foo.field); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{1} {} {bar}", "aa", foo.field); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{2} {} {1} {bar}", "aa", "bb", foo.field); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{1} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{1:?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
}
|
18
src/test/ui/fmt/struct-field-as-captured-argument.rs
Normal file
18
src/test/ui/fmt/struct-field-as-captured-argument.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// run-rustfix
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Foo {
|
||||
field: usize,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo { field: 0 };
|
||||
let bar = 3;
|
||||
format!("{foo.field}"); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{foo.field} {} {bar}", "aa"); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{foo.field} {} {1} {bar}", "aa", "bb"); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{foo.field} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{foo.field:?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{foo.field:#?} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
format!("{foo.field:.3} {} {baz}", "aa", baz = 3); //~ ERROR invalid format string: field access isn't supported
|
||||
}
|
79
src/test/ui/fmt/struct-field-as-captured-argument.stderr
Normal file
79
src/test/ui/fmt/struct-field-as-captured-argument.stderr
Normal file
@ -0,0 +1,79 @@
|
||||
error: invalid format string: field access isn't supported
|
||||
--> $DIR/struct-field-as-captured-argument.rs:11:15
|
||||
|
|
||||
LL | format!("{foo.field}");
|
||||
| ^^^^^^^^^ not supported in format string
|
||||
|
|
||||
help: consider using a positional formatting argument instead
|
||||
|
|
||||
LL | format!("{0}", foo.field);
|
||||
| ~ +++++++++++
|
||||
|
||||
error: invalid format string: field access isn't supported
|
||||
--> $DIR/struct-field-as-captured-argument.rs:12:15
|
||||
|
|
||||
LL | format!("{foo.field} {} {bar}", "aa");
|
||||
| ^^^^^^^^^ not supported in format string
|
||||
|
|
||||
help: consider using a positional formatting argument instead
|
||||
|
|
||||
LL | format!("{1} {} {bar}", "aa", foo.field);
|
||||
| ~ +++++++++++
|
||||
|
||||
error: invalid format string: field access isn't supported
|
||||
--> $DIR/struct-field-as-captured-argument.rs:13:15
|
||||
|
|
||||
LL | format!("{foo.field} {} {1} {bar}", "aa", "bb");
|
||||
| ^^^^^^^^^ not supported in format string
|
||||
|
|
||||
help: consider using a positional formatting argument instead
|
||||
|
|
||||
LL | format!("{2} {} {1} {bar}", "aa", "bb", foo.field);
|
||||
| ~ +++++++++++
|
||||
|
||||
error: invalid format string: field access isn't supported
|
||||
--> $DIR/struct-field-as-captured-argument.rs:14:15
|
||||
|
|
||||
LL | format!("{foo.field} {} {baz}", "aa", baz = 3);
|
||||
| ^^^^^^^^^ not supported in format string
|
||||
|
|
||||
help: consider using a positional formatting argument instead
|
||||
|
|
||||
LL | format!("{1} {} {baz}", "aa", foo.field, baz = 3);
|
||||
| ~ +++++++++++
|
||||
|
||||
error: invalid format string: field access isn't supported
|
||||
--> $DIR/struct-field-as-captured-argument.rs:15:15
|
||||
|
|
||||
LL | format!("{foo.field:?} {} {baz}", "aa", baz = 3);
|
||||
| ^^^^^^^^^ not supported in format string
|
||||
|
|
||||
help: consider using a positional formatting argument instead
|
||||
|
|
||||
LL | format!("{1:?} {} {baz}", "aa", foo.field, baz = 3);
|
||||
| ~ +++++++++++
|
||||
|
||||
error: invalid format string: field access isn't supported
|
||||
--> $DIR/struct-field-as-captured-argument.rs:16:15
|
||||
|
|
||||
LL | format!("{foo.field:#?} {} {baz}", "aa", baz = 3);
|
||||
| ^^^^^^^^^ not supported in format string
|
||||
|
|
||||
help: consider using a positional formatting argument instead
|
||||
|
|
||||
LL | format!("{1:#?} {} {baz}", "aa", foo.field, baz = 3);
|
||||
| ~ +++++++++++
|
||||
|
||||
error: invalid format string: field access isn't supported
|
||||
--> $DIR/struct-field-as-captured-argument.rs:17:15
|
||||
|
|
||||
LL | format!("{foo.field:.3} {} {baz}", "aa", baz = 3);
|
||||
| ^^^^^^^^^ not supported in format string
|
||||
|
|
||||
help: consider using a positional formatting argument instead
|
||||
|
|
||||
LL | format!("{1:.3} {} {baz}", "aa", foo.field, baz = 3);
|
||||
| ~ +++++++++++
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
9
src/test/ui/lint/unused/issue-92751.rs
Normal file
9
src/test/ui/lint/unused/issue-92751.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#[deny(unused)]
|
||||
pub fn broken(x: Option<()>) -> i32 {
|
||||
match x {
|
||||
Some(()) => (1), //~ ERROR unnecessary parentheses around match arm expression
|
||||
None => (2), //~ ERROR unnecessary parentheses around match arm expression
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
32
src/test/ui/lint/unused/issue-92751.stderr
Normal file
32
src/test/ui/lint/unused/issue-92751.stderr
Normal file
@ -0,0 +1,32 @@
|
||||
error: unnecessary parentheses around match arm expression
|
||||
--> $DIR/issue-92751.rs:4:21
|
||||
|
|
||||
LL | Some(()) => (1),
|
||||
| ^ ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-92751.rs:1:8
|
||||
|
|
||||
LL | #[deny(unused)]
|
||||
| ^^^^^^
|
||||
= note: `#[deny(unused_parens)]` implied by `#[deny(unused)]`
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - Some(()) => (1),
|
||||
LL + Some(()) => 1,
|
||||
|
|
||||
|
||||
error: unnecessary parentheses around match arm expression
|
||||
--> $DIR/issue-92751.rs:5:17
|
||||
|
|
||||
LL | None => (2),
|
||||
| ^ ^
|
||||
|
|
||||
help: remove these parentheses
|
||||
|
|
||||
LL - None => (2),
|
||||
LL + None => 2,
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -3,7 +3,7 @@
|
||||
// error-pattern:this file contains an unclosed delimiter
|
||||
// error-pattern:expected one of
|
||||
// error-pattern:missing `in` in `for` loop
|
||||
// error-pattern:expected `;`, found `e`
|
||||
// error-pattern:expected one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e`
|
||||
|
||||
fn m(){print!("",(c for&g
|
||||
u
|
||||
|
@ -48,19 +48,13 @@ error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found
|
||||
LL | fn m(){print!("",(c for&g
|
||||
| ^^^ expected one of 8 possible tokens
|
||||
|
||||
error: expected `;`, found `e`
|
||||
--> $DIR/issue-88770.rs:10:2
|
||||
error: expected one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e`
|
||||
--> $DIR/issue-88770.rs:11:1
|
||||
|
|
||||
LL | e
|
||||
| ^ help: add `;` here
|
||||
| - expected one of 9 possible tokens
|
||||
LL | e
|
||||
| - unexpected token
|
||||
| ^ unexpected token
|
||||
|
||||
error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `)`
|
||||
--> $DIR/issue-88770.rs:11:3
|
||||
|
|
||||
LL | e
|
||||
| ^ expected one of 7 possible tokens
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
5
src/test/ui/parser/suggest-semi-in-array.rs
Normal file
5
src/test/ui/parser/suggest-semi-in-array.rs
Normal file
@ -0,0 +1,5 @@
|
||||
fn main() {
|
||||
let v = [1
|
||||
2];
|
||||
//~^ ERROR expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found `2`
|
||||
}
|
10
src/test/ui/parser/suggest-semi-in-array.stderr
Normal file
10
src/test/ui/parser/suggest-semi-in-array.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found `2`
|
||||
--> $DIR/suggest-semi-in-array.rs:3:5
|
||||
|
|
||||
LL | let v = [1
|
||||
| - expected one of `,`, `.`, `;`, `?`, `]`, or an operator
|
||||
LL | 2];
|
||||
| ^ unexpected token
|
||||
|
||||
error: aborting due to previous error
|
||||
|
Loading…
x
Reference in New Issue
Block a user