Auto merge of #106588 - JohnTitor:rollup-4z80tjx, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #103104 (Stabilize `main_separator_str`) - #106410 (Suggest `mut self: &mut Self` for `?Sized` impls) - #106457 (Adjust comments about pre-push.sh hook) - #106546 (jsondoclint: Check local items in `paths` are also in `index`.) - #106557 (Add some UI tests and reword error-code docs) - #106562 (Clarify examples for `VecDeque::get/get_mut`) - #106580 (remove unreachable error code `E0313`) - #106581 (Do not emit wrong E0308 suggestion for closure mismatch) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8ea62f6c30
|
@ -344,20 +344,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
err.span_help(source_info.span, "try removing `&mut` here");
|
||||
}
|
||||
} else if decl.mutability == Mutability::Not
|
||||
&& !matches!(
|
||||
} else if decl.mutability == Mutability::Not {
|
||||
if matches!(
|
||||
decl.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
hir::ImplicitSelfKind::MutRef
|
||||
))))
|
||||
)
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
decl.source_info.span.shrink_to_lo(),
|
||||
"consider making the binding mutable",
|
||||
"mut ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
),)))
|
||||
) {
|
||||
err.note(
|
||||
"as `Self` may be unsized, this call attempts to take `&mut &mut self`",
|
||||
);
|
||||
err.note("however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably");
|
||||
} else {
|
||||
err.span_suggestion_verbose(
|
||||
decl.source_info.span.shrink_to_lo(),
|
||||
"consider making the binding mutable",
|
||||
"mut ",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -579,8 +579,7 @@ E0791: include_str!("./error_codes/E0791.md"),
|
|||
// E0300, // unexpanded macro
|
||||
// E0304, // expected signed integer constant
|
||||
// E0305, // expected constant
|
||||
E0313, // lifetime of borrowed pointer outlives lifetime of captured
|
||||
// variable
|
||||
// E0313, // removed: found unreachable
|
||||
// E0314, // closure outlives stack frame
|
||||
// E0315, // cannot invoke closure outside of its lifetime
|
||||
// E0319, // trait impls for defaulted traits allowed just for structs/enums
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
A constant item was initialized with something that is not a constant
|
||||
expression.
|
||||
A non-`const` function was called in a `const` context.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
@ -8,26 +7,20 @@ fn create_some() -> Option<u8> {
|
|||
Some(1)
|
||||
}
|
||||
|
||||
const FOO: Option<u8> = create_some(); // error!
|
||||
// error: cannot call non-const fn `create_some` in constants
|
||||
const FOO: Option<u8> = create_some();
|
||||
```
|
||||
|
||||
The only functions that can be called in static or constant expressions are
|
||||
`const` functions, and struct/enum constructors.
|
||||
All functions used in a `const` context (constant or static expression) must
|
||||
be marked `const`.
|
||||
|
||||
To fix this error, you can declare `create_some` as a constant function:
|
||||
|
||||
```
|
||||
const fn create_some() -> Option<u8> { // declared as a const function
|
||||
// declared as a `const` function:
|
||||
const fn create_some() -> Option<u8> {
|
||||
Some(1)
|
||||
}
|
||||
|
||||
const FOO: Option<u8> = create_some(); // ok!
|
||||
|
||||
// These are also working:
|
||||
struct Bar {
|
||||
x: u8,
|
||||
}
|
||||
|
||||
const OTHER_FOO: Option<u8> = Some(1);
|
||||
const BAR: Bar = Bar {x: 1};
|
||||
const FOO: Option<u8> = create_some(); // no error!
|
||||
```
|
||||
|
|
|
@ -1379,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
// If we've reached our target type with just removing `&`, then just print now.
|
||||
if steps == 0 {
|
||||
if steps == 0 && !remove.trim().is_empty() {
|
||||
return Some((
|
||||
prefix_span,
|
||||
format!("consider removing the `{}`", remove.trim()),
|
||||
|
@ -1438,6 +1438,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else {
|
||||
(prefix_span, format!("{}{}", prefix, "*".repeat(steps)))
|
||||
};
|
||||
if suggestion.trim().is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
return Some((
|
||||
span,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
// ignore-tidy-filelength
|
||||
//! Error Reporting Code for the inference engine
|
||||
//!
|
||||
//! Because of the way inference, and in particular region inference,
|
||||
|
|
|
@ -25,16 +25,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
infer::Reborrow(span) => {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
|
||||
}
|
||||
infer::ReborrowUpvar(span, ref upvar_id) => {
|
||||
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
|
||||
RegionOriginNote::WithName {
|
||||
span,
|
||||
msg: fluent::infer_reborrow,
|
||||
name: &var_name.to_string(),
|
||||
continues: false,
|
||||
}
|
||||
.add_to_diagnostic(err);
|
||||
}
|
||||
infer::RelateObjectBound(span) => {
|
||||
RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
|
||||
.add_to_diagnostic(err);
|
||||
|
@ -162,33 +152,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||
);
|
||||
err
|
||||
}
|
||||
infer::ReborrowUpvar(span, ref upvar_id) => {
|
||||
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
span,
|
||||
E0313,
|
||||
"lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
|
||||
var_name
|
||||
);
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
"...the borrowed pointer is valid for ",
|
||||
sub,
|
||||
"...",
|
||||
None,
|
||||
);
|
||||
note_and_explain_region(
|
||||
self.tcx,
|
||||
&mut err,
|
||||
&format!("...but `{}` is only valid for ", var_name),
|
||||
sup,
|
||||
"",
|
||||
None,
|
||||
);
|
||||
err
|
||||
}
|
||||
infer::RelateObjectBound(span) => {
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
|
|
|
@ -409,9 +409,6 @@ pub enum SubregionOrigin<'tcx> {
|
|||
/// Creating a pointer `b` to contents of another reference
|
||||
Reborrow(Span),
|
||||
|
||||
/// Creating a pointer `b` to contents of an upvar
|
||||
ReborrowUpvar(Span, ty::UpvarId),
|
||||
|
||||
/// Data with type `Ty<'tcx>` was borrowed
|
||||
DataBorrowed(Ty<'tcx>, Span),
|
||||
|
||||
|
@ -1954,7 +1951,6 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
|||
RelateParamBound(a, ..) => a,
|
||||
RelateRegionParamBound(a) => a,
|
||||
Reborrow(a) => a,
|
||||
ReborrowUpvar(a, _) => a,
|
||||
DataBorrowed(_, a) => a,
|
||||
ReferenceOutlivesReferent(_, a) => a,
|
||||
CompareImplItemObligation { span, .. } => span,
|
||||
|
|
|
@ -636,6 +636,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// buf.push_back(3);
|
||||
/// buf.push_back(4);
|
||||
/// buf.push_back(5);
|
||||
/// buf.push_back(6);
|
||||
/// assert_eq!(buf.get(1), Some(&4));
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -661,10 +662,11 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
/// buf.push_back(3);
|
||||
/// buf.push_back(4);
|
||||
/// buf.push_back(5);
|
||||
/// buf.push_back(6);
|
||||
/// assert_eq!(buf[1], 4);
|
||||
/// if let Some(elem) = buf.get_mut(1) {
|
||||
/// *elem = 7;
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(buf[1], 7);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
@ -271,7 +271,7 @@ pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
|
|||
/// The primary separator of path components for the current platform.
|
||||
///
|
||||
/// For example, `/` on Unix and `\` on Windows.
|
||||
#[unstable(feature = "main_separator_str", issue = "94071")]
|
||||
#[stable(feature = "main_separator_str", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -351,7 +351,7 @@ pub fn interactive_path() -> io::Result<Profile> {
|
|||
Ok(template)
|
||||
}
|
||||
|
||||
// install a git hook to automatically run tidy --bless, if they want
|
||||
// install a git hook to automatically run tidy, if they want
|
||||
fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
|
||||
let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| {
|
||||
assert!(output.status.success(), "failed to run `git`");
|
||||
|
@ -367,7 +367,7 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> {
|
|||
println!();
|
||||
println!(
|
||||
"Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
|
||||
If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before
|
||||
If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before
|
||||
pushing your code to ensure your code is up to par. If you decide later that this behavior is
|
||||
undesirable, simply delete the `pre-push` file from .git/hooks."
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Call `tidy --bless` before git push
|
||||
# Call `tidy` before git push
|
||||
# Copy this script to .git/hooks to activate,
|
||||
# and remove it from .git/hooks to deactivate.
|
||||
#
|
||||
|
|
15
src/test/ui/borrowck/issue-93078.rs
Normal file
15
src/test/ui/borrowck/issue-93078.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
trait Modify {
|
||||
fn modify(&mut self) ;
|
||||
}
|
||||
|
||||
impl<T> Modify for T {
|
||||
fn modify(&mut self) {}
|
||||
}
|
||||
|
||||
trait Foo {
|
||||
fn mute(&mut self) {
|
||||
self.modify(); //~ ERROR cannot borrow `self` as mutable
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
12
src/test/ui/borrowck/issue-93078.stderr
Normal file
12
src/test/ui/borrowck/issue-93078.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
|
||||
--> $DIR/issue-93078.rs:11:9
|
||||
|
|
||||
LL | self.modify();
|
||||
| ^^^^^^^^^^^^^ cannot borrow as mutable
|
||||
|
|
||||
= note: as `Self` may be unsized, this call attempts to take `&mut &mut self`
|
||||
= note: however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0596`.
|
4
src/test/ui/error-codes/E0013.rs
Normal file
4
src/test/ui/error-codes/E0013.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
static X: i32 = 42;
|
||||
const Y: i32 = X; //~ ERROR constants cannot refer to statics [E0013]
|
||||
|
||||
fn main() {}
|
11
src/test/ui/error-codes/E0013.stderr
Normal file
11
src/test/ui/error-codes/E0013.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error[E0013]: constants cannot refer to statics
|
||||
--> $DIR/E0013.rs:2:16
|
||||
|
|
||||
LL | const Y: i32 = X;
|
||||
| ^
|
||||
|
|
||||
= help: consider extracting the value of the `static` to a `const`, and referring to that
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0013`.
|
8
src/test/ui/error-codes/E0015.rs
Normal file
8
src/test/ui/error-codes/E0015.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
fn create_some() -> Option<u8> {
|
||||
Some(1)
|
||||
}
|
||||
|
||||
const FOO: Option<u8> = create_some();
|
||||
//~^ ERROR cannot call non-const fn `create_some` in constants [E0015]
|
||||
|
||||
fn main() {}
|
11
src/test/ui/error-codes/E0015.stderr
Normal file
11
src/test/ui/error-codes/E0015.stderr
Normal file
|
@ -0,0 +1,11 @@
|
|||
error[E0015]: cannot call non-const fn `create_some` in constants
|
||||
--> $DIR/E0015.rs:5:25
|
||||
|
|
||||
LL | const FOO: Option<u8> = create_some();
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
10
src/test/ui/type/closure-with-wrong-borrows.rs
Normal file
10
src/test/ui/type/closure-with-wrong-borrows.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
struct S<'a>(&'a str);
|
||||
|
||||
fn f(inner: fn(&str, &S)) {
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
fn main() {
|
||||
let inner: fn(_, _) = unimplemented!();
|
||||
f(inner); //~ ERROR mismatched types
|
||||
}
|
19
src/test/ui/type/closure-with-wrong-borrows.stderr
Normal file
19
src/test/ui/type/closure-with-wrong-borrows.stderr
Normal file
|
@ -0,0 +1,19 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/closure-with-wrong-borrows.rs:9:7
|
||||
|
|
||||
LL | f(inner);
|
||||
| - ^^^^^ one type is more general than the other
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected fn pointer `for<'a, 'b, 'c> fn(&'a str, &'b S<'c>)`
|
||||
found fn pointer `fn(_, _)`
|
||||
note: function defined here
|
||||
--> $DIR/closure-with-wrong-borrows.rs:3:4
|
||||
|
|
||||
LL | fn f(inner: fn(&str, &S)) {
|
||||
| ^ -------------------
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -3,14 +3,17 @@ use std::hash::Hash;
|
|||
|
||||
use rustdoc_json_types::{
|
||||
Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
|
||||
GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Module, OpaqueTy, Path,
|
||||
Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
|
||||
TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
|
||||
GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module,
|
||||
OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias,
|
||||
Type, TypeBinding, TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate,
|
||||
};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{item_kind::Kind, json_find, Error, ErrorKind};
|
||||
|
||||
// This is a rustc implementation detail that we rely on here
|
||||
const LOCAL_CRATE_ID: u32 = 0;
|
||||
|
||||
/// The Validator walks over the JSON tree, and ensures it is well formed.
|
||||
/// It is made of several parts.
|
||||
///
|
||||
|
@ -53,12 +56,19 @@ impl<'a> Validator<'a> {
|
|||
}
|
||||
|
||||
pub fn check_crate(&mut self) {
|
||||
// Graph traverse the index
|
||||
let root = &self.krate.root;
|
||||
self.add_mod_id(root);
|
||||
while let Some(id) = set_remove(&mut self.todo) {
|
||||
self.seen_ids.insert(id);
|
||||
self.check_item(id);
|
||||
}
|
||||
|
||||
let root_crate_id = self.krate.index[root].crate_id;
|
||||
assert_eq!(root_crate_id, LOCAL_CRATE_ID, "LOCAL_CRATE_ID is wrong");
|
||||
for (id, item_info) in &self.krate.paths {
|
||||
self.check_item_info(id, item_info);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, id: &'a Id) {
|
||||
|
@ -364,6 +374,19 @@ impl<'a> Validator<'a> {
|
|||
fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd));
|
||||
}
|
||||
|
||||
fn check_item_info(&mut self, id: &Id, item_info: &ItemSummary) {
|
||||
// FIXME: Their should be a better way to determine if an item is local, rather than relying on `LOCAL_CRATE_ID`,
|
||||
// which encodes rustc implementation details.
|
||||
if item_info.crate_id == LOCAL_CRATE_ID && !self.krate.index.contains_key(id) {
|
||||
self.errs.push(Error {
|
||||
id: id.clone(),
|
||||
kind: ErrorKind::Custom(
|
||||
"Id for local item in `paths` but not in `index`".to_owned(),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) {
|
||||
if let Some(kind) = self.kind_of(id) {
|
||||
if valid(kind) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use rustdoc_json_types::{Crate, Item, Visibility};
|
||||
use rustdoc_json_types::{Crate, Item, ItemKind, ItemSummary, Visibility, FORMAT_VERSION};
|
||||
|
||||
use crate::json_find::SelectorPart;
|
||||
|
||||
|
@ -64,3 +64,101 @@ fn errors_on_missing_links() {
|
|||
}],
|
||||
);
|
||||
}
|
||||
|
||||
// Test we would catch
|
||||
// https://github.com/rust-lang/rust/issues/104064#issuecomment-1368589718
|
||||
#[test]
|
||||
fn errors_on_local_in_paths_and_not_index() {
|
||||
let krate = Crate {
|
||||
root: id("0:0:1572"),
|
||||
crate_version: None,
|
||||
includes_private: false,
|
||||
index: HashMap::from_iter([
|
||||
(
|
||||
id("0:0:1572"),
|
||||
Item {
|
||||
id: id("0:0:1572"),
|
||||
crate_id: 0,
|
||||
name: Some("microcore".to_owned()),
|
||||
span: None,
|
||||
visibility: Visibility::Public,
|
||||
docs: None,
|
||||
links: HashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]),
|
||||
attrs: Vec::new(),
|
||||
deprecation: None,
|
||||
inner: ItemEnum::Module(Module {
|
||||
is_crate: true,
|
||||
items: vec![id("0:1:717")],
|
||||
is_stripped: false,
|
||||
}),
|
||||
},
|
||||
),
|
||||
(
|
||||
id("0:1:717"),
|
||||
Item {
|
||||
id: id("0:1:717"),
|
||||
crate_id: 0,
|
||||
name: Some("i32".to_owned()),
|
||||
span: None,
|
||||
visibility: Visibility::Public,
|
||||
docs: None,
|
||||
links: HashMap::default(),
|
||||
attrs: Vec::new(),
|
||||
deprecation: None,
|
||||
inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }),
|
||||
},
|
||||
),
|
||||
]),
|
||||
paths: HashMap::from_iter([(
|
||||
id("0:1:1571"),
|
||||
ItemSummary {
|
||||
crate_id: 0,
|
||||
path: vec!["microcore".to_owned(), "i32".to_owned()],
|
||||
kind: ItemKind::Primitive,
|
||||
},
|
||||
)]),
|
||||
external_crates: HashMap::default(),
|
||||
format_version: rustdoc_json_types::FORMAT_VERSION,
|
||||
};
|
||||
|
||||
check(
|
||||
&krate,
|
||||
&[Error {
|
||||
id: id("0:1:1571"),
|
||||
kind: ErrorKind::Custom("Id for local item in `paths` but not in `index`".to_owned()),
|
||||
}],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic = "LOCAL_CRATE_ID is wrong"]
|
||||
fn checks_local_crate_id_is_correct() {
|
||||
let krate = Crate {
|
||||
root: id("root"),
|
||||
crate_version: None,
|
||||
includes_private: false,
|
||||
index: HashMap::from_iter([(
|
||||
id("root"),
|
||||
Item {
|
||||
id: id("root"),
|
||||
crate_id: LOCAL_CRATE_ID.wrapping_add(1),
|
||||
name: Some("irrelavent".to_owned()),
|
||||
span: None,
|
||||
visibility: Visibility::Public,
|
||||
docs: None,
|
||||
links: HashMap::default(),
|
||||
attrs: Vec::new(),
|
||||
deprecation: None,
|
||||
inner: ItemEnum::Module(Module {
|
||||
is_crate: true,
|
||||
items: vec![],
|
||||
is_stripped: false,
|
||||
}),
|
||||
},
|
||||
)]),
|
||||
paths: HashMap::default(),
|
||||
external_crates: HashMap::default(),
|
||||
format_version: FORMAT_VERSION,
|
||||
};
|
||||
check(&krate, &[]);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
//!
|
||||
//! 4. We check that the error code is actually emitted by the compiler.
|
||||
//! - This is done by searching `compiler/` with a regex.
|
||||
//!
|
||||
//! This tidy check was merged and refactored from two others. See #PR_NUM for information about linting changes that occurred during this refactor.
|
||||
|
||||
use std::{ffi::OsStr, fs, path::Path};
|
||||
|
||||
|
@ -33,8 +31,8 @@ const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602"];
|
|||
|
||||
// Error codes that don't yet have a UI test. This list will eventually be removed.
|
||||
const IGNORE_UI_TEST_CHECK: &[&str] = &[
|
||||
"E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717",
|
||||
"E0729", "E0789",
|
||||
"E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729",
|
||||
"E0789",
|
||||
];
|
||||
|
||||
macro_rules! verbose_print {
|
||||
|
@ -57,7 +55,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
|
|||
let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose);
|
||||
|
||||
// Stage 3: check list has UI tests
|
||||
check_error_codes_tests(root_path, &error_codes, &mut errors, verbose);
|
||||
check_error_codes_tests(root_path, &error_codes, &mut errors, verbose, &no_longer_emitted);
|
||||
|
||||
// Stage 4: check list is emitted by compiler
|
||||
check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted, verbose);
|
||||
|
@ -174,8 +172,9 @@ fn check_error_codes_docs(
|
|||
return;
|
||||
}
|
||||
|
||||
let (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) =
|
||||
let (found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted) =
|
||||
check_explanation_has_doctest(&contents, &err_code);
|
||||
|
||||
if emit_ignore_warning {
|
||||
verbose_print!(
|
||||
verbose,
|
||||
|
@ -183,13 +182,11 @@ fn check_error_codes_docs(
|
|||
`IGNORE_DOCTEST_CHECK` constant instead."
|
||||
);
|
||||
}
|
||||
if emit_no_longer_warning {
|
||||
|
||||
if no_longer_emitted {
|
||||
no_longer_emitted_codes.push(err_code.to_owned());
|
||||
verbose_print!(
|
||||
verbose,
|
||||
"warning: Error code `{err_code}` is no longer emitted and should be removed entirely."
|
||||
);
|
||||
}
|
||||
|
||||
if !found_code_example {
|
||||
verbose_print!(
|
||||
verbose,
|
||||
|
@ -226,7 +223,7 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo
|
|||
let mut found_proper_doctest = false;
|
||||
|
||||
let mut emit_ignore_warning = false;
|
||||
let mut emit_no_longer_warning = false;
|
||||
let mut no_longer_emitted = false;
|
||||
|
||||
for line in explanation.lines() {
|
||||
let line = line.trim();
|
||||
|
@ -246,13 +243,13 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo
|
|||
} else if line
|
||||
.starts_with("#### Note: this error code is no longer emitted by the compiler")
|
||||
{
|
||||
emit_no_longer_warning = true;
|
||||
no_longer_emitted = true;
|
||||
found_code_example = true;
|
||||
found_proper_doctest = true;
|
||||
}
|
||||
}
|
||||
|
||||
(found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning)
|
||||
(found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted)
|
||||
}
|
||||
|
||||
// Stage 3: Checks that each error code has a UI test in the correct directory
|
||||
|
@ -261,6 +258,7 @@ fn check_error_codes_tests(
|
|||
error_codes: &[String],
|
||||
errors: &mut Vec<String>,
|
||||
verbose: bool,
|
||||
no_longer_emitted: &[String],
|
||||
) {
|
||||
let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH));
|
||||
|
||||
|
@ -295,6 +293,11 @@ fn check_error_codes_tests(
|
|||
}
|
||||
};
|
||||
|
||||
if no_longer_emitted.contains(code) {
|
||||
// UI tests *can't* contain error codes that are no longer emitted.
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut found_code = false;
|
||||
|
||||
for line in file.lines() {
|
||||
|
|
Loading…
Reference in a new issue