Skip to content

Commit 4e0d397

Browse files
committed
Auto merge of #90347 - matthiaskrgr:rollup-rp2ms7j, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #90239 (Consistent big O notation in map.rs) - #90267 (fix: inner attribute followed by outer attribute causing ICE) - #90288 (Add hint for people missing `TryFrom`, `TryInto`, `FromIterator` import pre-2021) - #90304 (Add regression test for #75961) - #90344 (Add tracking issue number to const_cstr_unchecked) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents dd757b9 + 623c3e1 commit 4e0d397

File tree

13 files changed

+227
-15
lines changed

13 files changed

+227
-15
lines changed

compiler/rustc_ast/src/tokenstream.rs

-6
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,6 @@ impl AttrAnnotatedTokenStream {
221221
for attr in &data.attrs {
222222
match attr.style {
223223
crate::AttrStyle::Outer => {
224-
assert!(
225-
inner_attrs.len() == 0,
226-
"Found outer attribute {:?} after inner attrs {:?}",
227-
attr,
228-
inner_attrs
229-
);
230224
outer_attrs.push(attr);
231225
}
232226
crate::AttrStyle::Inner => {

compiler/rustc_resolve/src/diagnostics.rs

+49-7
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ crate struct ImportSuggestion {
6666
pub descr: &'static str,
6767
pub path: Path,
6868
pub accessible: bool,
69+
/// An extra note that should be issued if this item is suggested
70+
pub note: Option<String>,
6971
}
7072

7173
/// Adjust the impl span so that just the `impl` keyword is taken by removing
@@ -872,11 +874,38 @@ impl<'a> Resolver<'a> {
872874
}
873875

874876
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
877+
// See if we're recommending TryFrom, TryInto, or FromIterator and add
878+
// a note about editions
879+
let note = if let Some(did) = did {
880+
let requires_note = !did.is_local()
881+
&& this.cstore().item_attrs(did, this.session).iter().any(
882+
|attr| {
883+
if attr.has_name(sym::rustc_diagnostic_item) {
884+
[sym::TryInto, sym::TryFrom, sym::FromIterator]
885+
.map(|x| Some(x))
886+
.contains(&attr.value_str())
887+
} else {
888+
false
889+
}
890+
},
891+
);
892+
893+
requires_note.then(|| {
894+
format!(
895+
"'{}' is included in the prelude starting in Edition 2021",
896+
path_names_to_string(&path)
897+
)
898+
})
899+
} else {
900+
None
901+
};
902+
875903
candidates.push(ImportSuggestion {
876904
did,
877905
descr: res.descr(),
878906
path,
879907
accessible: child_accessible,
908+
note,
880909
});
881910
}
882911
}
@@ -1764,12 +1793,14 @@ crate fn show_candidates(
17641793
return;
17651794
}
17661795

1767-
let mut accessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
1768-
let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
1796+
let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
1797+
Vec::new();
1798+
let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
1799+
Vec::new();
17691800

17701801
candidates.iter().for_each(|c| {
17711802
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
1772-
.push((path_names_to_string(&c.path), c.descr, c.did))
1803+
.push((path_names_to_string(&c.path), c.descr, c.did, &c.note))
17731804
});
17741805

17751806
// we want consistent results across executions, but candidates are produced
@@ -1792,6 +1823,10 @@ crate fn show_candidates(
17921823
let instead = if instead { " instead" } else { "" };
17931824
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
17941825

1826+
for note in accessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
1827+
err.note(note);
1828+
}
1829+
17951830
if let Some(span) = use_placement_span {
17961831
for candidate in &mut accessible_path_strings {
17971832
// produce an additional newline to separate the new use statement
@@ -1820,7 +1855,7 @@ crate fn show_candidates(
18201855
assert!(!inaccessible_path_strings.is_empty());
18211856

18221857
if inaccessible_path_strings.len() == 1 {
1823-
let (name, descr, def_id) = &inaccessible_path_strings[0];
1858+
let (name, descr, def_id, note) = &inaccessible_path_strings[0];
18241859
let msg = format!("{} `{}` exists but is inaccessible", descr, name);
18251860

18261861
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
@@ -1832,12 +1867,15 @@ crate fn show_candidates(
18321867
} else {
18331868
err.note(&msg);
18341869
}
1870+
if let Some(note) = (*note).as_deref() {
1871+
err.note(note);
1872+
}
18351873
} else {
1836-
let (_, descr_first, _) = &inaccessible_path_strings[0];
1874+
let (_, descr_first, _, _) = &inaccessible_path_strings[0];
18371875
let descr = if inaccessible_path_strings
18381876
.iter()
18391877
.skip(1)
1840-
.all(|(_, descr, _)| descr == descr_first)
1878+
.all(|(_, descr, _, _)| descr == descr_first)
18411879
{
18421880
descr_first.to_string()
18431881
} else {
@@ -1848,7 +1886,7 @@ crate fn show_candidates(
18481886
let mut has_colon = false;
18491887

18501888
let mut spans = Vec::new();
1851-
for (name, _, def_id) in &inaccessible_path_strings {
1889+
for (name, _, def_id, _) in &inaccessible_path_strings {
18521890
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
18531891
let span = definitions.def_span(local_def_id);
18541892
let span = session.source_map().guess_head_span(span);
@@ -1868,6 +1906,10 @@ crate fn show_candidates(
18681906
multi_span.push_span_label(span, format!("`{}`: not accessible", name));
18691907
}
18701908

1909+
for note in inaccessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
1910+
err.note(note);
1911+
}
1912+
18711913
err.span_note(multi_span, &msg);
18721914
}
18731915
}

compiler/rustc_resolve/src/late/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
15021502
descr: "module",
15031503
path,
15041504
accessible: true,
1505+
note: None,
15051506
},
15061507
));
15071508
} else {

compiler/rustc_typeck/src/check/method/suggest.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12031203
let mut candidates = valid_out_of_scope_traits;
12041204
candidates.sort();
12051205
candidates.dedup();
1206+
1207+
// `TryFrom` and `FromIterator` have no methods
1208+
let edition_fix = candidates
1209+
.iter()
1210+
.find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
1211+
.map(|&d| d);
1212+
12061213
err.help("items from traits can only be used if the trait is in scope");
12071214
let msg = format!(
12081215
"the following {traits_are} implemented but not in scope; \
@@ -1212,6 +1219,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12121219
);
12131220

12141221
self.suggest_use_candidates(err, msg, candidates);
1222+
if let Some(did) = edition_fix {
1223+
err.note(&format!(
1224+
"'{}' is included in the prelude starting in Edition 2021",
1225+
with_crate_prefix(|| self.tcx.def_path_str(did))
1226+
));
1227+
}
1228+
12151229
true
12161230
} else {
12171231
false

library/alloc/src/collections/btree/map.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
5555
/// performance on *small* nodes of elements which are cheap to compare. However in the future we
5656
/// would like to further explore choosing the optimal search strategy based on the choice of B,
5757
/// and possibly other factors. Using linear search, searching for a random element is expected
58-
/// to take O(B * log(n)) comparisons, which is generally worse than a BST. In practice,
58+
/// to take B * log(n) comparisons, which is generally worse than a BST. In practice,
5959
/// however, performance is excellent.
6060
///
6161
/// It is a logic error for a key to be modified in such a way that the key's ordering relative to

library/std/src/ffi/c_str.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1257,7 +1257,7 @@ impl CStr {
12571257
#[inline]
12581258
#[must_use]
12591259
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
1260-
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
1260+
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")]
12611261
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
12621262
// SAFETY: Casting to CStr is safe because its internal representation
12631263
// is a [u8] too (safe only inside std).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![crate_type = "proc-macro"]
5+
6+
extern crate proc_macro;
7+
8+
use proc_macro::TokenStream;
9+
10+
#[proc_macro_derive(ICE)]
11+
pub fn derive(_: TokenStream) -> TokenStream {
12+
r#"#[allow(missing_docs)] struct X { }"#.parse().unwrap()
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// aux-build:issue-89971-outer-attr-following-inner-attr-ice.rs
2+
3+
#[macro_use]
4+
extern crate issue_89971_outer_attr_following_inner_attr_ice;
5+
6+
fn main() {
7+
Mew();
8+
X {};
9+
}
10+
11+
#![deny(missing_docs)]
12+
//~^ ERROR an inner attribute is not permitted in this context
13+
#[derive(ICE)]
14+
#[deny(missing_docs)]
15+
struct Mew();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: an inner attribute is not permitted in this context
2+
--> $DIR/issue-89971-outer-attr-following-inner-attr-ice.rs:11:1
3+
|
4+
LL | #![deny(missing_docs)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
...
7+
LL | struct Mew();
8+
| ------------- the inner attribute doesn't annotate this struct
9+
|
10+
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
11+
help: to annotate the struct, change the attribute from inner to outer style
12+
|
13+
LL - #![deny(missing_docs)]
14+
LL + #[deny(missing_docs)]
15+
|
16+
17+
error: aborting due to previous error
18+

src/test/ui/rust-2021/future-prelude-collision-shadow.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ LL | fn try_into(self) -> Result<T, Self::Error>;
1515
| the method is available for `Rc<u8>` here
1616
|
1717
= help: items from traits can only be used if the trait is in scope
18+
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
1819
help: consider wrapping the receiver expression with the appropriate type
1920
|
2021
LL | let _: u32 = Box::new(3u8).try_into().unwrap();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions
2+
// Edition 2021 change
3+
// edition:2018
4+
5+
fn test() {
6+
let _i: i16 = 0_i32.try_into().unwrap();
7+
//~^ ERROR no method named `try_into` found for type `i32` in the current scope
8+
//~| NOTE method not found in `i32`
9+
//~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
10+
11+
let _i: i16 = TryFrom::try_from(0_i32).unwrap();
12+
//~^ ERROR failed to resolve: use of undeclared type
13+
//~| NOTE not found in this scope
14+
//~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
15+
//~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
16+
17+
let _i: i16 = TryInto::try_into(0_i32).unwrap();
18+
//~^ ERROR failed to resolve: use of undeclared type
19+
//~| NOTE not found in this scope
20+
//~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
21+
//~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021
22+
23+
let _v: Vec<_> = FromIterator::from_iter(&[1]);
24+
//~^ ERROR failed to resolve: use of undeclared type
25+
//~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
26+
//~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
27+
}
28+
29+
fn main() {
30+
test();
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
error[E0433]: failed to resolve: use of undeclared type `TryFrom`
2+
--> $DIR/suggest-tryinto-edition-change.rs:11:19
3+
|
4+
LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap();
5+
| ^^^^^^^ not found in this scope
6+
|
7+
= note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
8+
= note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
9+
help: consider importing one of these items
10+
|
11+
LL | use core::convert::TryFrom;
12+
|
13+
LL | use std::convert::TryFrom;
14+
|
15+
16+
error[E0433]: failed to resolve: use of undeclared type `TryInto`
17+
--> $DIR/suggest-tryinto-edition-change.rs:17:19
18+
|
19+
LL | let _i: i16 = TryInto::try_into(0_i32).unwrap();
20+
| ^^^^^^^ not found in this scope
21+
|
22+
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
23+
= note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021
24+
help: consider importing one of these items
25+
|
26+
LL | use core::convert::TryInto;
27+
|
28+
LL | use std::convert::TryInto;
29+
|
30+
31+
error[E0433]: failed to resolve: use of undeclared type `FromIterator`
32+
--> $DIR/suggest-tryinto-edition-change.rs:23:22
33+
|
34+
LL | let _v: Vec<_> = FromIterator::from_iter(&[1]);
35+
| ^^^^^^^^^^^^
36+
|
37+
::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
38+
|
39+
LL | pub trait IntoIterator {
40+
| ---------------------- similarly named trait `IntoIterator` defined here
41+
|
42+
= note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
43+
= note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
44+
help: a trait with a similar name exists
45+
|
46+
LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]);
47+
| ~~~~~~~~~~~~
48+
help: consider importing one of these items
49+
|
50+
LL | use core::iter::FromIterator;
51+
|
52+
LL | use std::iter::FromIterator;
53+
|
54+
55+
error[E0599]: no method named `try_into` found for type `i32` in the current scope
56+
--> $DIR/suggest-tryinto-edition-change.rs:6:25
57+
|
58+
LL | let _i: i16 = 0_i32.try_into().unwrap();
59+
| ^^^^^^^^ method not found in `i32`
60+
|
61+
::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
62+
|
63+
LL | fn try_into(self) -> Result<T, Self::Error>;
64+
| -------- the method is available for `i32` here
65+
|
66+
= help: items from traits can only be used if the trait is in scope
67+
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
68+
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
69+
|
70+
LL | use std::convert::TryInto;
71+
|
72+
73+
error: aborting due to 4 previous errors
74+
75+
Some errors have detailed explanations: E0433, E0599.
76+
For more information about an error, try `rustc --explain E0433`.
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// check-pass
2+
3+
pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
4+
<&mut () as Clone>::clone(&s);
5+
}
6+
7+
fn main() {}

0 commit comments

Comments
 (0)