Auto merge of #80364 - Dylan-DPC:rollup-0y96okz, r=Dylan-DPC
Rollup of 11 pull requests Successful merges: - #79213 (Stabilize `core::slice::fill`) - #79999 (Refactored verbose print into a function) - #80160 (Implemented a compiler diagnostic for move async mistake) - #80274 (Rename rustc_middle::lint::LintSource) - #80280 (Add installation commands to `x` tool README) - #80319 (Fix elided lifetimes shown as `'_` on async functions) - #80327 (Updated the match with the matches macro) - #80330 (Fix typo in simplify_try.rs) - #80340 (Don't unnecessarily override attrs for Module) - #80342 (Fix typo) - #80352 (BTreeMap: make test cases more explicit on failure) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9a40539c38
32 changed files with 203 additions and 105 deletions
|
@ -12,7 +12,9 @@ use rustc_hir::{intravisit, HirId};
|
|||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::lint::LevelSource;
|
||||
use rustc_middle::lint::LintDiagnosticBuilder;
|
||||
use rustc_middle::lint::{struct_lint_level, LintLevelMap, LintLevelSets, LintSet, LintSource};
|
||||
use rustc_middle::lint::{
|
||||
struct_lint_level, LintLevelMap, LintLevelSets, LintLevelSource, LintSet,
|
||||
};
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::lint::{builtin, Level, Lint, LintId};
|
||||
|
@ -91,7 +93,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
};
|
||||
for id in ids {
|
||||
self.check_gated_lint(id, DUMMY_SP);
|
||||
let src = LintSource::CommandLine(lint_flag_val, orig_level);
|
||||
let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
|
||||
specs.insert(id, (level, src));
|
||||
}
|
||||
}
|
||||
|
@ -128,19 +130,19 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
);
|
||||
diag_builder.span_label(src.span(), "overruled by previous forbid");
|
||||
match old_src {
|
||||
LintSource::Default => {
|
||||
LintLevelSource::Default => {
|
||||
diag_builder.note(&format!(
|
||||
"`forbid` lint level is the default for {}",
|
||||
id.to_string()
|
||||
));
|
||||
}
|
||||
LintSource::Node(_, forbid_source_span, reason) => {
|
||||
LintLevelSource::Node(_, forbid_source_span, reason) => {
|
||||
diag_builder.span_label(forbid_source_span, "`forbid` level set here");
|
||||
if let Some(rationale) = reason {
|
||||
diag_builder.note(&rationale.as_str());
|
||||
}
|
||||
}
|
||||
LintSource::CommandLine(_, _) => {
|
||||
LintLevelSource::CommandLine(_, _) => {
|
||||
diag_builder.note("`forbid` lint level was set on command line");
|
||||
}
|
||||
}
|
||||
|
@ -276,7 +278,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
let name = meta_item.path.segments.last().expect("empty lint name").ident.name;
|
||||
match store.check_lint_name(&name.as_str(), tool_name) {
|
||||
CheckLintNameResult::Ok(ids) => {
|
||||
let src = LintSource::Node(name, li.span(), reason);
|
||||
let src = LintLevelSource::Node(name, li.span(), reason);
|
||||
for &id in ids {
|
||||
self.check_gated_lint(id, attr.span);
|
||||
self.insert_spec(&mut specs, id, (level, src));
|
||||
|
@ -287,7 +289,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
match result {
|
||||
Ok(ids) => {
|
||||
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
|
||||
let src = LintSource::Node(
|
||||
let src = LintLevelSource::Node(
|
||||
Symbol::intern(complete_name),
|
||||
li.span(),
|
||||
reason,
|
||||
|
@ -324,7 +326,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
},
|
||||
);
|
||||
|
||||
let src = LintSource::Node(
|
||||
let src = LintLevelSource::Node(
|
||||
Symbol::intern(&new_lint_name),
|
||||
li.span(),
|
||||
reason,
|
||||
|
@ -403,7 +405,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
}
|
||||
|
||||
let (lint_attr_name, lint_attr_span) = match *src {
|
||||
LintSource::Node(name, span, _) => (name, span),
|
||||
LintLevelSource::Node(name, span, _) => (name, span),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
|
@ -460,7 +462,7 @@ impl<'s> LintLevelsBuilder<'s> {
|
|||
}
|
||||
|
||||
/// Find the lint level for a lint.
|
||||
pub fn lint_level(&self, lint: &'static Lint) -> (Level, LintSource) {
|
||||
pub fn lint_level(&self, lint: &'static Lint) -> (Level, LintLevelSource) {
|
||||
self.sets.get_lint_level(lint, self.cur, None, self.sess)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
|
|||
|
||||
/// How a lint level was set.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, HashStable)]
|
||||
pub enum LintSource {
|
||||
pub enum LintLevelSource {
|
||||
/// Lint is at the default level as declared
|
||||
/// in rustc or a plugin.
|
||||
Default,
|
||||
|
@ -27,25 +27,26 @@ pub enum LintSource {
|
|||
CommandLine(Symbol, Level),
|
||||
}
|
||||
|
||||
impl LintSource {
|
||||
impl LintLevelSource {
|
||||
pub fn name(&self) -> Symbol {
|
||||
match *self {
|
||||
LintSource::Default => symbol::kw::Default,
|
||||
LintSource::Node(name, _, _) => name,
|
||||
LintSource::CommandLine(name, _) => name,
|
||||
LintLevelSource::Default => symbol::kw::Default,
|
||||
LintLevelSource::Node(name, _, _) => name,
|
||||
LintLevelSource::CommandLine(name, _) => name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
match *self {
|
||||
LintSource::Default => DUMMY_SP,
|
||||
LintSource::Node(_, span, _) => span,
|
||||
LintSource::CommandLine(_, _) => DUMMY_SP,
|
||||
LintLevelSource::Default => DUMMY_SP,
|
||||
LintLevelSource::Node(_, span, _) => span,
|
||||
LintLevelSource::CommandLine(_, _) => DUMMY_SP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type LevelSource = (Level, LintSource);
|
||||
/// A tuple of a lint level and its source.
|
||||
pub type LevelSource = (Level, LintLevelSource);
|
||||
|
||||
pub struct LintLevelSets {
|
||||
pub list: Vec<LintSet>,
|
||||
|
@ -113,7 +114,7 @@ impl LintLevelSets {
|
|||
id: LintId,
|
||||
mut idx: u32,
|
||||
aux: Option<&FxHashMap<LintId, LevelSource>>,
|
||||
) -> (Option<Level>, LintSource) {
|
||||
) -> (Option<Level>, LintLevelSource) {
|
||||
if let Some(specs) = aux {
|
||||
if let Some(&(level, src)) = specs.get(&id) {
|
||||
return (Some(level), src);
|
||||
|
@ -125,7 +126,7 @@ impl LintLevelSets {
|
|||
if let Some(&(level, src)) = specs.get(&id) {
|
||||
return (Some(level), src);
|
||||
}
|
||||
return (None, LintSource::Default);
|
||||
return (None, LintLevelSource::Default);
|
||||
}
|
||||
LintSet::Node { ref specs, parent } => {
|
||||
if let Some(&(level, src)) = specs.get(&id) {
|
||||
|
@ -213,7 +214,7 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
sess: &'s Session,
|
||||
lint: &'static Lint,
|
||||
level: Level,
|
||||
src: LintSource,
|
||||
src: LintLevelSource,
|
||||
span: Option<MultiSpan>,
|
||||
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a>) + 'd,
|
||||
) {
|
||||
|
@ -223,7 +224,7 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
sess: &'s Session,
|
||||
lint: &'static Lint,
|
||||
level: Level,
|
||||
src: LintSource,
|
||||
src: LintLevelSource,
|
||||
span: Option<MultiSpan>,
|
||||
decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b>) + 'd>,
|
||||
) {
|
||||
|
@ -274,14 +275,14 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
|
||||
let name = lint.name_lower();
|
||||
match src {
|
||||
LintSource::Default => {
|
||||
LintLevelSource::Default => {
|
||||
sess.diag_note_once(
|
||||
&mut err,
|
||||
DiagnosticMessageId::from(lint),
|
||||
&format!("`#[{}({})]` on by default", level.as_str(), name),
|
||||
);
|
||||
}
|
||||
LintSource::CommandLine(lint_flag_val, orig_level) => {
|
||||
LintLevelSource::CommandLine(lint_flag_val, orig_level) => {
|
||||
let flag = match orig_level {
|
||||
Level::Warn => "-W",
|
||||
Level::Deny => "-D",
|
||||
|
@ -310,7 +311,7 @@ pub fn struct_lint_level<'s, 'd>(
|
|||
);
|
||||
}
|
||||
}
|
||||
LintSource::Node(lint_attr_name, src, reason) => {
|
||||
LintLevelSource::Node(lint_attr_name, src, reason) => {
|
||||
if let Some(rationale) = reason {
|
||||
err.note(&rationale.as_str());
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::dep_graph::{self, DepGraph, DepKind, DepNode, DepNodeExt};
|
|||
use crate::hir::exports::ExportMap;
|
||||
use crate::ich::{NodeIdHashingMode, StableHashingContext};
|
||||
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
|
||||
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintSource};
|
||||
use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
|
||||
use crate::middle;
|
||||
use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata};
|
||||
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
|
||||
|
@ -2559,7 +2559,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self,
|
||||
lint: &'static Lint,
|
||||
mut id: hir::HirId,
|
||||
) -> (Level, LintSource) {
|
||||
) -> (Level, LintLevelSource) {
|
||||
let sets = self.lint_levels(LOCAL_CRATE);
|
||||
loop {
|
||||
if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
|
||||
|
|
|
@ -24,7 +24,7 @@ extern "C" {
|
|||
/// This means we can use pointer for both
|
||||
/// equality comparisons and hashing.
|
||||
///
|
||||
/// Unlike slices, The types contained in `List` are expected to be `Copy`
|
||||
/// Unlike slices, the types contained in `List` are expected to be `Copy`
|
||||
/// and iterating over a `List` returns `T` instead of a reference.
|
||||
///
|
||||
/// Note: `Slice` was already taken by the `Ty`.
|
||||
|
|
|
@ -215,10 +215,7 @@ pub enum TyKind<'tcx> {
|
|||
impl TyKind<'tcx> {
|
||||
#[inline]
|
||||
pub fn is_primitive(&self) -> bool {
|
||||
match self {
|
||||
Bool | Char | Int(_) | Uint(_) | Float(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self, Bool | Char | Int(_) | Uint(_) | Float(_))
|
||||
}
|
||||
|
||||
/// Get the article ("a" or "an") to use with this type.
|
||||
|
|
|
@ -306,7 +306,7 @@ fn optimization_applies<'tcx>(
|
|||
return false;
|
||||
}
|
||||
|
||||
// Verify the assigment chain consists of the form b = a; c = b; d = c; etc...
|
||||
// Verify the assignment chain consists of the form b = a; c = b; d = c; etc...
|
||||
if opt_info.field_tmp_assignments.is_empty() {
|
||||
trace!("NO: no assignments found");
|
||||
return false;
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_middle::mir::interpret::{
|
|||
};
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitor};
|
||||
use rustc_middle::ty::{self, TyCtxt, TyS, TypeFoldable, TypeVisitor};
|
||||
use rustc_target::abi::Size;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
|
@ -408,6 +408,18 @@ impl ExtraComments<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn use_verbose(ty: &&TyS<'tcx>) -> bool {
|
||||
match ty.kind() {
|
||||
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false,
|
||||
// Unit type
|
||||
ty::Tuple(g_args) if g_args.is_empty() => false,
|
||||
ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(&g_arg.expect_ty())),
|
||||
ty::Array(ty, _) => use_verbose(ty),
|
||||
ty::FnDef(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
impl Visitor<'tcx> for ExtraComments<'tcx> {
|
||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
||||
self.super_constant(constant, location);
|
||||
|
@ -430,16 +442,10 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
|
|||
fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
|
||||
self.super_const(constant);
|
||||
let ty::Const { ty, val, .. } = constant;
|
||||
match ty.kind() {
|
||||
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => {}
|
||||
// Unit type
|
||||
ty::Tuple(tys) if tys.is_empty() => {}
|
||||
ty::FnDef(..) => {}
|
||||
_ => {
|
||||
self.push("ty::Const");
|
||||
self.push(&format!("+ ty: {:?}", ty));
|
||||
self.push(&format!("+ val: {:?}", val));
|
||||
}
|
||||
if use_verbose(ty) {
|
||||
self.push("ty::Const");
|
||||
self.push(&format!("+ ty: {:?}", ty));
|
||||
self.push(&format!("+ val: {:?}", val));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1912,4 +1912,22 @@ impl<'a> Parser<'a> {
|
|||
*self = snapshot;
|
||||
Err(err)
|
||||
}
|
||||
|
||||
/// Get the diagnostics for the cases where `move async` is found.
|
||||
///
|
||||
/// `move_async_span` starts at the 'm' of the move keyword and ends with the 'c' of the async keyword
|
||||
pub(super) fn incorrect_move_async_order_found(
|
||||
&self,
|
||||
move_async_span: Span,
|
||||
) -> DiagnosticBuilder<'a> {
|
||||
let mut err =
|
||||
self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect");
|
||||
err.span_suggestion_verbose(
|
||||
move_async_span,
|
||||
"try switching the order",
|
||||
"async move".to_owned(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1603,7 +1603,7 @@ impl<'a> Parser<'a> {
|
|||
self.sess.gated_spans.gate(sym::async_closure, span);
|
||||
}
|
||||
|
||||
let capture_clause = self.parse_capture_clause();
|
||||
let capture_clause = self.parse_capture_clause()?;
|
||||
let decl = self.parse_fn_block_decl()?;
|
||||
let decl_hi = self.prev_token.span;
|
||||
let body = match decl.output {
|
||||
|
@ -1626,8 +1626,18 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses an optional `move` prefix to a closure-like construct.
|
||||
fn parse_capture_clause(&mut self) -> CaptureBy {
|
||||
if self.eat_keyword(kw::Move) { CaptureBy::Value } else { CaptureBy::Ref }
|
||||
fn parse_capture_clause(&mut self) -> PResult<'a, CaptureBy> {
|
||||
if self.eat_keyword(kw::Move) {
|
||||
// Check for `move async` and recover
|
||||
if self.check_keyword(kw::Async) {
|
||||
let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
|
||||
Err(self.incorrect_move_async_order_found(move_async_span))
|
||||
} else {
|
||||
Ok(CaptureBy::Value)
|
||||
}
|
||||
} else {
|
||||
Ok(CaptureBy::Ref)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the `|arg, arg|` header of a closure.
|
||||
|
@ -2019,7 +2029,7 @@ impl<'a> Parser<'a> {
|
|||
fn parse_async_block(&mut self, mut attrs: AttrVec) -> PResult<'a, P<Expr>> {
|
||||
let lo = self.token.span;
|
||||
self.expect_keyword(kw::Async)?;
|
||||
let capture_clause = self.parse_capture_clause();
|
||||
let capture_clause = self.parse_capture_clause()?;
|
||||
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
attrs.extend(iattrs);
|
||||
let kind = ExprKind::Async(capture_clause, DUMMY_NODE_ID, body);
|
||||
|
|
|
@ -115,7 +115,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||
|
||||
impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> {
|
||||
fn assert_min_len(self, min_len: usize) {
|
||||
assert!(self.len() >= min_len, "{} < {}", self.len(), min_len);
|
||||
assert!(self.len() >= min_len, "node len {} < {}", self.len(), min_len);
|
||||
if let node::ForceResult::Internal(node) = self.force() {
|
||||
for idx in 0..=node.len() {
|
||||
let edge = unsafe { Handle::new_edge(node, idx) };
|
||||
|
|
|
@ -30,11 +30,15 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
|
|||
let depth = self.height();
|
||||
let indent = " ".repeat(depth);
|
||||
result += &format!("\n{}", indent);
|
||||
for idx in 0..leaf.len() {
|
||||
if idx > 0 {
|
||||
result += ", ";
|
||||
if leaf.len() == 0 {
|
||||
result += "(empty node)";
|
||||
} else {
|
||||
for idx in 0..leaf.len() {
|
||||
if idx > 0 {
|
||||
result += ", ";
|
||||
}
|
||||
result += &format!("{:?}", unsafe { leaf.key_at(idx) });
|
||||
}
|
||||
result += &format!("{:?}", unsafe { leaf.key_at(idx) });
|
||||
}
|
||||
}
|
||||
navigate::Position::Internal(_) => {}
|
||||
|
|
|
@ -2581,14 +2581,12 @@ impl<T> [T] {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_fill)]
|
||||
///
|
||||
/// let mut buf = vec![0; 10];
|
||||
/// buf.fill(1);
|
||||
/// assert_eq!(buf, vec![1; 10]);
|
||||
/// ```
|
||||
#[doc(alias = "memset")]
|
||||
#[unstable(feature = "slice_fill", issue = "70758")]
|
||||
#[stable(feature = "slice_fill", since = "1.50.0")]
|
||||
pub fn fill(&mut self, value: T)
|
||||
where
|
||||
T: Clone,
|
||||
|
|
|
@ -304,7 +304,6 @@
|
|||
#![feature(rustc_private)]
|
||||
#![feature(shrink_to)]
|
||||
#![feature(slice_concat_ext)]
|
||||
#![feature(slice_fill)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(slice_ptr_len)]
|
||||
|
|
|
@ -218,11 +218,6 @@ impl Clean<ExternalCrate> for CrateNum {
|
|||
|
||||
impl Clean<Item> for doctree::Module<'_> {
|
||||
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
// maintain a stack of mod ids, for doc comment path resolution
|
||||
// but we also need to resolve the module's own docs based on whether its docs were written
|
||||
// inside or outside the module, so check for that
|
||||
let attrs = self.attrs.clean(cx);
|
||||
|
||||
let mut items: Vec<Item> = vec![];
|
||||
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
|
||||
items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
|
||||
|
@ -251,7 +246,7 @@ impl Clean<Item> for doctree::Module<'_> {
|
|||
ModuleItem(Module { is_crate: self.is_crate, items }),
|
||||
cx,
|
||||
);
|
||||
Item { attrs, source: span.clean(cx), ..what_rustc_thinks }
|
||||
Item { source: span.clean(cx), ..what_rustc_thinks }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -638,6 +633,18 @@ impl Clean<Generics> for hir::Generics<'_> {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
/// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
|
||||
///
|
||||
/// See [`lifetime_to_generic_param`] in [`rustc_ast_lowering`] for more information.
|
||||
///
|
||||
/// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param
|
||||
fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
|
||||
match param.kind {
|
||||
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
let impl_trait_params = self
|
||||
.params
|
||||
.iter()
|
||||
|
@ -656,7 +663,7 @@ impl Clean<Generics> for hir::Generics<'_> {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
let mut params = Vec::with_capacity(self.params.len());
|
||||
for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
|
||||
for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
|
||||
let p = p.clean(cx);
|
||||
params.push(p);
|
||||
}
|
||||
|
@ -1437,7 +1444,16 @@ impl Clean<Type> for hir::Ty<'_> {
|
|||
TyKind::Never => Never,
|
||||
TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
|
||||
TyKind::Rptr(ref l, ref m) => {
|
||||
let lifetime = if l.is_elided() { None } else { Some(l.clean(cx)) };
|
||||
// There are two times a `Fresh` lifetime can be created:
|
||||
// 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`.
|
||||
// 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`.
|
||||
// See #59286 for more information.
|
||||
// Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it.
|
||||
// Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though;
|
||||
// there's no case where it could cause the function to fail to compile.
|
||||
let elided =
|
||||
l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_)));
|
||||
let lifetime = if elided { None } else { Some(l.clean(cx)) };
|
||||
BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
|
||||
}
|
||||
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
|
||||
|
|
|
@ -9,7 +9,6 @@ use rustc_hir as hir;
|
|||
|
||||
crate struct Module<'hir> {
|
||||
crate name: Option<Symbol>,
|
||||
crate attrs: &'hir [ast::Attribute],
|
||||
crate where_outer: Span,
|
||||
crate where_inner: Span,
|
||||
crate imports: Vec<Import<'hir>>,
|
||||
|
@ -23,13 +22,12 @@ crate struct Module<'hir> {
|
|||
}
|
||||
|
||||
impl Module<'hir> {
|
||||
crate fn new(name: Option<Symbol>, attrs: &'hir [ast::Attribute]) -> Module<'hir> {
|
||||
crate fn new(name: Option<Symbol>) -> Module<'hir> {
|
||||
Module {
|
||||
name,
|
||||
id: hir::CRATE_HIR_ID,
|
||||
where_outer: rustc_span::DUMMY_SP,
|
||||
where_inner: rustc_span::DUMMY_SP,
|
||||
attrs,
|
||||
imports: Vec::new(),
|
||||
mods: Vec::new(),
|
||||
items: Vec::new(),
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::html::markdown::{find_testable_code, ErrorCodes};
|
|||
use crate::passes::doc_test_lints::{should_have_doc_example, Tests};
|
||||
use crate::passes::Pass;
|
||||
use rustc_lint::builtin::MISSING_DOCS;
|
||||
use rustc_middle::lint::LintSource;
|
||||
use rustc_middle::lint::LintLevelSource;
|
||||
use rustc_session::lint;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::FileName;
|
||||
|
@ -254,7 +254,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
|
|||
// `missing_docs` is allow-by-default, so don't treat this as ignoring the item
|
||||
// unless the user had an explicit `allow`
|
||||
let should_have_docs =
|
||||
level != lint::Level::Allow || matches!(source, LintSource::Default);
|
||||
level != lint::Level::Allow || matches!(source, LintLevelSource::Default);
|
||||
debug!("counting {:?} {:?} in {}", i.type_(), i.name, filename);
|
||||
self.items.entry(filename).or_default().count_item(
|
||||
has_docs,
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::clean::*;
|
|||
use crate::core::DocContext;
|
||||
use crate::fold::DocFolder;
|
||||
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
|
||||
use rustc_middle::lint::LintSource;
|
||||
use rustc_middle::lint::LintLevelSource;
|
||||
use rustc_session::lint;
|
||||
|
||||
crate const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
|
||||
|
@ -77,7 +77,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
|
|||
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_local());
|
||||
let (level, source) =
|
||||
cx.tcx.lint_level_at_node(lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id);
|
||||
level != lint::Level::Allow || matches!(source, LintSource::Default)
|
||||
level != lint::Level::Allow || matches!(source, LintLevelSource::Default)
|
||||
}
|
||||
|
||||
crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! The Rust AST Visitor. Extracts useful information and massages it into a form
|
||||
//! usable for `clean`.
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
@ -64,7 +63,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
|
||||
let mut module = self.visit_mod_contents(
|
||||
krate.item.span,
|
||||
krate.item.attrs,
|
||||
&Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
|
||||
hir::CRATE_HIR_ID,
|
||||
&krate.item.module,
|
||||
|
@ -82,13 +80,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
fn visit_mod_contents(
|
||||
&mut self,
|
||||
span: Span,
|
||||
attrs: &'tcx [ast::Attribute],
|
||||
vis: &'tcx hir::Visibility<'_>,
|
||||
id: hir::HirId,
|
||||
m: &'tcx hir::Mod<'tcx>,
|
||||
name: Option<Symbol>,
|
||||
) -> Module<'tcx> {
|
||||
let mut om = Module::new(name, attrs);
|
||||
let mut om = Module::new(name);
|
||||
om.where_outer = span;
|
||||
om.where_inner = m.inner;
|
||||
om.id = id;
|
||||
|
@ -292,7 +289,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
hir::ItemKind::Mod(ref m) => {
|
||||
om.mods.push(self.visit_mod_contents(
|
||||
item.span,
|
||||
&item.attrs,
|
||||
&item.vis,
|
||||
item.hir_id,
|
||||
m,
|
||||
|
|
|
@ -14,9 +14,6 @@
|
|||
- _2 = CheckedAdd(const 1_u32, const 1_u32); // scope 0 at $DIR/checked_add.rs:5:18: 5:23
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 1_u32, const 1_u32) -> bb1; // scope 0 at $DIR/checked_add.rs:5:18: 5:23
|
||||
+ _2 = const (2_u32, false); // scope 0 at $DIR/checked_add.rs:5:18: 5:23
|
||||
+ // ty::Const
|
||||
+ // + ty: (u32, bool)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [2, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/checked_add.rs:5:18: 5:23
|
||||
+ // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [2, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29
|
||||
+ _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:5:13: 5:25
|
||||
+ _3 = const (3_u8, false); // scope 0 at $DIR/indirect.rs:5:13: 5:29
|
||||
+ // ty::Const
|
||||
+ // + ty: (u8, bool)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [3, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/indirect.rs:5:13: 5:29
|
||||
+ // + literal: Const { ty: (u8, bool), val: Value(ByRef { alloc: Allocation { bytes: [3, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
(_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue-67019.rs:11:11: 11:17
|
||||
- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue-67019.rs:11:10: 11:19
|
||||
+ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue-67019.rs:11:10: 11:19
|
||||
+ // ty::Const
|
||||
+ // + ty: (u8, u8)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [1, 2], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/issue-67019.rs:11:10: 11:19
|
||||
+ // + literal: Const { ty: (u8, u8), val: Value(ByRef { alloc: Allocation { bytes: [1, 2], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, size: Size { raw: 2 }, align: Align { pow2: 0 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -20,9 +20,6 @@
|
|||
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10
|
||||
- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14
|
||||
+ _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14
|
||||
+ // ty::Const
|
||||
+ // + ty: (i32, i32)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [42, 0, 0, 0, 99, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/mutable_variable_aggregate.rs:7:13: 7:14
|
||||
+ // + literal: Const { ty: (i32, i32), val: Value(ByRef { alloc: Allocation { bytes: [42, 0, 0, 0, 99, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
- _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
+ _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
+ // ty::Const
|
||||
+ // + ty: (i32, bool)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
+ // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
- _2 = CheckedAdd(const 2_i32, const 2_i32); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
- assert(!move (_2.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_i32, const 2_i32) -> bb1; // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
+ _2 = const (4_i32, false); // scope 0 at $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
+ // ty::Const
|
||||
+ // + ty: (i32, bool)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/optimizes_into_variable.rs:12:13: 12:18
|
||||
+ // + literal: Const { ty: (i32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -9,9 +9,6 @@
|
|||
- _1 = CheckedAdd(const 2_u32, const 2_u32); // scope 0 at $DIR/return_place.rs:6:5: 6:10
|
||||
- assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 2_u32, const 2_u32) -> bb1; // scope 0 at $DIR/return_place.rs:6:5: 6:10
|
||||
+ _1 = const (4_u32, false); // scope 0 at $DIR/return_place.rs:6:5: 6:10
|
||||
+ // ty::Const
|
||||
+ // + ty: (u32, bool)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/return_place.rs:6:5: 6:10
|
||||
+ // + literal: Const { ty: (u32, bool), val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [31], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
+ // ty::Const
|
||||
+ // + ty: (u32, u32)
|
||||
+ // + val: Value(ByRef { alloc: Allocation { bytes: [1, 0, 0, 0, 2, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
|
||||
+ // mir::Constant
|
||||
+ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:14
|
||||
+ // + literal: Const { ty: (u32, u32), val: Value(ByRef { alloc: Allocation { bytes: [1, 0, 0, 0, 2, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
|
||||
|
|
|
@ -42,9 +42,6 @@
|
|||
// mir::Constant
|
||||
// + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:12
|
||||
// + literal: Const { ty: fn(((), ())) {use_zst}, val: Value(Scalar(<ZST>)) }
|
||||
// ty::Const
|
||||
// + ty: ((), ())
|
||||
// + val: Value(Scalar(<ZST>))
|
||||
// mir::Constant
|
||||
// + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
|
||||
// + literal: Const { ty: ((), ()), val: Value(Scalar(<ZST>)) }
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// ignore-tidy-linelength
|
||||
// edition:2018
|
||||
#![feature(min_const_generics)]
|
||||
|
||||
|
@ -48,7 +49,50 @@ impl Foo {
|
|||
pub async fn mut_self(mut self, mut first: usize) {}
|
||||
}
|
||||
|
||||
pub trait Pattern<'a> {}
|
||||
|
||||
pub trait Trait<const N: usize> {}
|
||||
// @has async_fn/fn.const_generics.html
|
||||
// @has - '//pre[@class="rust fn"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
|
||||
pub async fn const_generics<const N: usize>(_: impl Trait<N>) {}
|
||||
|
||||
// test that elided lifetimes are properly elided and not displayed as `'_`
|
||||
// regression test for #63037
|
||||
// @has async_fn/fn.elided.html
|
||||
// @has - '//pre[@class="rust fn"]' 'pub async fn elided(foo: &str) -> &str'
|
||||
pub async fn elided(foo: &str) -> &str {}
|
||||
// This should really be shown as written, but for implementation reasons it's difficult.
|
||||
// See `impl Clean for TyKind::Rptr`.
|
||||
// @has async_fn/fn.user_elided.html
|
||||
// @has - '//pre[@class="rust fn"]' 'pub async fn user_elided(foo: &str) -> &str'
|
||||
pub async fn user_elided(foo: &'_ str) -> &str {}
|
||||
// @has async_fn/fn.static_trait.html
|
||||
// @has - '//pre[@class="rust fn"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
|
||||
pub async fn static_trait(foo: &str) -> Box<dyn Bar> {}
|
||||
// @has async_fn/fn.lifetime_for_trait.html
|
||||
// @has - '//pre[@class="rust fn"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
|
||||
pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_> {}
|
||||
// @has async_fn/fn.elided_in_input_trait.html
|
||||
// @has - '//pre[@class="rust fn"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
|
||||
pub async fn elided_in_input_trait(t: impl Pattern<'_>) {}
|
||||
|
||||
struct AsyncFdReadyGuard<'a, T> { x: &'a T }
|
||||
|
||||
impl Foo {
|
||||
// @has async_fn/struct.Foo.html
|
||||
// @has - '//h4[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator<Item = &usize>'
|
||||
pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {}
|
||||
// taken from `tokio` as an example of a method that was particularly bad before
|
||||
// @has - '//h4[@class="method"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>"
|
||||
pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()> {}
|
||||
// @has - '//h4[@class="method"]' "pub async fn mut_self(&mut self)"
|
||||
pub async fn mut_self(&mut self) {}
|
||||
}
|
||||
|
||||
// test named lifetimes, just in case
|
||||
// @has async_fn/fn.named.html
|
||||
// @has - '//pre[@class="rust fn"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
|
||||
pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {}
|
||||
// @has async_fn/fn.named_trait.html
|
||||
// @has - '//pre[@class="rust fn"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
|
||||
pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// run-rustfix
|
||||
// edition:2018
|
||||
|
||||
// Regression test for issue 79694
|
||||
|
||||
fn main() {
|
||||
let _ = async move { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// run-rustfix
|
||||
// edition:2018
|
||||
|
||||
// Regression test for issue 79694
|
||||
|
||||
fn main() {
|
||||
let _ = move async { }; //~ ERROR 7:13: 7:23: the order of `move` and `async` is incorrect
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
error: the order of `move` and `async` is incorrect
|
||||
--> $DIR/incorrect-move-async-order-issue-79694.rs:7:13
|
||||
|
|
||||
LL | let _ = move async { };
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: try switching the order
|
||||
|
|
||||
LL | let _ = async move { };
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -1,3 +1,10 @@
|
|||
# x
|
||||
|
||||
`x` invokes `x.py` from any subdirectory.
|
||||
|
||||
To install, run the following commands:
|
||||
|
||||
```
|
||||
$ cd rust/src/tools/x/
|
||||
$ cargo install --path .
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue