Auto merge of #100416 - Dylan-DPC:rollup-m344lh1, r=Dylan-DPC
Rollup of 11 pull requests Successful merges: - #92744 (Check if enum from foreign crate has any non exhaustive variants when attempting a cast) - #99110 (Determine match_has_guard from candidates instead of looking up thir table again) - #100184 (Stabilize ptr_const_cast) - #100192 ( Remove duplicated temporaries creating during box derefs elaboration) - #100232 (Do not consider method call receiver as an argument in AST.) - #100287 (linux: Use `pthread_setname_np` instead of `prctl`) - #100351 (Use `&mut Diagnostic` instead of `&mut DiagnosticBuilder` unless needed) - #100370 (Remove more Clean trait implementations) - #100391 (Improve size assertions) - #100398 (Improve `-Zhir-stats`) - #100403 (Improve error messages when running rustdoc GUI tests) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
20ffea6938
59 changed files with 954 additions and 474 deletions
|
@ -19,7 +19,6 @@
|
|||
#![feature(rustc_attrs)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(ptr_const_cast)]
|
||||
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
|
|
@ -1338,14 +1338,13 @@ pub enum ExprKind {
|
|||
///
|
||||
/// The `PathSegment` represents the method name and its generic arguments
|
||||
/// (within the angle brackets).
|
||||
/// The first element of the vector of an `Expr` is the expression that evaluates
|
||||
/// to the object on which the method is being called on (the receiver),
|
||||
/// and the remaining elements are the rest of the arguments.
|
||||
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
|
||||
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
|
||||
/// The standalone `Expr` is the receiver expression.
|
||||
/// The vector of `Expr` is the arguments.
|
||||
/// `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
|
||||
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d])`.
|
||||
/// This `Span` is the span of the function, without the dot and receiver
|
||||
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
|
||||
MethodCall(PathSegment, Vec<P<Expr>>, Span),
|
||||
MethodCall(PathSegment, P<Expr>, Vec<P<Expr>>, Span),
|
||||
/// A tuple (e.g., `(a, b, c, d)`).
|
||||
Tup(Vec<P<Expr>>),
|
||||
/// A binary operation (e.g., `a + b`, `a * b`).
|
||||
|
@ -3030,22 +3029,25 @@ pub type ForeignItem = Item<ForeignItemKind>;
|
|||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
mod size_asserts {
|
||||
use super::*;
|
||||
use rustc_data_structures::static_assert_size;
|
||||
// These are in alphabetical order, which is easy to maintain.
|
||||
rustc_data_structures::static_assert_size!(AssocItemKind, 72);
|
||||
rustc_data_structures::static_assert_size!(Attribute, 152);
|
||||
rustc_data_structures::static_assert_size!(Block, 48);
|
||||
rustc_data_structures::static_assert_size!(Expr, 104);
|
||||
rustc_data_structures::static_assert_size!(Fn, 192);
|
||||
rustc_data_structures::static_assert_size!(ForeignItemKind, 72);
|
||||
rustc_data_structures::static_assert_size!(GenericBound, 88);
|
||||
rustc_data_structures::static_assert_size!(Generics, 72);
|
||||
rustc_data_structures::static_assert_size!(Impl, 200);
|
||||
rustc_data_structures::static_assert_size!(Item, 200);
|
||||
rustc_data_structures::static_assert_size!(ItemKind, 112);
|
||||
rustc_data_structures::static_assert_size!(Lit, 48);
|
||||
rustc_data_structures::static_assert_size!(Pat, 120);
|
||||
rustc_data_structures::static_assert_size!(Path, 40);
|
||||
rustc_data_structures::static_assert_size!(PathSegment, 24);
|
||||
rustc_data_structures::static_assert_size!(Stmt, 32);
|
||||
rustc_data_structures::static_assert_size!(Ty, 96);
|
||||
static_assert_size!(AssocItem, 160);
|
||||
static_assert_size!(AssocItemKind, 72);
|
||||
static_assert_size!(Attribute, 152);
|
||||
static_assert_size!(Block, 48);
|
||||
static_assert_size!(Expr, 104);
|
||||
static_assert_size!(Fn, 192);
|
||||
static_assert_size!(ForeignItem, 160);
|
||||
static_assert_size!(ForeignItemKind, 72);
|
||||
static_assert_size!(GenericBound, 88);
|
||||
static_assert_size!(Generics, 72);
|
||||
static_assert_size!(Impl, 200);
|
||||
static_assert_size!(Item, 200);
|
||||
static_assert_size!(ItemKind, 112);
|
||||
static_assert_size!(Lit, 48);
|
||||
static_assert_size!(Pat, 120);
|
||||
static_assert_size!(Path, 40);
|
||||
static_assert_size!(PathSegment, 24);
|
||||
static_assert_size!(Stmt, 32);
|
||||
static_assert_size!(Ty, 96);
|
||||
}
|
||||
|
|
|
@ -1302,10 +1302,11 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||
vis.visit_expr(f);
|
||||
visit_exprs(args, vis);
|
||||
}
|
||||
ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
|
||||
ExprKind::MethodCall(PathSegment { ident, id, args }, receiver, exprs, span) => {
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_id(id);
|
||||
visit_opt(args, |args| vis.visit_generic_args(args));
|
||||
vis.visit_expr(receiver);
|
||||
visit_exprs(exprs, vis);
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
|
|
@ -396,9 +396,9 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
|
|||
contains_exterior_struct_lit(&x)
|
||||
}
|
||||
|
||||
ast::ExprKind::MethodCall(.., ref exprs, _) => {
|
||||
ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
|
||||
// X { y: 1 }.bar(...)
|
||||
contains_exterior_struct_lit(&exprs[0])
|
||||
contains_exterior_struct_lit(&receiver)
|
||||
}
|
||||
|
||||
_ => false,
|
||||
|
|
|
@ -813,8 +813,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||
visitor.visit_expr(callee_expression);
|
||||
walk_list!(visitor, visit_expr, arguments);
|
||||
}
|
||||
ExprKind::MethodCall(ref segment, ref arguments, _span) => {
|
||||
ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => {
|
||||
visitor.visit_path_segment(expression.span, segment);
|
||||
visitor.visit_expr(receiver);
|
||||
walk_list!(visitor, visit_expr, arguments);
|
||||
}
|
||||
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
|
||||
|
|
|
@ -62,7 +62,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::ExprKind::Call(f, self.lower_exprs(args))
|
||||
}
|
||||
}
|
||||
ExprKind::MethodCall(ref seg, ref args, span) => {
|
||||
ExprKind::MethodCall(ref seg, ref receiver, ref args, span) => {
|
||||
let hir_seg = self.arena.alloc(self.lower_path_segment(
|
||||
e.span,
|
||||
seg,
|
||||
|
@ -70,7 +70,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
));
|
||||
let args = self.lower_exprs(args);
|
||||
let args = self.arena.alloc_from_iter(
|
||||
[&*receiver].into_iter().chain(args.iter()).map(|x| self.lower_expr_mut(x)),
|
||||
);
|
||||
hir::ExprKind::MethodCall(hir_seg, args, self.lower_span(span))
|
||||
}
|
||||
ExprKind::Binary(binop, ref lhs, ref rhs) => {
|
||||
|
|
|
@ -13,9 +13,7 @@ use rustc_ast::walk_list;
|
|||
use rustc_ast::*;
|
||||
use rustc_ast_pretty::pprust::{self, State};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{
|
||||
error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
|
||||
};
|
||||
use rustc_errors::{error_code, pluralize, struct_span_err, Applicability, Diagnostic};
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::lint::builtin::{
|
||||
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
|
@ -477,7 +475,7 @@ impl<'a> AstValidator<'a> {
|
|||
ctx: &str,
|
||||
msg: &str,
|
||||
sugg: &str,
|
||||
help: impl FnOnce(&mut DiagnosticBuilder<'_, ErrorGuaranteed>),
|
||||
help: impl FnOnce(&mut Diagnostic),
|
||||
) {
|
||||
let source_map = self.session.source_map();
|
||||
let end = source_map.end_point(sp);
|
||||
|
@ -1196,7 +1194,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
let msg = "free function without a body";
|
||||
let ext = sig.header.ext;
|
||||
|
||||
let f = |e: &mut DiagnosticBuilder<'_, _>| {
|
||||
let f = |e: &mut Diagnostic| {
|
||||
if let Extern::Implicit(start_span) | Extern::Explicit(_, start_span) = &ext
|
||||
{
|
||||
let start_suggestion = if let Extern::Explicit(abi, _) = ext {
|
||||
|
|
|
@ -193,9 +193,13 @@ impl<'a> State<'a> {
|
|||
self.print_call_post(args)
|
||||
}
|
||||
|
||||
fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P<ast::Expr>]) {
|
||||
let base_args = &args[1..];
|
||||
self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
|
||||
fn print_expr_method_call(
|
||||
&mut self,
|
||||
segment: &ast::PathSegment,
|
||||
receiver: &ast::Expr,
|
||||
base_args: &[P<ast::Expr>],
|
||||
) {
|
||||
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
|
||||
self.word(".");
|
||||
self.print_ident(segment.ident);
|
||||
if let Some(ref args) = segment.args {
|
||||
|
@ -303,8 +307,8 @@ impl<'a> State<'a> {
|
|||
ast::ExprKind::Call(ref func, ref args) => {
|
||||
self.print_expr_call(func, &args);
|
||||
}
|
||||
ast::ExprKind::MethodCall(ref segment, ref args, _) => {
|
||||
self.print_expr_method_call(segment, &args);
|
||||
ast::ExprKind::MethodCall(ref segment, ref receiver, ref args, _) => {
|
||||
self.print_expr_method_call(segment, &receiver, &args);
|
||||
}
|
||||
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
|
||||
self.print_expr_binary(op, lhs, rhs);
|
||||
|
|
|
@ -451,7 +451,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
|
||||
fn suggest_borrow_fn_like(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
ty: Ty<'tcx>,
|
||||
move_sites: &[MoveSite],
|
||||
value_name: &str,
|
||||
|
@ -526,12 +526,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
true
|
||||
}
|
||||
|
||||
fn suggest_adding_copy_bounds(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
|
||||
let tcx = self.infcx.tcx;
|
||||
let generics = tcx.generics_of(self.mir_def_id());
|
||||
|
||||
|
|
|
@ -783,7 +783,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
|
||||
fn maybe_suggest_constrain_dyn_trait_impl(
|
||||
&self,
|
||||
diag: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
diag: &mut Diagnostic,
|
||||
f: Region<'tcx>,
|
||||
o: Region<'tcx>,
|
||||
category: &ConstraintCategory<'tcx>,
|
||||
|
|
|
@ -240,8 +240,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
self.manage_cond_expr(prefix);
|
||||
self.manage_cond_expr(suffix);
|
||||
}
|
||||
ExprKind::MethodCall(_, ref mut local_exprs, _) => {
|
||||
for local_expr in local_exprs.iter_mut().skip(1) {
|
||||
ExprKind::MethodCall(_, _,ref mut local_exprs, _) => {
|
||||
for local_expr in local_exprs.iter_mut() {
|
||||
self.manage_cond_expr(local_expr);
|
||||
}
|
||||
}
|
||||
|
@ -377,14 +377,12 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||
id: DUMMY_NODE_ID,
|
||||
ident: Ident::new(sym::try_capture, self.span),
|
||||
},
|
||||
vec![
|
||||
expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)),
|
||||
expr_addr_of_mut(
|
||||
self.cx,
|
||||
self.span,
|
||||
self.cx.expr_path(Path::from_ident(capture)),
|
||||
),
|
||||
],
|
||||
expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)),
|
||||
vec![expr_addr_of_mut(
|
||||
self.cx,
|
||||
self.span,
|
||||
self.cx.expr_path(Path::from_ident(capture)),
|
||||
)],
|
||||
self.span,
|
||||
))
|
||||
.add_trailing_semicolon();
|
||||
|
@ -442,10 +440,11 @@ fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
|
|||
fn expr_method_call(
|
||||
cx: &ExtCtxt<'_>,
|
||||
path: PathSegment,
|
||||
receiver: P<Expr>,
|
||||
args: Vec<P<Expr>>,
|
||||
span: Span,
|
||||
) -> P<Expr> {
|
||||
cx.expr(span, ExprKind::MethodCall(path, args, span))
|
||||
cx.expr(span, ExprKind::MethodCall(path, receiver, args, span))
|
||||
}
|
||||
|
||||
fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
|
||||
|
|
|
@ -823,9 +823,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
mod size_asserts {
|
||||
use super::*;
|
||||
use rustc_data_structures::static_assert_size;
|
||||
// These are in alphabetical order, which is easy to maintain.
|
||||
rustc_data_structures::static_assert_size!(Immediate, 56);
|
||||
rustc_data_structures::static_assert_size!(ImmTy<'_>, 72);
|
||||
rustc_data_structures::static_assert_size!(Operand, 64);
|
||||
rustc_data_structures::static_assert_size!(OpTy<'_>, 88);
|
||||
static_assert_size!(Immediate, 56);
|
||||
static_assert_size!(ImmTy<'_>, 72);
|
||||
static_assert_size!(Operand, 64);
|
||||
static_assert_size!(OpTy<'_>, 88);
|
||||
}
|
||||
|
|
|
@ -891,10 +891,11 @@ where
|
|||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
mod size_asserts {
|
||||
use super::*;
|
||||
use rustc_data_structures::static_assert_size;
|
||||
// These are in alphabetical order, which is easy to maintain.
|
||||
rustc_data_structures::static_assert_size!(MemPlaceMeta, 24);
|
||||
rustc_data_structures::static_assert_size!(MemPlace, 40);
|
||||
rustc_data_structures::static_assert_size!(MPlaceTy<'_>, 64);
|
||||
rustc_data_structures::static_assert_size!(Place, 48);
|
||||
rustc_data_structures::static_assert_size!(PlaceTy<'_>, 72);
|
||||
static_assert_size!(MemPlaceMeta, 24);
|
||||
static_assert_size!(MemPlace, 40);
|
||||
static_assert_size!(MPlaceTy<'_>, 64);
|
||||
static_assert_size!(Place, 48);
|
||||
static_assert_size!(PlaceTy<'_>, 72);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc_ast::{NodeId, DUMMY_NODE_ID};
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{self as attr, TransparencyError};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
|
||||
use rustc_feature::Features;
|
||||
use rustc_lint_defs::builtin::{
|
||||
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
|
||||
|
@ -608,11 +608,7 @@ enum ExplainDocComment {
|
|||
},
|
||||
}
|
||||
|
||||
fn annotate_doc_comment(
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
sm: &SourceMap,
|
||||
span: Span,
|
||||
) {
|
||||
fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) {
|
||||
if let Ok(src) = sm.span_to_snippet(span) {
|
||||
if src.starts_with("///") || src.starts_with("/**") {
|
||||
err.subdiagnostic(ExplainDocComment::Outer { span });
|
||||
|
|
|
@ -3491,16 +3491,16 @@ impl<'hir> Node<'hir> {
|
|||
mod size_asserts {
|
||||
use super::*;
|
||||
// These are in alphabetical order, which is easy to maintain.
|
||||
rustc_data_structures::static_assert_size!(Block<'static>, 48);
|
||||
rustc_data_structures::static_assert_size!(Expr<'static>, 56);
|
||||
rustc_data_structures::static_assert_size!(ForeignItem<'static>, 72);
|
||||
rustc_data_structures::static_assert_size!(GenericBound<'_>, 48);
|
||||
rustc_data_structures::static_assert_size!(Generics<'static>, 56);
|
||||
rustc_data_structures::static_assert_size!(ImplItem<'static>, 88);
|
||||
rustc_data_structures::static_assert_size!(Impl<'static>, 80);
|
||||
rustc_data_structures::static_assert_size!(Item<'static>, 80);
|
||||
rustc_data_structures::static_assert_size!(Pat<'static>, 88);
|
||||
rustc_data_structures::static_assert_size!(QPath<'static>, 24);
|
||||
rustc_data_structures::static_assert_size!(TraitItem<'static>, 96);
|
||||
rustc_data_structures::static_assert_size!(Ty<'static>, 72);
|
||||
static_assert_size!(Block<'static>, 48);
|
||||
static_assert_size!(Expr<'static>, 56);
|
||||
static_assert_size!(ForeignItem<'static>, 72);
|
||||
static_assert_size!(GenericBound<'_>, 48);
|
||||
static_assert_size!(Generics<'static>, 56);
|
||||
static_assert_size!(ImplItem<'static>, 88);
|
||||
static_assert_size!(Impl<'static>, 80);
|
||||
static_assert_size!(Item<'static>, 80);
|
||||
static_assert_size!(Pat<'static>, 88);
|
||||
static_assert_size!(QPath<'static>, 24);
|
||||
static_assert_size!(TraitItem<'static>, 96);
|
||||
static_assert_size!(Ty<'static>, 72);
|
||||
}
|
||||
|
|
|
@ -608,8 +608,7 @@ trait UnusedDelimLint {
|
|||
ref call_or_other => {
|
||||
let (args_to_check, ctx) = match *call_or_other {
|
||||
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
|
||||
// first "argument" is self (which sometimes needs delims)
|
||||
MethodCall(_, ref args, _) => (&args[1..], UnusedDelimsCtx::MethodArg),
|
||||
MethodCall(_, _, ref args, _) => (&args[..], UnusedDelimsCtx::MethodArg),
|
||||
// actual catch-all arm
|
||||
_ => {
|
||||
return;
|
||||
|
|
|
@ -814,8 +814,8 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
|
|||
mod size_asserts {
|
||||
use super::*;
|
||||
// These are in alphabetical order, which is easy to maintain.
|
||||
rustc_data_structures::static_assert_size!(Block, 56);
|
||||
rustc_data_structures::static_assert_size!(Expr<'_>, 104);
|
||||
rustc_data_structures::static_assert_size!(Pat<'_>, 24);
|
||||
rustc_data_structures::static_assert_size!(Stmt<'_>, 120);
|
||||
static_assert_size!(Block, 56);
|
||||
static_assert_size!(Expr<'_>, 104);
|
||||
static_assert_size!(Pat<'_>, 24);
|
||||
static_assert_size!(Stmt<'_>, 120);
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
|
||||
let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
|
||||
|
||||
let match_has_guard = arms.iter().copied().any(|arm| self.thir[arm].guard.is_some());
|
||||
let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard);
|
||||
let mut candidates =
|
||||
arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
|
||||
|
||||
|
|
|
@ -70,7 +70,6 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> {
|
|||
build_ptr_tys(tcx, base_ty.boxed_ty(), self.unique_did, self.nonnull_did);
|
||||
|
||||
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
|
||||
self.local_decls.push(LocalDecl::new(ptr_ty, source_info.span));
|
||||
|
||||
self.patch.add_statement(location, StatementKind::StorageLive(ptr_local));
|
||||
|
||||
|
@ -125,13 +124,6 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
|
|||
index += 1;
|
||||
}
|
||||
|
||||
if let Some(terminator) = terminator
|
||||
&& !matches!(terminator.kind, TerminatorKind::Yield{..})
|
||||
{
|
||||
let location = Location { block, statement_index: index };
|
||||
visitor.visit_terminator(terminator, location);
|
||||
}
|
||||
|
||||
let location = Location { block, statement_index: index };
|
||||
match terminator {
|
||||
// yielding into a box is handled when lowering generators
|
||||
|
|
|
@ -19,7 +19,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_errors::{
|
||||
fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
|
||||
};
|
||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, EmissionGuarantee, ErrorGuaranteed};
|
||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
|
||||
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
|
@ -228,13 +228,13 @@ struct MultiSugg {
|
|||
}
|
||||
|
||||
impl MultiSugg {
|
||||
fn emit<G: EmissionGuarantee>(self, err: &mut DiagnosticBuilder<'_, G>) {
|
||||
fn emit(self, err: &mut Diagnostic) {
|
||||
err.multipart_suggestion(&self.msg, self.patches, self.applicability);
|
||||
}
|
||||
|
||||
/// Overrides individual messages and applicabilities.
|
||||
fn emit_many<G: EmissionGuarantee>(
|
||||
err: &mut DiagnosticBuilder<'_, G>,
|
||||
fn emit_many(
|
||||
err: &mut Diagnostic,
|
||||
msg: &str,
|
||||
applicability: Applicability,
|
||||
suggestions: impl Iterator<Item = Self>,
|
||||
|
|
|
@ -850,7 +850,7 @@ impl<'a> Parser<'a> {
|
|||
ExprKind::Index(_, _) => "indexing",
|
||||
ExprKind::Try(_) => "`?`",
|
||||
ExprKind::Field(_, _) => "a field access",
|
||||
ExprKind::MethodCall(_, _, _) => "a method call",
|
||||
ExprKind::MethodCall(_, _, _, _) => "a method call",
|
||||
ExprKind::Call(_, _) => "a function call",
|
||||
ExprKind::Await(_) => "`.await`",
|
||||
ExprKind::Err => return Ok(with_postfix),
|
||||
|
@ -859,7 +859,7 @@ impl<'a> Parser<'a> {
|
|||
);
|
||||
let mut err = self.struct_span_err(span, &msg);
|
||||
|
||||
let suggest_parens = |err: &mut DiagnosticBuilder<'_, _>| {
|
||||
let suggest_parens = |err: &mut Diagnostic| {
|
||||
let suggestions = vec![
|
||||
(span.shrink_to_lo(), "(".to_string()),
|
||||
(span.shrink_to_hi(), ")".to_string()),
|
||||
|
@ -1280,12 +1280,14 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
|
||||
// Method call `expr.f()`
|
||||
let mut args = self.parse_paren_expr_seq()?;
|
||||
args.insert(0, self_arg);
|
||||
|
||||
let args = self.parse_paren_expr_seq()?;
|
||||
let fn_span = fn_span_lo.to(self.prev_token.span);
|
||||
let span = lo.to(self.prev_token.span);
|
||||
Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args, fn_span), AttrVec::new()))
|
||||
Ok(self.mk_expr(
|
||||
span,
|
||||
ExprKind::MethodCall(segment, self_arg, args, fn_span),
|
||||
AttrVec::new(),
|
||||
))
|
||||
} else {
|
||||
// Field access `expr.f`
|
||||
if let Some(args) = segment.args {
|
||||
|
|
|
@ -21,21 +21,55 @@ enum Id {
|
|||
None,
|
||||
}
|
||||
|
||||
struct NodeData {
|
||||
struct NodeStats {
|
||||
count: usize,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl NodeStats {
|
||||
fn new() -> NodeStats {
|
||||
NodeStats { count: 0, size: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
struct Node {
|
||||
stats: NodeStats,
|
||||
subnodes: FxHashMap<&'static str, NodeStats>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
fn new() -> Node {
|
||||
Node { stats: NodeStats::new(), subnodes: FxHashMap::default() }
|
||||
}
|
||||
}
|
||||
|
||||
/// This type measures the size of AST and HIR nodes, by implementing the AST
|
||||
/// and HIR `Visitor` traits. But we don't measure every visited type because
|
||||
/// that could cause double counting.
|
||||
///
|
||||
/// For example, `ast::Visitor` has `visit_ident`, but `Ident`s are always
|
||||
/// stored inline within other AST nodes, so we don't implement `visit_ident`
|
||||
/// here. In constrast, we do implement `visit_expr` because `ast::Expr` is
|
||||
/// always stored as `P<ast::Expr>`, and every such expression should be
|
||||
/// measured separately.
|
||||
///
|
||||
/// In general, a `visit_foo` method should be implemented here if the
|
||||
/// corresponding `Foo` type is always stored on its own, e.g.: `P<Foo>`,
|
||||
/// `Box<Foo>`, `Vec<Foo>`, `Box<[Foo]>`.
|
||||
///
|
||||
/// There are some types in the AST and HIR tree that the visitors do not have
|
||||
/// a `visit_*` method for, and so we cannot measure these, which is
|
||||
/// unfortunate.
|
||||
struct StatCollector<'k> {
|
||||
krate: Option<Map<'k>>,
|
||||
data: FxHashMap<&'static str, NodeData>,
|
||||
nodes: FxHashMap<&'static str, Node>,
|
||||
seen: FxHashSet<Id>,
|
||||
}
|
||||
|
||||
pub fn print_hir_stats(tcx: TyCtxt<'_>) {
|
||||
let mut collector = StatCollector {
|
||||
krate: Some(tcx.hir()),
|
||||
data: FxHashMap::default(),
|
||||
nodes: FxHashMap::default(),
|
||||
seen: FxHashSet::default(),
|
||||
};
|
||||
tcx.hir().walk_toplevel_module(&mut collector);
|
||||
|
@ -44,49 +78,88 @@ pub fn print_hir_stats(tcx: TyCtxt<'_>) {
|
|||
}
|
||||
|
||||
pub fn print_ast_stats(krate: &ast::Crate, title: &str) {
|
||||
use rustc_ast::visit::Visitor;
|
||||
|
||||
let mut collector =
|
||||
StatCollector { krate: None, data: FxHashMap::default(), seen: FxHashSet::default() };
|
||||
ast_visit::walk_crate(&mut collector, krate);
|
||||
StatCollector { krate: None, nodes: FxHashMap::default(), seen: FxHashSet::default() };
|
||||
collector.visit_crate(krate);
|
||||
collector.print(title);
|
||||
}
|
||||
|
||||
impl<'k> StatCollector<'k> {
|
||||
fn record<T>(&mut self, label: &'static str, id: Id, node: &T) {
|
||||
// Record a top-level node.
|
||||
fn record<T>(&mut self, label: &'static str, id: Id, val: &T) {
|
||||
self.record_inner(label, None, id, val);
|
||||
}
|
||||
|
||||
// Record a two-level entry, with a top-level enum type and a variant.
|
||||
fn record_variant<T>(&mut self, label1: &'static str, label2: &'static str, id: Id, val: &T) {
|
||||
self.record_inner(label1, Some(label2), id, val);
|
||||
}
|
||||
|
||||
fn record_inner<T>(
|
||||
&mut self,
|
||||
label1: &'static str,
|
||||
label2: Option<&'static str>,
|
||||
id: Id,
|
||||
val: &T,
|
||||
) {
|
||||
if id != Id::None && !self.seen.insert(id) {
|
||||
return;
|
||||
}
|
||||
|
||||
let entry = self.data.entry(label).or_insert(NodeData { count: 0, size: 0 });
|
||||
let node = self.nodes.entry(label1).or_insert(Node::new());
|
||||
node.stats.count += 1;
|
||||
node.stats.size = std::mem::size_of_val(val);
|
||||
|
||||
entry.count += 1;
|
||||
entry.size = std::mem::size_of_val(node);
|
||||
if let Some(label2) = label2 {
|
||||
let subnode = node.subnodes.entry(label2).or_insert(NodeStats::new());
|
||||
subnode.count += 1;
|
||||
subnode.size = std::mem::size_of_val(val);
|
||||
}
|
||||
}
|
||||
|
||||
fn print(&self, title: &str) {
|
||||
let mut stats: Vec<_> = self.data.iter().collect();
|
||||
let mut nodes: Vec<_> = self.nodes.iter().collect();
|
||||
nodes.sort_by_key(|&(_, ref node)| node.stats.count * node.stats.size);
|
||||
|
||||
stats.sort_by_key(|&(_, ref d)| d.count * d.size);
|
||||
|
||||
let mut total_size = 0;
|
||||
let total_size = nodes.iter().map(|(_, node)| node.stats.count * node.stats.size).sum();
|
||||
|
||||
eprintln!("\n{}\n", title);
|
||||
|
||||
eprintln!("{:<18}{:>18}{:>14}{:>14}", "Name", "Accumulated Size", "Count", "Item Size");
|
||||
eprintln!("----------------------------------------------------------------");
|
||||
|
||||
for (label, data) in stats {
|
||||
eprintln!(
|
||||
"{:<18}{:>18}{:>14}{:>14}",
|
||||
label,
|
||||
to_readable_str(data.count * data.size),
|
||||
to_readable_str(data.count),
|
||||
to_readable_str(data.size)
|
||||
);
|
||||
let percent = |m, n| (m * 100) as f64 / n as f64;
|
||||
|
||||
total_size += data.count * data.size;
|
||||
for (label, node) in nodes {
|
||||
let size = node.stats.count * node.stats.size;
|
||||
eprintln!(
|
||||
"{:<18}{:>10} ({:4.1}%){:>14}{:>14}",
|
||||
label,
|
||||
to_readable_str(size),
|
||||
percent(size, total_size),
|
||||
to_readable_str(node.stats.count),
|
||||
to_readable_str(node.stats.size)
|
||||
);
|
||||
if !node.subnodes.is_empty() {
|
||||
let mut subnodes: Vec<_> = node.subnodes.iter().collect();
|
||||
subnodes.sort_by_key(|&(_, ref subnode)| subnode.count * subnode.size);
|
||||
|
||||
for (label, subnode) in subnodes {
|
||||
let size = subnode.count * subnode.size;
|
||||
eprintln!(
|
||||
"- {:<18}{:>10} ({:4.1}%){:>14}",
|
||||
label,
|
||||
to_readable_str(size),
|
||||
percent(size, total_size),
|
||||
to_readable_str(subnode.count),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
eprintln!("----------------------------------------------------------------");
|
||||
eprintln!("{:<18}{:>18}\n", "Total", to_readable_str(total_size));
|
||||
eprintln!("{:<18}{:>10}\n", "Total", to_readable_str(total_size));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,6 +301,10 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
hir_visit::walk_path(self, path)
|
||||
}
|
||||
|
||||
// `PathSegment` has one inline use (in `ast::ExprKind::MethodCall`) and
|
||||
// one non-inline use (in `Path::segments`). The latter case is more common
|
||||
// than the former case, so we implement this visitor and tolerate the
|
||||
// double counting in the former case.
|
||||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v hir::PathSegment<'v>) {
|
||||
self.record("PathSegment", Id::None, path_segment);
|
||||
hir_visit::walk_path_segment(self, path_span, path_segment)
|
||||
|
@ -243,14 +320,54 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
|
|||
}
|
||||
}
|
||||
|
||||
// Used to avoid boilerplate for types with many variants.
|
||||
macro_rules! record_variants {
|
||||
(
|
||||
($self:ident, $val:expr, $kind:expr, $ty:ty, $tykind:ident), // mandatory pieces
|
||||
[$($variant:ident),*]
|
||||
) => {
|
||||
match $kind {
|
||||
$(
|
||||
ast::$tykind::$variant { .. } => {
|
||||
$self.record_variant(stringify!($ty), stringify!($variant), Id::None, $val)
|
||||
}
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
||||
fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) {
|
||||
self.record("ForeignItem", Id::None, i);
|
||||
record_variants!(
|
||||
(self, i, i.kind, ForeignItem, ForeignItemKind),
|
||||
[Static, Fn, TyAlias, MacCall]
|
||||
);
|
||||
ast_visit::walk_foreign_item(self, i)
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, i: &'v ast::Item) {
|
||||
self.record("Item", Id::None, i);
|
||||
record_variants!(
|
||||
(self, i, i.kind, Item, ItemKind),
|
||||
[
|
||||
ExternCrate,
|
||||
Use,
|
||||
Static,
|
||||
Const,
|
||||
Fn,
|
||||
Mod,
|
||||
ForeignMod,
|
||||
GlobalAsm,
|
||||
TyAlias,
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
Trait,
|
||||
TraitAlias,
|
||||
Impl,
|
||||
MacCall,
|
||||
MacroDef
|
||||
]
|
||||
);
|
||||
ast_visit::walk_item(self, i)
|
||||
}
|
||||
|
||||
|
@ -265,47 +382,116 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
}
|
||||
|
||||
fn visit_stmt(&mut self, s: &'v ast::Stmt) {
|
||||
self.record("Stmt", Id::None, s);
|
||||
record_variants!(
|
||||
(self, s, s.kind, Stmt, StmtKind),
|
||||
[Local, Item, Expr, Semi, Empty, MacCall]
|
||||
);
|
||||
ast_visit::walk_stmt(self, s)
|
||||
}
|
||||
|
||||
fn visit_param(&mut self, p: &'v ast::Param) {
|
||||
self.record("Param", Id::None, p);
|
||||
ast_visit::walk_param(self, p)
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, a: &'v ast::Arm) {
|
||||
self.record("Arm", Id::None, a);
|
||||
ast_visit::walk_arm(self, a)
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, p: &'v ast::Pat) {
|
||||
self.record("Pat", Id::None, p);
|
||||
record_variants!(
|
||||
(self, p, p.kind, Pat, PatKind),
|
||||
[
|
||||
Wild,
|
||||
Ident,
|
||||
Struct,
|
||||
TupleStruct,
|
||||
Or,
|
||||
Path,
|
||||
Tuple,
|
||||
Box,
|
||||
Ref,
|
||||
Lit,
|
||||
Range,
|
||||
Slice,
|
||||
Rest,
|
||||
Paren,
|
||||
MacCall
|
||||
]
|
||||
);
|
||||
ast_visit::walk_pat(self, p)
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, ex: &'v ast::Expr) {
|
||||
self.record("Expr", Id::None, ex);
|
||||
ast_visit::walk_expr(self, ex)
|
||||
fn visit_expr(&mut self, e: &'v ast::Expr) {
|
||||
record_variants!(
|
||||
(self, e, e.kind, Expr, ExprKind),
|
||||
[
|
||||
Box, Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
|
||||
If, While, ForLoop, Loop, Match, Closure, Block, Async, Await, TryBlock, Assign,
|
||||
AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret,
|
||||
InlineAsm, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, Err
|
||||
]
|
||||
);
|
||||
ast_visit::walk_expr(self, e)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'v ast::Ty) {
|
||||
self.record("Ty", Id::None, t);
|
||||
record_variants!(
|
||||
(self, t, t.kind, Ty, TyKind),
|
||||
[
|
||||
Slice,
|
||||
Array,
|
||||
Ptr,
|
||||
Rptr,
|
||||
BareFn,
|
||||
Never,
|
||||
Tup,
|
||||
Path,
|
||||
TraitObject,
|
||||
ImplTrait,
|
||||
Paren,
|
||||
Typeof,
|
||||
Infer,
|
||||
ImplicitSelf,
|
||||
MacCall,
|
||||
Err,
|
||||
CVarArgs
|
||||
]
|
||||
);
|
||||
|
||||
ast_visit::walk_ty(self, t)
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, g: &'v ast::GenericParam) {
|
||||
self.record("GenericParam", Id::None, g);
|
||||
ast_visit::walk_generic_param(self, g)
|
||||
}
|
||||
|
||||
fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) {
|
||||
record_variants!(
|
||||
(self, p, p, WherePredicate, WherePredicate),
|
||||
[BoundPredicate, RegionPredicate, EqPredicate]
|
||||
);
|
||||
ast_visit::walk_where_predicate(self, p)
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, s: Span, _: NodeId) {
|
||||
self.record("FnDecl", Id::None, fk.decl());
|
||||
ast_visit::walk_fn(self, fk, s)
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
let label = match ctxt {
|
||||
ast_visit::AssocCtxt::Trait => "TraitItem",
|
||||
ast_visit::AssocCtxt::Impl => "ImplItem",
|
||||
};
|
||||
self.record(label, Id::None, item);
|
||||
ast_visit::walk_assoc_item(self, item, ctxt);
|
||||
fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
record_variants!(
|
||||
(self, i, i.kind, AssocItem, AssocItemKind),
|
||||
[Const, Fn, TyAlias, MacCall]
|
||||
);
|
||||
ast_visit::walk_assoc_item(self, i, ctxt);
|
||||
}
|
||||
|
||||
fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound, _ctxt: BoundKind) {
|
||||
self.record("GenericBound", Id::None, bounds);
|
||||
ast_visit::walk_param_bound(self, bounds)
|
||||
fn visit_param_bound(&mut self, b: &'v ast::GenericBound, _ctxt: BoundKind) {
|
||||
record_variants!((self, b, b, GenericBound, GenericBound), [Trait, Outlives]);
|
||||
ast_visit::walk_param_bound(self, b)
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'v ast::FieldDef) {
|
||||
|
@ -318,27 +504,42 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
|
|||
ast_visit::walk_variant(self, v)
|
||||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lifetime: &'v ast::Lifetime, _: ast_visit::LifetimeCtxt) {
|
||||
self.record("Lifetime", Id::None, lifetime);
|
||||
ast_visit::walk_lifetime(self, lifetime)
|
||||
}
|
||||
|
||||
fn visit_mac_call(&mut self, mac: &'v ast::MacCall) {
|
||||
self.record("MacCall", Id::None, mac);
|
||||
ast_visit::walk_mac(self, mac)
|
||||
}
|
||||
// `UseTree` has one inline use (in `ast::ItemKind::Use`) and one
|
||||
// non-inline use (in `ast::UseTreeKind::Nested). The former case is more
|
||||
// common, so we don't implement `visit_use_tree` and tolerate the missed
|
||||
// coverage in the latter case.
|
||||
|
||||
fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v ast::PathSegment) {
|
||||
self.record("PathSegment", Id::None, path_segment);
|
||||
ast_visit::walk_path_segment(self, path_span, path_segment)
|
||||
}
|
||||
|
||||
fn visit_assoc_constraint(&mut self, constraint: &'v ast::AssocConstraint) {
|
||||
self.record("AssocConstraint", Id::None, constraint);
|
||||
ast_visit::walk_assoc_constraint(self, constraint)
|
||||
// `GenericArgs` has one inline use (in `ast::AssocConstraint::gen_args`) and one
|
||||
// non-inline use (in `ast::PathSegment::args`). The latter case is more
|
||||
// common, so we implement `visit_generic_args` and tolerate the double
|
||||
// counting in the former case.
|
||||
fn visit_generic_args(&mut self, sp: Span, g: &'v ast::GenericArgs) {
|
||||
record_variants!((self, g, g, GenericArgs, GenericArgs), [AngleBracketed, Parenthesized]);
|
||||
ast_visit::walk_generic_args(self, sp, g)
|
||||
}
|
||||
|
||||
fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
|
||||
self.record("Attribute", Id::None, attr);
|
||||
record_variants!((self, attr, attr.kind, Attribute, AttrKind), [Normal, DocComment]);
|
||||
ast_visit::walk_attribute(self, attr)
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, f: &'v ast::ExprField) {
|
||||
self.record("ExprField", Id::None, f);
|
||||
ast_visit::walk_expr_field(self, f)
|
||||
}
|
||||
|
||||
fn visit_crate(&mut self, krate: &'v ast::Crate) {
|
||||
self.record("Crate", Id::None, krate);
|
||||
ast_visit::walk_crate(self, krate)
|
||||
}
|
||||
|
||||
fn visit_inline_asm(&mut self, asm: &'v ast::InlineAsm) {
|
||||
self.record("InlineAsm", Id::None, asm);
|
||||
ast_visit::walk_inline_asm(self, asm)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3796,9 +3796,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
ExprKind::Field(ref subexpression, _) => {
|
||||
self.resolve_expr(subexpression, Some(expr));
|
||||
}
|
||||
ExprKind::MethodCall(ref segment, ref arguments, _) => {
|
||||
let mut arguments = arguments.iter();
|
||||
self.resolve_expr(arguments.next().unwrap(), Some(expr));
|
||||
ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _) => {
|
||||
self.resolve_expr(receiver, Some(expr));
|
||||
for argument in arguments {
|
||||
self.resolve_expr(argument, None);
|
||||
}
|
||||
|
|
|
@ -2021,9 +2021,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
|||
|
||||
fn suggest_introducing_lifetime(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
name: Option<&str>,
|
||||
suggest: impl Fn(&mut DiagnosticBuilder<'_, ErrorGuaranteed>, bool, Span, &str, String) -> bool,
|
||||
suggest: impl Fn(&mut Diagnostic, bool, Span, &str, String) -> bool,
|
||||
) {
|
||||
let mut suggest_note = true;
|
||||
for rib in self.lifetime_ribs.iter().rev() {
|
||||
|
@ -2149,7 +2149,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
|
|||
|
||||
pub(crate) fn add_missing_lifetime_specifiers_label(
|
||||
&mut self,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
lifetime_refs: Vec<MissingLifetime>,
|
||||
function_param_lifetimes: Option<(Vec<MissingLifetime>, Vec<ElisionFnParameter>)>,
|
||||
) {
|
||||
|
|
|
@ -16,7 +16,8 @@ use crate::require_c_abi_if_c_variadic;
|
|||
use rustc_ast::TraitObjectSyntax;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{
|
||||
struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan,
|
||||
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
|
||||
MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
||||
|
@ -2106,7 +2107,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
pub fn prohibit_generics<'a>(
|
||||
&self,
|
||||
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
|
||||
extend: impl Fn(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>),
|
||||
extend: impl Fn(&mut Diagnostic),
|
||||
) -> bool {
|
||||
let args = segments.clone().flat_map(|segment| segment.args().args);
|
||||
|
||||
|
@ -2984,11 +2985,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
}
|
||||
|
||||
/// Make sure that we are in the condition to suggest the blanket implementation.
|
||||
fn maybe_lint_blanket_trait_impl<T: rustc_errors::EmissionGuarantee>(
|
||||
&self,
|
||||
self_ty: &hir::Ty<'_>,
|
||||
diag: &mut DiagnosticBuilder<'_, T>,
|
||||
) {
|
||||
fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) {
|
||||
let tcx = self.tcx();
|
||||
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id);
|
||||
if let hir::Node::Item(hir::Item {
|
||||
|
@ -3081,7 +3078,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||
sugg,
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
self.maybe_lint_blanket_trait_impl::<()>(&self_ty, &mut diag);
|
||||
self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
|
||||
diag.emit();
|
||||
},
|
||||
);
|
||||
|
|
|
@ -32,6 +32,7 @@ use super::FnCtxt;
|
|||
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::type_error_struct;
|
||||
use hir::def_id::LOCAL_CRATE;
|
||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
|
@ -40,7 +41,7 @@ use rustc_middle::ty::adjustment::AllowTwoPhase;
|
|||
use rustc_middle::ty::cast::{CastKind, CastTy};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable};
|
||||
use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef};
|
||||
use rustc_session::lint;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
|
@ -173,6 +174,7 @@ pub enum CastError {
|
|||
/// or "a length". If this argument is None, then the metadata is unknown, for example,
|
||||
/// when we're typechecking a type parameter with a ?Sized bound.
|
||||
IntToFatCast(Option<&'static str>),
|
||||
ForeignNonExhaustiveAdt,
|
||||
}
|
||||
|
||||
impl From<ErrorGuaranteed> for CastError {
|
||||
|
@ -591,6 +593,17 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
}
|
||||
err.emit();
|
||||
}
|
||||
CastError::ForeignNonExhaustiveAdt => {
|
||||
make_invalid_casting_error(
|
||||
fcx.tcx.sess,
|
||||
self.span,
|
||||
self.expr_ty,
|
||||
self.cast_ty,
|
||||
fcx,
|
||||
)
|
||||
.note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,6 +802,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
_ => return Err(CastError::NonScalar),
|
||||
};
|
||||
|
||||
if let ty::Adt(adt_def, _) = *self.expr_ty.kind() {
|
||||
if adt_def.did().krate != LOCAL_CRATE {
|
||||
if adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) {
|
||||
return Err(CastError::ForeignNonExhaustiveAdt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match (t_from, t_cast) {
|
||||
// These types have invariants! can't cast into them.
|
||||
(_, Int(CEnum) | FnPtr) => Err(CastError::NonScalar),
|
||||
|
|
|
@ -1525,9 +1525,7 @@ fn detect_discriminant_duplicate<'tcx>(
|
|||
) {
|
||||
// Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate.
|
||||
// Here `idx` refers to the order of which the discriminant appears, and its index in `vs`
|
||||
let report = |dis: Discr<'tcx>,
|
||||
idx: usize,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>| {
|
||||
let report = |dis: Discr<'tcx>, idx: usize, err: &mut Diagnostic| {
|
||||
let var = &vs[idx]; // HIR for the duplicate discriminant
|
||||
let (span, display_discr) = match var.disr_expr {
|
||||
Some(ref expr) => {
|
||||
|
|
|
@ -1585,9 +1585,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn note_unreachable_loop_return<'a>(
|
||||
fn note_unreachable_loop_return(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>,
|
||||
) {
|
||||
|
|
|
@ -28,7 +28,7 @@ use rustc_data_structures::fx::FxHashMap;
|
|||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{
|
||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
|
||||
EmissionGuarantee, ErrorGuaranteed,
|
||||
ErrorGuaranteed,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
|
@ -879,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
lhs: &'tcx hir::Expr<'tcx>,
|
||||
err_code: &'static str,
|
||||
op_span: Span,
|
||||
adjust_err: impl FnOnce(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>),
|
||||
adjust_err: impl FnOnce(&mut Diagnostic),
|
||||
) {
|
||||
if lhs.is_syntactic_place_expr() {
|
||||
return;
|
||||
|
@ -1089,8 +1089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
||||
|
||||
let suggest_deref_binop = |err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
rhs_ty: Ty<'tcx>| {
|
||||
let suggest_deref_binop = |err: &mut Diagnostic, rhs_ty: Ty<'tcx>| {
|
||||
if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
|
||||
// Can only assign if the type is sized, so if `DerefMut` yields a type that is
|
||||
// unsized, do not suggest dereferencing it.
|
||||
|
@ -2205,9 +2204,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.tcx().ty_error()
|
||||
}
|
||||
|
||||
fn check_call_constructor<G: EmissionGuarantee>(
|
||||
fn check_call_constructor(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_, G>,
|
||||
err: &mut Diagnostic,
|
||||
base: &'tcx hir::Expr<'tcx>,
|
||||
def_id: DefId,
|
||||
) {
|
||||
|
|
|
@ -1778,7 +1778,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
fn label_fn_like(
|
||||
&self,
|
||||
err: &mut rustc_errors::DiagnosticBuilder<'tcx, rustc_errors::ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
callable_def_id: Option<DefId>,
|
||||
callee_ty: Option<Ty<'tcx>>,
|
||||
) {
|
||||
|
|
|
@ -904,7 +904,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let label_span_not_found = |err: &mut DiagnosticBuilder<'_, _>| {
|
||||
let label_span_not_found = |err: &mut Diagnostic| {
|
||||
if unsatisfied_predicates.is_empty() {
|
||||
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
|
||||
let is_string_or_ref_str = match actual.kind() {
|
||||
|
@ -1154,7 +1154,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
rcvr_ty: Ty<'tcx>,
|
||||
expr: &hir::Expr<'_>,
|
||||
item_name: Ident,
|
||||
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
) -> bool {
|
||||
let tcx = self.tcx;
|
||||
let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
|
||||
|
@ -1331,7 +1331,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
fn check_for_field_method(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
source: SelfSource<'tcx>,
|
||||
span: Span,
|
||||
actual: Ty<'tcx>,
|
||||
|
@ -1380,7 +1380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
fn check_for_unwrap_self(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||
err: &mut Diagnostic,
|
||||
source: SelfSource<'tcx>,
|
||||
span: Span,
|
||||
actual: Ty<'tcx>,
|
||||
|
|
|
@ -104,7 +104,7 @@ use crate::astconv::AstConv;
|
|||
use crate::check::gather_locals::GatherLocalsVisitor;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{
|
||||
pluralize, struct_span_err, Applicability, DiagnosticBuilder, EmissionGuarantee, MultiSpan,
|
||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
|
@ -973,12 +973,7 @@ fn has_expected_num_generic_args<'tcx>(
|
|||
/// * `span` - The span of the snippet
|
||||
/// * `params` - The number of parameters the constructor accepts
|
||||
/// * `err` - A mutable diagnostic builder to add the suggestion to
|
||||
fn suggest_call_constructor<G: EmissionGuarantee>(
|
||||
span: Span,
|
||||
kind: CtorOf,
|
||||
params: usize,
|
||||
err: &mut DiagnosticBuilder<'_, G>,
|
||||
) {
|
||||
fn suggest_call_constructor(span: Span, kind: CtorOf, params: usize, err: &mut Diagnostic) {
|
||||
// Note: tuple-structs don't have named fields, so just use placeholders
|
||||
let args = vec!["_"; params].join(", ");
|
||||
let applicable = if params > 0 {
|
||||
|
|
|
@ -59,7 +59,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
{
|
||||
// Suppress this error, since we already emitted
|
||||
// a deref suggestion in check_overloaded_binop
|
||||
err.delay_as_bug();
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -95,8 +95,8 @@ impl<T: ?Sized> *const T {
|
|||
///
|
||||
/// This is a bit safer than `as` because it wouldn't silently change the type if the code is
|
||||
/// refactored.
|
||||
#[unstable(feature = "ptr_const_cast", issue = "92675")]
|
||||
#[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")]
|
||||
#[stable(feature = "ptr_const_cast", since = "1.65.0")]
|
||||
#[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
|
||||
pub const fn cast_mut(self) -> *mut T {
|
||||
self as _
|
||||
}
|
||||
|
|
|
@ -100,8 +100,8 @@ impl<T: ?Sized> *mut T {
|
|||
/// coercion.
|
||||
///
|
||||
/// [`cast_mut`]: #method.cast_mut
|
||||
#[unstable(feature = "ptr_const_cast", issue = "92675")]
|
||||
#[rustc_const_unstable(feature = "ptr_const_cast", issue = "92675")]
|
||||
#[stable(feature = "ptr_const_cast", since = "1.65.0")]
|
||||
#[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
|
||||
pub const fn cast_const(self) -> *const T {
|
||||
self as _
|
||||
}
|
||||
|
|
|
@ -116,11 +116,9 @@ impl Thread {
|
|||
debug_assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
#[cfg(target_os = "android")]
|
||||
pub fn set_name(name: &CStr) {
|
||||
const PR_SET_NAME: libc::c_int = 15;
|
||||
// pthread wrapper only appeared in glibc 2.12, so we use syscall
|
||||
// directly.
|
||||
unsafe {
|
||||
libc::prctl(
|
||||
PR_SET_NAME,
|
||||
|
@ -132,6 +130,14 @@ impl Thread {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn set_name(name: &CStr) {
|
||||
unsafe {
|
||||
// Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
|
||||
libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
|
||||
pub fn set_name(name: &CStr) {
|
||||
unsafe {
|
||||
|
|
|
@ -924,6 +924,11 @@ fn compare_browser_ui_test_version(installed_version: &str, src: &Path) {
|
|||
one used in the CI (`{}`)",
|
||||
installed_version, v
|
||||
);
|
||||
eprintln!(
|
||||
"You can install this version using `npm update browser-ui-test` or by using \
|
||||
`npm install browser-ui-test@{}`",
|
||||
v,
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => eprintln!("Couldn't find the CI browser-ui-test version: {:?}", e),
|
||||
|
|
|
@ -120,7 +120,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
|
|||
items: cx.tcx
|
||||
.associated_items(impl_def_id)
|
||||
.in_definition_order()
|
||||
.map(|x| x.clean(cx))
|
||||
.map(|x| clean_middle_assoc_item(x, cx))
|
||||
.collect::<Vec<_>>(),
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
kind: ImplKind::Blanket(Box::new(clean_middle_ty(trait_ref.0.self_ty(), cx, None))),
|
||||
|
|
|
@ -16,9 +16,10 @@ use rustc_span::hygiene::MacroKind;
|
|||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
|
||||
use crate::clean::{
|
||||
self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_field,
|
||||
clean_middle_ty, clean_trait_ref_with_bindings, clean_ty, clean_ty_generics, clean_variant_def,
|
||||
clean_visibility, utils, Attributes, AttributesExt, Clean, ImplKind, ItemId, Type, Visibility,
|
||||
self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item,
|
||||
clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty,
|
||||
clean_ty_generics, clean_variant_def, clean_visibility, utils, Attributes, AttributesExt,
|
||||
ImplKind, ItemId, Type, Visibility,
|
||||
};
|
||||
use crate::core::DocContext;
|
||||
use crate::formats::item_type::ItemType;
|
||||
|
@ -217,7 +218,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
|
|||
// which causes methods to have a `pub` prefix, which is invalid since items in traits
|
||||
// can not have a visibility prefix. Thus we override the visibility here manually.
|
||||
// See https://github.com/rust-lang/rust/issues/81274
|
||||
clean::Item { visibility: Visibility::Inherited, ..item.clean(cx) }
|
||||
clean::Item { visibility: Visibility::Inherited, ..clean_middle_assoc_item(item, cx) }
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -452,7 +453,7 @@ pub(crate) fn build_impl(
|
|||
item.visibility(tcx).is_public()
|
||||
}
|
||||
})
|
||||
.map(|item| item.clean(cx))
|
||||
.map(|item| clean_middle_assoc_item(item, cx))
|
||||
.collect::<Vec<_>>(),
|
||||
clean::enter_impl_trait(cx, |cx| {
|
||||
clean_ty_generics(cx, tcx.generics_of(did), predicates)
|
||||
|
|
|
@ -123,7 +123,7 @@ fn clean_generic_bound<'tcx>(
|
|||
|
||||
let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
|
||||
|
||||
let generic_args = generic_args.clean(cx);
|
||||
let generic_args = clean_generic_args(generic_args, cx);
|
||||
let GenericArgs::AngleBracketed { bindings, .. } = generic_args
|
||||
else {
|
||||
bug!("clean: parenthesized `GenericBound::LangItemTrait`");
|
||||
|
@ -1092,199 +1092,201 @@ pub(crate) fn clean_impl_item<'tcx>(
|
|||
})
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<'tcx, Item> for ty::AssocItem {
|
||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
|
||||
let tcx = cx.tcx;
|
||||
let kind = match self.kind {
|
||||
ty::AssocKind::Const => {
|
||||
let ty = clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id));
|
||||
pub(crate) fn clean_middle_assoc_item<'tcx>(
|
||||
assoc_item: &ty::AssocItem,
|
||||
cx: &mut DocContext<'tcx>,
|
||||
) -> Item {
|
||||
let tcx = cx.tcx;
|
||||
let kind = match assoc_item.kind {
|
||||
ty::AssocKind::Const => {
|
||||
let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id));
|
||||
|
||||
let provided = match self.container {
|
||||
ty::ImplContainer => true,
|
||||
ty::TraitContainer => tcx.impl_defaultness(self.def_id).has_value(),
|
||||
};
|
||||
if provided {
|
||||
AssocConstItem(ty, ConstantKind::Extern { def_id: self.def_id })
|
||||
} else {
|
||||
TyAssocConstItem(ty)
|
||||
}
|
||||
let provided = match assoc_item.container {
|
||||
ty::ImplContainer => true,
|
||||
ty::TraitContainer => tcx.impl_defaultness(assoc_item.def_id).has_value(),
|
||||
};
|
||||
if provided {
|
||||
AssocConstItem(ty, ConstantKind::Extern { def_id: assoc_item.def_id })
|
||||
} else {
|
||||
TyAssocConstItem(ty)
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
let generics = clean_ty_generics(
|
||||
cx,
|
||||
tcx.generics_of(self.def_id),
|
||||
tcx.explicit_predicates_of(self.def_id),
|
||||
);
|
||||
let sig = tcx.fn_sig(self.def_id);
|
||||
let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(self.def_id), sig);
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
let generics = clean_ty_generics(
|
||||
cx,
|
||||
tcx.generics_of(assoc_item.def_id),
|
||||
tcx.explicit_predicates_of(assoc_item.def_id),
|
||||
);
|
||||
let sig = tcx.fn_sig(assoc_item.def_id);
|
||||
let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig);
|
||||
|
||||
if self.fn_has_self_parameter {
|
||||
let self_ty = match self.container {
|
||||
ty::ImplContainer => tcx.type_of(self.container_id(tcx)),
|
||||
ty::TraitContainer => tcx.types.self_param,
|
||||
};
|
||||
let self_arg_ty = sig.input(0).skip_binder();
|
||||
if self_arg_ty == self_ty {
|
||||
decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
|
||||
} else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
|
||||
if ty == self_ty {
|
||||
match decl.inputs.values[0].type_ {
|
||||
BorrowedRef { ref mut type_, .. } => {
|
||||
**type_ = Generic(kw::SelfUpper)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
if assoc_item.fn_has_self_parameter {
|
||||
let self_ty = match assoc_item.container {
|
||||
ty::ImplContainer => tcx.type_of(assoc_item.container_id(tcx)),
|
||||
ty::TraitContainer => tcx.types.self_param,
|
||||
};
|
||||
let self_arg_ty = sig.input(0).skip_binder();
|
||||
if self_arg_ty == self_ty {
|
||||
decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
|
||||
} else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
|
||||
if ty == self_ty {
|
||||
match decl.inputs.values[0].type_ {
|
||||
BorrowedRef { ref mut type_, .. } => **type_ = Generic(kw::SelfUpper),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let provided = match self.container {
|
||||
ty::ImplContainer => true,
|
||||
ty::TraitContainer => self.defaultness(tcx).has_value(),
|
||||
let provided = match assoc_item.container {
|
||||
ty::ImplContainer => true,
|
||||
ty::TraitContainer => assoc_item.defaultness(tcx).has_value(),
|
||||
};
|
||||
if provided {
|
||||
let defaultness = match assoc_item.container {
|
||||
ty::ImplContainer => Some(assoc_item.defaultness(tcx)),
|
||||
ty::TraitContainer => None,
|
||||
};
|
||||
if provided {
|
||||
let defaultness = match self.container {
|
||||
ty::ImplContainer => Some(self.defaultness(tcx)),
|
||||
ty::TraitContainer => None,
|
||||
};
|
||||
MethodItem(Box::new(Function { generics, decl }), defaultness)
|
||||
} else {
|
||||
TyMethodItem(Box::new(Function { generics, decl }))
|
||||
MethodItem(Box::new(Function { generics, decl }), defaultness)
|
||||
} else {
|
||||
TyMethodItem(Box::new(Function { generics, decl }))
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Type => {
|
||||
let my_name = assoc_item.name;
|
||||
|
||||
fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
|
||||
match (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
|
||||
if *ty == param.name =>
|
||||
{
|
||||
true
|
||||
}
|
||||
(GenericParamDefKind::Lifetime { .. }, GenericArg::Lifetime(Lifetime(lt)))
|
||||
if *lt == param.name =>
|
||||
{
|
||||
true
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind {
|
||||
ConstantKind::TyConst { expr } => expr == param.name.as_str(),
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Type => {
|
||||
let my_name = self.name;
|
||||
|
||||
fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool {
|
||||
match (¶m.kind, arg) {
|
||||
(GenericParamDefKind::Type { .. }, GenericArg::Type(Type::Generic(ty)))
|
||||
if *ty == param.name =>
|
||||
{
|
||||
if let ty::TraitContainer = assoc_item.container {
|
||||
let bounds = tcx.explicit_item_bounds(assoc_item.def_id);
|
||||
let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
|
||||
let mut generics =
|
||||
clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates);
|
||||
// Filter out the bounds that are (likely?) directly attached to the associated type,
|
||||
// as opposed to being located in the where clause.
|
||||
let mut bounds = generics
|
||||
.where_predicates
|
||||
.drain_filter(|pred| match *pred {
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: QPath { ref assoc, ref self_type, ref trait_, .. },
|
||||
..
|
||||
} => {
|
||||
if assoc.name != my_name {
|
||||
return false;
|
||||
}
|
||||
if trait_.def_id() != assoc_item.container_id(tcx) {
|
||||
return false;
|
||||
}
|
||||
match **self_type {
|
||||
Generic(ref s) if *s == kw::SelfUpper => {}
|
||||
_ => return false,
|
||||
}
|
||||
match &assoc.args {
|
||||
GenericArgs::AngleBracketed { args, bindings } => {
|
||||
if !bindings.is_empty()
|
||||
|| generics
|
||||
.params
|
||||
.iter()
|
||||
.zip(args.iter())
|
||||
.any(|(param, arg)| !param_eq_arg(param, arg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
GenericArgs::Parenthesized { .. } => {
|
||||
// The only time this happens is if we're inside the rustdoc for Fn(),
|
||||
// which only has one associated type, which is not a GAT, so whatever.
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
(
|
||||
GenericParamDefKind::Lifetime { .. },
|
||||
GenericArg::Lifetime(Lifetime(lt)),
|
||||
) if *lt == param.name => true,
|
||||
(GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => {
|
||||
match &c.kind {
|
||||
ConstantKind::TyConst { expr } => expr == param.name.as_str(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.flat_map(|pred| {
|
||||
if let WherePredicate::BoundPredicate { bounds, .. } = pred {
|
||||
bounds
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// Our Sized/?Sized bound didn't get handled when creating the generics
|
||||
// because we didn't actually get our whole set of bounds until just now
|
||||
// (some of them may have come from the trait). If we do have a sized
|
||||
// bound, we remove it, and if we don't then we add the `?Sized` bound
|
||||
// at the end.
|
||||
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
|
||||
Some(i) => {
|
||||
bounds.remove(i);
|
||||
}
|
||||
None => bounds.push(GenericBound::maybe_sized(cx)),
|
||||
}
|
||||
|
||||
if let ty::TraitContainer = self.container {
|
||||
let bounds = tcx.explicit_item_bounds(self.def_id);
|
||||
let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
|
||||
let mut generics =
|
||||
clean_ty_generics(cx, tcx.generics_of(self.def_id), predicates);
|
||||
// Filter out the bounds that are (likely?) directly attached to the associated type,
|
||||
// as opposed to being located in the where clause.
|
||||
let mut bounds = generics
|
||||
.where_predicates
|
||||
.drain_filter(|pred| match *pred {
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: QPath { ref assoc, ref self_type, ref trait_, .. },
|
||||
..
|
||||
} => {
|
||||
if assoc.name != my_name {
|
||||
return false;
|
||||
}
|
||||
if trait_.def_id() != self.container_id(tcx) {
|
||||
return false;
|
||||
}
|
||||
match **self_type {
|
||||
Generic(ref s) if *s == kw::SelfUpper => {}
|
||||
_ => return false,
|
||||
}
|
||||
match &assoc.args {
|
||||
GenericArgs::AngleBracketed { args, bindings } => {
|
||||
if !bindings.is_empty()
|
||||
|| generics
|
||||
.params
|
||||
.iter()
|
||||
.zip(args.iter())
|
||||
.any(|(param, arg)| !param_eq_arg(param, arg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
GenericArgs::Parenthesized { .. } => {
|
||||
// The only time this happens is if we're inside the rustdoc for Fn(),
|
||||
// which only has one associated type, which is not a GAT, so whatever.
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
.flat_map(|pred| {
|
||||
if let WherePredicate::BoundPredicate { bounds, .. } = pred {
|
||||
bounds
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// Our Sized/?Sized bound didn't get handled when creating the generics
|
||||
// because we didn't actually get our whole set of bounds until just now
|
||||
// (some of them may have come from the trait). If we do have a sized
|
||||
// bound, we remove it, and if we don't then we add the `?Sized` bound
|
||||
// at the end.
|
||||
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
|
||||
Some(i) => {
|
||||
bounds.remove(i);
|
||||
}
|
||||
None => bounds.push(GenericBound::maybe_sized(cx)),
|
||||
}
|
||||
|
||||
if tcx.impl_defaultness(self.def_id).has_value() {
|
||||
AssocTypeItem(
|
||||
Box::new(Typedef {
|
||||
type_: clean_middle_ty(
|
||||
tcx.type_of(self.def_id),
|
||||
cx,
|
||||
Some(self.def_id),
|
||||
),
|
||||
generics,
|
||||
// FIXME: should we obtain the Type from HIR and pass it on here?
|
||||
item_type: None,
|
||||
}),
|
||||
bounds,
|
||||
)
|
||||
} else {
|
||||
TyAssocTypeItem(Box::new(generics), bounds)
|
||||
}
|
||||
} else {
|
||||
// FIXME: when could this happen? Associated items in inherent impls?
|
||||
if tcx.impl_defaultness(assoc_item.def_id).has_value() {
|
||||
AssocTypeItem(
|
||||
Box::new(Typedef {
|
||||
type_: clean_middle_ty(tcx.type_of(self.def_id), cx, Some(self.def_id)),
|
||||
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
|
||||
type_: clean_middle_ty(
|
||||
tcx.type_of(assoc_item.def_id),
|
||||
cx,
|
||||
Some(assoc_item.def_id),
|
||||
),
|
||||
generics,
|
||||
// FIXME: should we obtain the Type from HIR and pass it on here?
|
||||
item_type: None,
|
||||
}),
|
||||
Vec::new(),
|
||||
bounds,
|
||||
)
|
||||
} else {
|
||||
TyAssocTypeItem(Box::new(generics), bounds)
|
||||
}
|
||||
} else {
|
||||
// FIXME: when could this happen? Associated items in inherent impls?
|
||||
AssocTypeItem(
|
||||
Box::new(Typedef {
|
||||
type_: clean_middle_ty(
|
||||
tcx.type_of(assoc_item.def_id),
|
||||
cx,
|
||||
Some(assoc_item.def_id),
|
||||
),
|
||||
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
|
||||
item_type: None,
|
||||
}),
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let mut what_rustc_thinks =
|
||||
Item::from_def_id_and_parts(self.def_id, Some(self.name), kind, cx);
|
||||
|
||||
let impl_ref = tcx.impl_trait_ref(tcx.parent(self.def_id));
|
||||
|
||||
// Trait impl items always inherit the impl's visibility --
|
||||
// we don't want to show `pub`.
|
||||
if impl_ref.is_some() {
|
||||
what_rustc_thinks.visibility = Visibility::Inherited;
|
||||
}
|
||||
};
|
||||
|
||||
what_rustc_thinks
|
||||
let mut what_rustc_thinks =
|
||||
Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx);
|
||||
|
||||
let impl_ref = tcx.impl_trait_ref(tcx.parent(assoc_item.def_id));
|
||||
|
||||
// Trait impl items always inherit the impl's visibility --
|
||||
// we don't want to show `pub`.
|
||||
if impl_ref.is_some() {
|
||||
what_rustc_thinks.visibility = Visibility::Inherited;
|
||||
}
|
||||
|
||||
what_rustc_thinks
|
||||
}
|
||||
|
||||
fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
|
||||
|
@ -1824,39 +1826,44 @@ fn clean_path<'tcx>(path: &hir::Path<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
|
|||
Path { res: path.res, segments: path.segments.iter().map(|x| x.clean(cx)).collect() }
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<'tcx, GenericArgs> for hir::GenericArgs<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericArgs {
|
||||
if self.parenthesized {
|
||||
let output = clean_ty(self.bindings[0].ty(), cx);
|
||||
let output =
|
||||
if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
|
||||
let inputs = self.inputs().iter().map(|x| clean_ty(x, cx)).collect::<Vec<_>>().into();
|
||||
GenericArgs::Parenthesized { inputs, output }
|
||||
} else {
|
||||
let args = self
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| match arg {
|
||||
hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
|
||||
GenericArg::Lifetime(clean_lifetime(*lt, cx))
|
||||
}
|
||||
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
|
||||
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
|
||||
hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))),
|
||||
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
let bindings =
|
||||
self.bindings.iter().map(|x| clean_type_binding(x, cx)).collect::<Vec<_>>().into();
|
||||
GenericArgs::AngleBracketed { args, bindings }
|
||||
}
|
||||
fn clean_generic_args<'tcx>(
|
||||
generic_args: &hir::GenericArgs<'tcx>,
|
||||
cx: &mut DocContext<'tcx>,
|
||||
) -> GenericArgs {
|
||||
if generic_args.parenthesized {
|
||||
let output = clean_ty(generic_args.bindings[0].ty(), cx);
|
||||
let output = if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
|
||||
let inputs =
|
||||
generic_args.inputs().iter().map(|x| clean_ty(x, cx)).collect::<Vec<_>>().into();
|
||||
GenericArgs::Parenthesized { inputs, output }
|
||||
} else {
|
||||
let args = generic_args
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| match arg {
|
||||
hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
|
||||
GenericArg::Lifetime(clean_lifetime(*lt, cx))
|
||||
}
|
||||
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
|
||||
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
|
||||
hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))),
|
||||
hir::GenericArg::Infer(_inf) => GenericArg::Infer,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
let bindings = generic_args
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|x| clean_type_binding(x, cx))
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
GenericArgs::AngleBracketed { args, bindings }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<'tcx, PathSegment> for hir::PathSegment<'tcx> {
|
||||
fn clean(&self, cx: &mut DocContext<'tcx>) -> PathSegment {
|
||||
PathSegment { name: self.ident.name, args: self.args().clean(cx) }
|
||||
PathSegment { name: self.ident.name, args: clean_generic_args(self.args(), cx) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2226,7 +2233,10 @@ fn clean_type_binding<'tcx>(
|
|||
cx: &mut DocContext<'tcx>,
|
||||
) -> TypeBinding {
|
||||
TypeBinding {
|
||||
assoc: PathSegment { name: type_binding.ident.name, args: type_binding.gen_args.clean(cx) },
|
||||
assoc: PathSegment {
|
||||
name: type_binding.ident.name,
|
||||
args: clean_generic_args(type_binding.gen_args, cx),
|
||||
},
|
||||
kind: match type_binding.kind {
|
||||
hir::TypeBindingKind::Equality { ref term } => {
|
||||
TypeBindingKind::Equality { term: clean_hir_term(term, cx) }
|
||||
|
|
|
@ -2495,14 +2495,15 @@ impl SubstParam {
|
|||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
mod size_asserts {
|
||||
use super::*;
|
||||
use rustc_data_structures::static_assert_size;
|
||||
// These are in alphabetical order, which is easy to maintain.
|
||||
rustc_data_structures::static_assert_size!(Crate, 72); // frequently moved by-value
|
||||
rustc_data_structures::static_assert_size!(DocFragment, 32);
|
||||
rustc_data_structures::static_assert_size!(GenericArg, 80);
|
||||
rustc_data_structures::static_assert_size!(GenericArgs, 32);
|
||||
rustc_data_structures::static_assert_size!(GenericParamDef, 56);
|
||||
rustc_data_structures::static_assert_size!(Item, 56);
|
||||
rustc_data_structures::static_assert_size!(ItemKind, 112);
|
||||
rustc_data_structures::static_assert_size!(PathSegment, 40);
|
||||
rustc_data_structures::static_assert_size!(Type, 72);
|
||||
static_assert_size!(Crate, 72); // frequently moved by-value
|
||||
static_assert_size!(DocFragment, 32);
|
||||
static_assert_size!(GenericArg, 80);
|
||||
static_assert_size!(GenericArgs, 32);
|
||||
static_assert_size!(GenericParamDef, 56);
|
||||
static_assert_size!(Item, 56);
|
||||
static_assert_size!(ItemKind, 112);
|
||||
static_assert_size!(PathSegment, 40);
|
||||
static_assert_size!(Type, 72);
|
||||
}
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
let mut _7: std::boxed::Box<i32>; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22
|
||||
let mut _8: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22
|
||||
let mut _9: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22
|
||||
let mut _10: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22
|
||||
let mut _11: *const i32; // in scope 0 at $DIR/boxes.rs:+1:14: +1:22
|
||||
scope 1 {
|
||||
debug x => _1; // in scope 1 at $DIR/boxes.rs:+1:9: +1:10
|
||||
}
|
||||
|
|
|
@ -10,15 +10,14 @@
|
|||
let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43
|
||||
let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
let mut _8: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
+ let mut _9: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
scope 1 {
|
||||
debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:+1:9: +1:11
|
||||
}
|
||||
scope 2 {
|
||||
}
|
||||
+ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
|
||||
+ let mut _10: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ let mut _9: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -37,10 +36,10 @@
|
|||
StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
_7 = (((_5.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ StorageLive(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ _9 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ _10 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageLive(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ _8 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ _9 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
// mir::Constant
|
||||
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
|
||||
- // + user_ty: UserType(1)
|
||||
|
@ -51,11 +50,11 @@
|
|||
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ // + user_ty: UserType(0)
|
||||
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
|
||||
+ Deinit((*_9)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_9).0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_9).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ Deinit((*_8)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_8).0: alloc::raw_vec::RawVec<u32>) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
_1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43
|
||||
|
|
|
@ -10,15 +10,14 @@
|
|||
let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43
|
||||
let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
let mut _8: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
+ let mut _9: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
scope 1 {
|
||||
debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:+1:9: +1:11
|
||||
}
|
||||
scope 2 {
|
||||
}
|
||||
+ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
|
||||
+ let mut _10: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ let mut _9: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -37,10 +36,10 @@
|
|||
StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
_7 = (((_5.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ StorageLive(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ _9 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ _10 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageLive(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ _8 = &mut (*_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ StorageLive(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ _9 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
// mir::Constant
|
||||
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
|
||||
- // + user_ty: UserType(1)
|
||||
|
@ -51,11 +50,11 @@
|
|||
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ // + user_ty: UserType(0)
|
||||
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
|
||||
+ Deinit((*_9)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_9).0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_9).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_9); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
+ Deinit((*_8)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_8).0: alloc::raw_vec::RawVec<u32>) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
+ StorageDead(_8); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:+1:33: +1:43
|
||||
_1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:+1:29: +1:43
|
||||
StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:+1:42: +1:43
|
||||
|
|
|
@ -74,10 +74,10 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
|
|||
2 => {
|
||||
let seg = PathSegment::from_ident(Ident::from_str("x"));
|
||||
iter_exprs(depth - 1, &mut |e| {
|
||||
g(ExprKind::MethodCall(seg.clone(), vec![e, make_x()], DUMMY_SP))
|
||||
g(ExprKind::MethodCall(seg.clone(), e, vec![make_x()], DUMMY_SP))
|
||||
});
|
||||
iter_exprs(depth - 1, &mut |e| {
|
||||
g(ExprKind::MethodCall(seg.clone(), vec![make_x(), e], DUMMY_SP))
|
||||
g(ExprKind::MethodCall(seg.clone(), make_x(), vec![e], DUMMY_SP))
|
||||
});
|
||||
}
|
||||
3..=8 => {
|
||||
|
|
12
src/test/ui/cfg/cfg-method-receiver.rs
Normal file
12
src/test/ui/cfg/cfg-method-receiver.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
macro_rules! cbor_map {
|
||||
($key:expr) => {
|
||||
$key.signum();
|
||||
//~^ ERROR can't call method `signum` on ambiguous numeric type `{integer}` [E0689]
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
cbor_map! { #[cfg(test)] 4};
|
||||
//~^ ERROR attributes on expressions are experimental
|
||||
//~| ERROR removing an expression is not supported in this position
|
||||
}
|
34
src/test/ui/cfg/cfg-method-receiver.stderr
Normal file
34
src/test/ui/cfg/cfg-method-receiver.stderr
Normal file
|
@ -0,0 +1,34 @@
|
|||
error[E0658]: attributes on expressions are experimental
|
||||
--> $DIR/cfg-method-receiver.rs:9:17
|
||||
|
|
||||
LL | cbor_map! { #[cfg(test)] 4};
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
|
||||
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
|
||||
|
||||
error: removing an expression is not supported in this position
|
||||
--> $DIR/cfg-method-receiver.rs:9:17
|
||||
|
|
||||
LL | cbor_map! { #[cfg(test)] 4};
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error[E0689]: can't call method `signum` on ambiguous numeric type `{integer}`
|
||||
--> $DIR/cfg-method-receiver.rs:3:14
|
||||
|
|
||||
LL | $key.signum();
|
||||
| ^^^^^^
|
||||
...
|
||||
LL | cbor_map! { #[cfg(test)] 4};
|
||||
| --------------------------- in this macro invocation
|
||||
|
|
||||
= note: this error originates in the macro `cbor_map` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: you must specify a concrete type for this numeric value, like `i32`
|
||||
|
|
||||
LL | cbor_map! { #[cfg(test)] 4_i32};
|
||||
| ~~~~~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0658, E0689.
|
||||
For more information about an error, try `rustc --explain E0658`.
|
|
@ -1,5 +1,4 @@
|
|||
// aux-build:enums.rs
|
||||
// run-pass
|
||||
|
||||
extern crate enums;
|
||||
|
||||
|
@ -7,11 +6,6 @@ use enums::FieldLessWithNonExhaustiveVariant;
|
|||
|
||||
fn main() {
|
||||
let e = FieldLessWithNonExhaustiveVariant::default();
|
||||
// FIXME: https://github.com/rust-lang/rust/issues/91161
|
||||
// This `as` cast *should* be an error, since it would fail
|
||||
// if the non-exhaustive variant got fields. But today it
|
||||
// doesn't. The fix for that will update this test to
|
||||
// show an error (and not be run-pass any more).
|
||||
let d = e as u8;
|
||||
let d = e as u8; //~ ERROR casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid [E0606]
|
||||
assert_eq!(d, 0);
|
||||
}
|
||||
|
|
11
src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr
Normal file
11
src/test/ui/rfc-2008-non-exhaustive/enum-as-cast.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error[E0606]: casting `FieldLessWithNonExhaustiveVariant` as `u8` is invalid
|
||||
--> $DIR/enum-as-cast.rs:9:13
|
||||
|
|
||||
LL | let d = e as u8;
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: cannot cast an enum with a non-exhaustive variant when it's defined in another crate
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0606`.
|
41
src/test/ui/stats/hir-stats.rs
Normal file
41
src/test/ui/stats/hir-stats.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
// check-pass
|
||||
// compile-flags: -Zhir-stats
|
||||
// only-x86_64
|
||||
|
||||
// The aim here is to include at least one of every different type of top-level
|
||||
// AST/HIR node reported by `-Zhir-stats`.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::arch::asm;
|
||||
use std::fmt::Debug;
|
||||
use std::ffi::c_void;
|
||||
|
||||
extern "C" { fn f(p: *mut c_void); }
|
||||
|
||||
/// An enum.
|
||||
enum E<'a, T: Copy> { A { t: T }, B(&'a u32) }
|
||||
|
||||
trait Go {
|
||||
type G: Debug;
|
||||
fn go(self) -> u32;
|
||||
}
|
||||
|
||||
impl<'a, T: Copy> Go for E<'a, T> {
|
||||
type G = bool;
|
||||
fn go(self) -> u32 {
|
||||
99
|
||||
}
|
||||
}
|
||||
|
||||
fn f2<T>(t: T) where T: Debug {}
|
||||
|
||||
fn main() {
|
||||
let x = E::A { t: 3 };
|
||||
match x {
|
||||
E::A { .. } => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
unsafe { asm!("mov rdi, 1"); }
|
||||
}
|
151
src/test/ui/stats/hir-stats.stderr
Normal file
151
src/test/ui/stats/hir-stats.stderr
Normal file
|
@ -0,0 +1,151 @@
|
|||
|
||||
PRE EXPANSION AST STATS
|
||||
|
||||
Name Accumulated Size Count Item Size
|
||||
----------------------------------------------------------------
|
||||
ExprField 48 ( 0.5%) 1 48
|
||||
GenericArgs 64 ( 0.7%) 1 64
|
||||
- AngleBracketed 64 ( 0.7%) 1
|
||||
Local 72 ( 0.8%) 1 72
|
||||
WherePredicate 72 ( 0.8%) 1 72
|
||||
- BoundPredicate 72 ( 0.8%) 1
|
||||
Crate 72 ( 0.8%) 1 72
|
||||
Arm 96 ( 1.0%) 2 48
|
||||
FieldDef 160 ( 1.7%) 2 80
|
||||
ForeignItem 160 ( 1.7%) 1 160
|
||||
- Fn 160 ( 1.7%) 1
|
||||
Stmt 160 ( 1.7%) 5 32
|
||||
- Local 32 ( 0.3%) 1
|
||||
- MacCall 32 ( 0.3%) 1
|
||||
- Expr 96 ( 1.0%) 3
|
||||
Param 160 ( 1.7%) 4 40
|
||||
FnDecl 200 ( 2.2%) 5 40
|
||||
Variant 240 ( 2.6%) 2 120
|
||||
Block 288 ( 3.1%) 6 48
|
||||
Attribute 304 ( 3.3%) 2 152
|
||||
- Normal 152 ( 1.7%) 1
|
||||
- DocComment 152 ( 1.7%) 1
|
||||
GenericBound 352 ( 3.8%) 4 88
|
||||
- Trait 352 ( 3.8%) 4
|
||||
GenericParam 520 ( 5.7%) 5 104
|
||||
AssocItem 640 ( 7.0%) 4 160
|
||||
- TyAlias 320 ( 3.5%) 2
|
||||
- Fn 320 ( 3.5%) 2
|
||||
PathSegment 720 ( 7.9%) 30 24
|
||||
Expr 832 ( 9.1%) 8 104
|
||||
- Path 104 ( 1.1%) 1
|
||||
- Match 104 ( 1.1%) 1
|
||||
- Struct 104 ( 1.1%) 1
|
||||
- Lit 208 ( 2.3%) 2
|
||||
- Block 312 ( 3.4%) 3
|
||||
Pat 840 ( 9.2%) 7 120
|
||||
- Struct 120 ( 1.3%) 1
|
||||
- Wild 120 ( 1.3%) 1
|
||||
- Ident 600 ( 6.6%) 5
|
||||
Ty 1_344 (14.7%) 14 96
|
||||
- Rptr 96 ( 1.0%) 1
|
||||
- Ptr 96 ( 1.0%) 1
|
||||
- ImplicitSelf 192 ( 2.1%) 2
|
||||
- Path 960 (10.5%) 10
|
||||
Item 1_800 (19.7%) 9 200
|
||||
- Trait 200 ( 2.2%) 1
|
||||
- Enum 200 ( 2.2%) 1
|
||||
- ForeignMod 200 ( 2.2%) 1
|
||||
- Impl 200 ( 2.2%) 1
|
||||
- Fn 400 ( 4.4%) 2
|
||||
- Use 600 ( 6.6%) 3
|
||||
----------------------------------------------------------------
|
||||
Total 9_144
|
||||
|
||||
|
||||
POST EXPANSION AST STATS
|
||||
|
||||
Name Accumulated Size Count Item Size
|
||||
----------------------------------------------------------------
|
||||
ExprField 48 ( 0.5%) 1 48
|
||||
GenericArgs 64 ( 0.6%) 1 64
|
||||
- AngleBracketed 64 ( 0.6%) 1
|
||||
Local 72 ( 0.7%) 1 72
|
||||
WherePredicate 72 ( 0.7%) 1 72
|
||||
- BoundPredicate 72 ( 0.7%) 1
|
||||
Crate 72 ( 0.7%) 1 72
|
||||
Arm 96 ( 0.9%) 2 48
|
||||
InlineAsm 120 ( 1.2%) 1 120
|
||||
FieldDef 160 ( 1.6%) 2 80
|
||||
ForeignItem 160 ( 1.6%) 1 160
|
||||
- Fn 160 ( 1.6%) 1
|
||||
Stmt 160 ( 1.6%) 5 32
|
||||
- Local 32 ( 0.3%) 1
|
||||
- Semi 32 ( 0.3%) 1
|
||||
- Expr 96 ( 0.9%) 3
|
||||
Param 160 ( 1.6%) 4 40
|
||||
FnDecl 200 ( 2.0%) 5 40
|
||||
Variant 240 ( 2.4%) 2 120
|
||||
Block 288 ( 2.8%) 6 48
|
||||
GenericBound 352 ( 3.5%) 4 88
|
||||
- Trait 352 ( 3.5%) 4
|
||||
GenericParam 520 ( 5.1%) 5 104
|
||||
Attribute 608 ( 6.0%) 4 152
|
||||
- DocComment 152 ( 1.5%) 1
|
||||
- Normal 456 ( 4.5%) 3
|
||||
AssocItem 640 ( 6.3%) 4 160
|
||||
- TyAlias 320 ( 3.2%) 2
|
||||
- Fn 320 ( 3.2%) 2
|
||||
PathSegment 792 ( 7.8%) 33 24
|
||||
Pat 840 ( 8.3%) 7 120
|
||||
- Struct 120 ( 1.2%) 1
|
||||
- Wild 120 ( 1.2%) 1
|
||||
- Ident 600 ( 5.9%) 5
|
||||
Expr 936 ( 9.2%) 9 104
|
||||
- Path 104 ( 1.0%) 1
|
||||
- Match 104 ( 1.0%) 1
|
||||
- Struct 104 ( 1.0%) 1
|
||||
- InlineAsm 104 ( 1.0%) 1
|
||||
- Lit 208 ( 2.1%) 2
|
||||
- Block 312 ( 3.1%) 3
|
||||
Ty 1_344 (13.2%) 14 96
|
||||
- Rptr 96 ( 0.9%) 1
|
||||
- Ptr 96 ( 0.9%) 1
|
||||
- ImplicitSelf 192 ( 1.9%) 2
|
||||
- Path 960 ( 9.5%) 10
|
||||
Item 2_200 (21.7%) 11 200
|
||||
- Trait 200 ( 2.0%) 1
|
||||
- Enum 200 ( 2.0%) 1
|
||||
- ExternCrate 200 ( 2.0%) 1
|
||||
- ForeignMod 200 ( 2.0%) 1
|
||||
- Impl 200 ( 2.0%) 1
|
||||
- Fn 400 ( 3.9%) 2
|
||||
- Use 800 ( 7.9%) 4
|
||||
----------------------------------------------------------------
|
||||
Total 10_144
|
||||
|
||||
|
||||
HIR STATS
|
||||
|
||||
Name Accumulated Size Count Item Size
|
||||
----------------------------------------------------------------
|
||||
Param 64 ( 0.7%) 2 32
|
||||
Local 64 ( 0.7%) 1 64
|
||||
ForeignItem 72 ( 0.7%) 1 72
|
||||
FieldDef 96 ( 1.0%) 2 48
|
||||
Arm 96 ( 1.0%) 2 48
|
||||
Stmt 96 ( 1.0%) 3 32
|
||||
FnDecl 120 ( 1.2%) 3 40
|
||||
Lifetime 128 ( 1.3%) 4 32
|
||||
Variant 160 ( 1.6%) 2 80
|
||||
ImplItem 176 ( 1.8%) 2 88
|
||||
GenericBound 192 ( 2.0%) 4 48
|
||||
TraitItem 192 ( 2.0%) 2 96
|
||||
WherePredicate 216 ( 2.2%) 3 72
|
||||
Block 288 ( 3.0%) 6 48
|
||||
QPath 408 ( 4.2%) 17 24
|
||||
Pat 440 ( 4.5%) 5 88
|
||||
Attribute 608 ( 6.2%) 4 152
|
||||
Expr 672 ( 6.9%) 12 56
|
||||
Item 960 ( 9.9%) 12 80
|
||||
Ty 1_152 (11.8%) 16 72
|
||||
Path 1_296 (13.3%) 27 48
|
||||
PathSegment 2_240 (23.0%) 40 56
|
||||
----------------------------------------------------------------
|
||||
Total 9_736
|
||||
|
|
@ -61,9 +61,8 @@ impl EarlyLintPass for DoubleParens {
|
|||
}
|
||||
}
|
||||
},
|
||||
ExprKind::MethodCall(_, ref params, _) => {
|
||||
if params.len() == 2 {
|
||||
let param = ¶ms[1];
|
||||
ExprKind::MethodCall(_, _, ref params, _) => {
|
||||
if let [ref param] = params[..] {
|
||||
if let ExprKind::Paren(_) = param.kind {
|
||||
span_lint(cx, DOUBLE_PARENS, param.span, msg);
|
||||
}
|
||||
|
|
|
@ -37,9 +37,9 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
|
|||
impl EarlyLintPass for OptionEnvUnwrap {
|
||||
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
if_chain! {
|
||||
if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind;
|
||||
if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind;
|
||||
if matches!(path_segment.ident.name, sym::expect | sym::unwrap);
|
||||
if let ExprKind::Call(caller, _) = &args[0].kind;
|
||||
if let ExprKind::Call(caller, _) = &receiver.kind;
|
||||
if is_direct_expn_of(caller.span, "option_env").is_some();
|
||||
then {
|
||||
span_lint_and_help(
|
||||
|
|
|
@ -109,12 +109,12 @@ impl EarlyLintPass for Precedence {
|
|||
let mut arg = operand;
|
||||
|
||||
let mut all_odd = true;
|
||||
while let ExprKind::MethodCall(path_segment, args, _) = &arg.kind {
|
||||
while let ExprKind::MethodCall(path_segment, receiver, _, _) = &arg.kind {
|
||||
let path_segment_str = path_segment.ident.name.as_str();
|
||||
all_odd &= ALLOWED_ODD_FUNCTIONS
|
||||
.iter()
|
||||
.any(|odd_function| **odd_function == *path_segment_str);
|
||||
arg = args.first().expect("A method always has a receiver.");
|
||||
arg = receiver;
|
||||
}
|
||||
|
||||
if_chain! {
|
||||
|
|
|
@ -595,7 +595,7 @@ fn ident_difference_expr_with_base_location(
|
|||
| (Unary(_, _), Unary(_, _))
|
||||
| (Binary(_, _, _), Binary(_, _, _))
|
||||
| (Tup(_), Tup(_))
|
||||
| (MethodCall(_, _, _), MethodCall(_, _, _))
|
||||
| (MethodCall(_, _, _, _), MethodCall(_, _, _, _))
|
||||
| (Call(_, _), Call(_, _))
|
||||
| (ConstBlock(_), ConstBlock(_))
|
||||
| (Array(_), Array(_))
|
||||
|
|
|
@ -30,11 +30,10 @@ declare_clippy_lint! {
|
|||
declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
|
||||
|
||||
fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
|
||||
if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind
|
||||
if let ExprKind::MethodCall(name_ident, receiver, _, _) = &expr.kind
|
||||
&& let method_name = name_ident.ident.name.as_str()
|
||||
&& (method_name == "ceil" || method_name == "round" || method_name == "floor")
|
||||
&& !args.is_empty()
|
||||
&& let ExprKind::Lit(spanned) = &args[0].kind
|
||||
&& let ExprKind::Lit(spanned) = &receiver.kind
|
||||
&& let LitKind::Float(symbol, ty) = spanned.kind {
|
||||
let f = symbol.as_str().parse::<f64>().unwrap();
|
||||
let f_str = symbol.to_string() + if let LitFloatType::Suffixed(ty) = ty {
|
||||
|
|
|
@ -147,7 +147,9 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||
(Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
|
||||
(Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
|
||||
(Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
|
||||
(MethodCall(lc, la, _), MethodCall(rc, ra, _)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
|
||||
(MethodCall(lc, ls, la, _), MethodCall(rc, rs, ra, _)) => {
|
||||
eq_path_seg(lc, rc) && eq_expr(ls, rs) && over(la, ra, |l, r| eq_expr(l, r))
|
||||
},
|
||||
(Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
|
||||
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
|
||||
(Lit(l), Lit(r)) => l.kind == r.kind,
|
||||
|
|
|
@ -201,6 +201,19 @@ async function main(argv) {
|
|||
process.setMaxListeners(opts["jobs"] + 1);
|
||||
}
|
||||
|
||||
// We catch this "event" to display a nicer message in case of unexpected exit (because of a
|
||||
// missing `--no-sandbox`).
|
||||
const exitHandling = (code) => {
|
||||
if (!opts["no_sandbox"]) {
|
||||
console.log("");
|
||||
console.log(
|
||||
"`browser-ui-test` crashed unexpectedly. Please try again with adding `--test-args \
|
||||
--no-sandbox` at the end. For example: `x.py test src/test/rustdoc-gui --test-args --no-sandbox`");
|
||||
console.log("");
|
||||
}
|
||||
};
|
||||
process.on('exit', exitHandling);
|
||||
|
||||
const tests_queue = [];
|
||||
let results = {
|
||||
successful: [],
|
||||
|
@ -247,6 +260,9 @@ async function main(argv) {
|
|||
}
|
||||
status_bar.finish();
|
||||
|
||||
// We don't need this listener anymore.
|
||||
process.removeListener("exit", exitHandling);
|
||||
|
||||
if (debug) {
|
||||
results.successful.sort(by_filename);
|
||||
results.successful.forEach(r => {
|
||||
|
|
|
@ -145,7 +145,7 @@ impl ChainItemKind {
|
|||
|
||||
fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) {
|
||||
let (kind, span) = match expr.kind {
|
||||
ast::ExprKind::MethodCall(ref segment, ref expressions, _) => {
|
||||
ast::ExprKind::MethodCall(ref segment, ref receiver, ref expressions, _) => {
|
||||
let types = if let Some(ref generic_args) = segment.args {
|
||||
if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
|
||||
data.args
|
||||
|
@ -163,7 +163,7 @@ impl ChainItemKind {
|
|||
} else {
|
||||
vec![]
|
||||
};
|
||||
let span = mk_sp(expressions[0].span.hi(), expr.span.hi());
|
||||
let span = mk_sp(receiver.span.hi(), expr.span.hi());
|
||||
let kind = ChainItemKind::MethodCall(segment.clone(), types, expressions.clone());
|
||||
(kind, span)
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ impl ChainItem {
|
|||
format!("::<{}>", type_list.join(", "))
|
||||
};
|
||||
let callee_str = format!(".{}{}", rewrite_ident(context, method_name), type_str);
|
||||
rewrite_call(context, &callee_str, &args[1..], span, shape)
|
||||
rewrite_call(context, &callee_str, &args, span, shape)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,8 +400,8 @@ impl Chain {
|
|||
// is a try! macro, we'll convert it to shorthand when the option is set.
|
||||
fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option<ast::Expr> {
|
||||
match expr.kind {
|
||||
ast::ExprKind::MethodCall(_, ref expressions, _) => {
|
||||
Some(Self::convert_try(&expressions[0], context))
|
||||
ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
|
||||
Some(Self::convert_try(&receiver, context))
|
||||
}
|
||||
ast::ExprKind::Field(ref subexpr, _)
|
||||
| ast::ExprKind::Try(ref subexpr)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue