Skip to content
This repository was archived by the owner on Nov 24, 2023. It is now read-only.

Commit 1ca1cbd

Browse files
authored
Merge pull request #156 from rust-lang-nursery/revert-155-multiple-solutions
Revert "Allow multiple solutions in a suggestion"
2 parents 557ebdf + 42fd66d commit 1ca1cbd

9 files changed

+169
-129
lines changed

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ pub fn collect_suggestions<S: ::std::hash::BuildHasher>(
184184
})
185185
.filter_map(collect_span)
186186
.collect();
187-
if replacements.len() >= 1 {
187+
if replacements.len() == 1 {
188188
Some(Solution {
189189
message: child.message.clone(),
190190
replacements,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
let xs = vec![String::from("foo")];
3+
let d: &Display = &xs;
4+
println!("{}", d);
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
{
2+
"message": "cannot find type `Display` in this scope",
3+
"code": {
4+
"code": "E0412",
5+
"explanation": "\nThe type name used is not in scope.\n\nErroneous code examples:\n\n```compile_fail,E0412\nimpl Something {} // error: type name `Something` is not in scope\n\n// or:\n\ntrait Foo {\n fn bar(N); // error: type name `N` is not in scope\n}\n\n// or:\n\nfn foo(x: T) {} // type name `T` is not in scope\n```\n\nTo fix this error, please verify you didn't misspell the type name, you did\ndeclare it or imported it into the scope. Examples:\n\n```\nstruct Something;\n\nimpl Something {} // ok!\n\n// or:\n\ntrait Foo {\n type N;\n\n fn bar(_: Self::N); // ok!\n}\n\n// or:\n\nfn foo<T>(x: T) {} // ok!\n```\n\nAnother case that causes this error is when a type is imported into a parent\nmodule. To fix this, you can follow the suggestion and use File directly or\n`use super::File;` which will import the types from the parent namespace. An\nexample that causes this error is below:\n\n```compile_fail,E0412\nuse std::fs::File;\n\nmod foo {\n fn some_function(f: File) {}\n}\n```\n\n```\nuse std::fs::File;\n\nmod foo {\n // either\n use super::File;\n // or\n // use std::fs::File;\n fn foo(f: File) {}\n}\n# fn main() {} // don't insert it for us; that'll break imports\n```\n"
6+
},
7+
"level": "error",
8+
"spans": [
9+
{
10+
"file_name": "./tests/everything/skip-multi-option-lints.rs",
11+
"byte_start": 64,
12+
"byte_end": 71,
13+
"line_start": 3,
14+
"line_end": 3,
15+
"column_start": 13,
16+
"column_end": 20,
17+
"is_primary": true,
18+
"text": [
19+
{
20+
"text": " let d: &Display = &xs;",
21+
"highlight_start": 13,
22+
"highlight_end": 20
23+
}
24+
],
25+
"label": "not found in this scope",
26+
"suggested_replacement": null,
27+
"expansion": null
28+
}
29+
],
30+
"children": [
31+
{
32+
"message": "possible candidates are found in other modules, you can import them into scope",
33+
"code": null,
34+
"level": "help",
35+
"spans": [
36+
{
37+
"file_name": "./tests/everything/skip-multi-option-lints.rs",
38+
"byte_start": 0,
39+
"byte_end": 0,
40+
"line_start": 1,
41+
"line_end": 1,
42+
"column_start": 1,
43+
"column_end": 1,
44+
"is_primary": true,
45+
"text": [
46+
{
47+
"text": "fn main() {",
48+
"highlight_start": 1,
49+
"highlight_end": 1
50+
}
51+
],
52+
"label": null,
53+
"suggested_replacement": "use std::fmt::Display;\n\n",
54+
"suggestion_applicability": "Unspecified",
55+
"expansion": null
56+
},
57+
{
58+
"file_name": "./tests/everything/skip-multi-option-lints.rs",
59+
"byte_start": 0,
60+
"byte_end": 0,
61+
"line_start": 1,
62+
"line_end": 1,
63+
"column_start": 1,
64+
"column_end": 1,
65+
"is_primary": true,
66+
"text": [
67+
{
68+
"text": "fn main() {",
69+
"highlight_start": 1,
70+
"highlight_end": 1
71+
}
72+
],
73+
"label": null,
74+
"suggested_replacement": "use std::path::Display;\n\n",
75+
"suggestion_applicability": "Unspecified",
76+
"expansion": null
77+
}
78+
],
79+
"children": [],
80+
"rendered": null
81+
}
82+
],
83+
"rendered": "error[E0412]: cannot find type `Display` in this scope\n --> ./tests/everything/skip-multi-option-lints.rs:3:13\n |\n3 | let d: &Display = &xs;\n | ^^^^^^^ not found in this scope\nhelp: possible candidates are found in other modules, you can import them into scope\n |\n1 | use std::fmt::Display;\n |\n1 | use std::path::Display;\n |\n\n"
84+
}
85+
{
86+
"message": "aborting due to previous error",
87+
"code": null,
88+
"level": "error",
89+
"spans": [],
90+
"children": [],
91+
"rendered": "error: aborting due to previous error\n\n"
92+
}
93+
{
94+
"message": "For more information about this error, try `rustc --explain E0412`.",
95+
"code": null,
96+
"level": "",
97+
"spans": [],
98+
"children": [],
99+
"rendered": "For more information about this error, try `rustc --explain E0412`.\n"
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
let xs = vec![String::from("foo")];
3+
let d: &Display = &xs;
4+
println!("{}", d);
5+
}

tests/edge_cases.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
extern crate rustfix;
2+
use std::collections::HashSet;
3+
use std::fs;
4+
5+
#[test]
6+
fn multiple_fix_options_yield_no_suggestions() {
7+
let json = fs::read_to_string("./tests/edge-cases/skip-multi-option-lints.json").unwrap();
8+
let expected_suggestions =
9+
rustfix::get_suggestions_from_json(&json, &HashSet::new(), rustfix::Filter::Everything)
10+
.unwrap();
11+
assert!(expected_suggestions.is_empty());
12+
}

tests/everything/multiple-solutions.fixed.rs

-5
This file was deleted.

tests/everything/multiple-solutions.json

-114
This file was deleted.

tests/everything/multiple-solutions.rs

-5
This file was deleted.

tests/parse_and_replace.rs

+46-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ mod fixmode {
3030

3131
mod settings {
3232
// can be set as env var to debug
33+
pub const CHECK_JSON: &str = "RUSTFIX_TEST_CHECK_JSON";
34+
pub const RECORD_JSON: &str = "RUSTFIX_TEST_RECORD_JSON";
3335
pub const RECORD_FIXED_RUST: &str = "RUSTFIX_TEST_RECORD_FIXED_RUST";
3436
}
3537

@@ -61,6 +63,20 @@ fn compile(file: &Path, mode: &str) -> Result<Output, Error> {
6163
Ok(res)
6264
}
6365

66+
fn compile_and_get_json_errors(file: &Path, mode: &str) -> Result<String, Error> {
67+
let res = compile(file, mode)?;
68+
let stderr = String::from_utf8(res.stderr)?;
69+
70+
match res.status.code() {
71+
Some(0) | Some(1) | Some(101) => Ok(stderr),
72+
_ => Err(format_err!(
73+
"failed with status {:?}: {}",
74+
res.status.code(),
75+
stderr
76+
)),
77+
}
78+
}
79+
6480
fn compiles_without_errors(file: &Path, mode: &str) -> Result<(), Error> {
6581
let res = compile(file, mode)?;
6682

@@ -107,8 +123,7 @@ fn diff(expected: &str, actual: &str) -> String {
107123
write!(
108124
&mut res,
109125
"differences found (+ == actual, - == expected):\n"
110-
)
111-
.unwrap();
126+
).unwrap();
112127
different = true;
113128
}
114129
for diff in diff.lines() {
@@ -135,12 +150,39 @@ fn test_rustfix_with_file<P: AsRef<Path>>(file: P, mode: &str) -> Result<(), Err
135150

136151
debug!("next up: {:?}", file);
137152
let code = read_file(file).context(format!("could not read {}", file.display()))?;
138-
let errors = read_file(&json_file)
139-
.with_context(|_| format!("could not load json suggestions for {}", file.display()))?;
153+
let errors = compile_and_get_json_errors(file, mode)
154+
.context(format!("could compile {}", file.display()))?;
140155
let suggestions =
141156
rustfix::get_suggestions_from_json(&errors, &HashSet::new(), filter_suggestions)
142157
.context("could not load suggestions")?;
143158

159+
if std::env::var(settings::RECORD_JSON).is_ok() {
160+
use std::io::Write;
161+
let mut recorded_json = fs::File::create(&file.with_extension("recorded.json")).context(
162+
format!("could not create recorded.json for {}", file.display()),
163+
)?;
164+
recorded_json.write_all(errors.as_bytes())?;
165+
}
166+
167+
if std::env::var(settings::CHECK_JSON).is_ok() {
168+
let expected_json = read_file(&json_file).context(format!(
169+
"could not load json fixtures for {}",
170+
file.display()
171+
))?;
172+
let expected_suggestions =
173+
rustfix::get_suggestions_from_json(&expected_json, &HashSet::new(), filter_suggestions)
174+
.context("could not load expected suggesitons")?;
175+
176+
ensure!(
177+
expected_suggestions == suggestions,
178+
"got unexpected suggestions from clippy:\n{}",
179+
diff(
180+
&format!("{:?}", expected_suggestions),
181+
&format!("{:?}", suggestions)
182+
)
183+
);
184+
}
185+
144186
let fixed = apply_suggestions(&code, &suggestions)
145187
.context(format!("could not apply suggestions to {}", file.display()))?;
146188

0 commit comments

Comments
 (0)