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
This commit is contained in:
bors 2021-10-27 18:42:13 +00:00
commit 4e0d3973fa
13 changed files with 227 additions and 15 deletions

View File

@ -221,12 +221,6 @@ impl AttrAnnotatedTokenStream {
for attr in &data.attrs {
match attr.style {
crate::AttrStyle::Outer => {
assert!(
inner_attrs.len() == 0,
"Found outer attribute {:?} after inner attrs {:?}",
attr,
inner_attrs
);
outer_attrs.push(attr);
}
crate::AttrStyle::Inner => {

View File

@ -66,6 +66,8 @@ crate struct ImportSuggestion {
pub descr: &'static str,
pub path: Path,
pub accessible: bool,
/// An extra note that should be issued if this item is suggested
pub note: Option<String>,
}
/// Adjust the impl span so that just the `impl` keyword is taken by removing
@ -872,11 +874,38 @@ impl<'a> Resolver<'a> {
}
if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
// See if we're recommending TryFrom, TryInto, or FromIterator and add
// a note about editions
let note = if let Some(did) = did {
let requires_note = !did.is_local()
&& this.cstore().item_attrs(did, this.session).iter().any(
|attr| {
if attr.has_name(sym::rustc_diagnostic_item) {
[sym::TryInto, sym::TryFrom, sym::FromIterator]
.map(|x| Some(x))
.contains(&attr.value_str())
} else {
false
}
},
);
requires_note.then(|| {
format!(
"'{}' is included in the prelude starting in Edition 2021",
path_names_to_string(&path)
)
})
} else {
None
};
candidates.push(ImportSuggestion {
did,
descr: res.descr(),
path,
accessible: child_accessible,
note,
});
}
}
@ -1764,12 +1793,14 @@ crate fn show_candidates(
return;
}
let mut accessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>)> = Vec::new();
let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
Vec::new();
let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
Vec::new();
candidates.iter().for_each(|c| {
(if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
.push((path_names_to_string(&c.path), c.descr, c.did))
.push((path_names_to_string(&c.path), c.descr, c.did, &c.note))
});
// we want consistent results across executions, but candidates are produced
@ -1792,6 +1823,10 @@ crate fn show_candidates(
let instead = if instead { " instead" } else { "" };
let mut msg = format!("consider importing {} {}{}", determiner, kind, instead);
for note in accessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
err.note(note);
}
if let Some(span) = use_placement_span {
for candidate in &mut accessible_path_strings {
// produce an additional newline to separate the new use statement
@ -1820,7 +1855,7 @@ crate fn show_candidates(
assert!(!inaccessible_path_strings.is_empty());
if inaccessible_path_strings.len() == 1 {
let (name, descr, def_id) = &inaccessible_path_strings[0];
let (name, descr, def_id, note) = &inaccessible_path_strings[0];
let msg = format!("{} `{}` exists but is inaccessible", descr, name);
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
@ -1832,12 +1867,15 @@ crate fn show_candidates(
} else {
err.note(&msg);
}
if let Some(note) = (*note).as_deref() {
err.note(note);
}
} else {
let (_, descr_first, _) = &inaccessible_path_strings[0];
let (_, descr_first, _, _) = &inaccessible_path_strings[0];
let descr = if inaccessible_path_strings
.iter()
.skip(1)
.all(|(_, descr, _)| descr == descr_first)
.all(|(_, descr, _, _)| descr == descr_first)
{
descr_first.to_string()
} else {
@ -1848,7 +1886,7 @@ crate fn show_candidates(
let mut has_colon = false;
let mut spans = Vec::new();
for (name, _, def_id) in &inaccessible_path_strings {
for (name, _, def_id, _) in &inaccessible_path_strings {
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
let span = definitions.def_span(local_def_id);
let span = session.source_map().guess_head_span(span);
@ -1868,6 +1906,10 @@ crate fn show_candidates(
multi_span.push_span_label(span, format!("`{}`: not accessible", name));
}
for note in inaccessible_path_strings.iter().map(|cand| cand.3.as_ref()).flatten() {
err.note(note);
}
err.span_note(multi_span, &msg);
}
}

View File

@ -1502,6 +1502,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
descr: "module",
path,
accessible: true,
note: None,
},
));
} else {

View File

@ -1203,6 +1203,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut candidates = valid_out_of_scope_traits;
candidates.sort();
candidates.dedup();
// `TryFrom` and `FromIterator` have no methods
let edition_fix = candidates
.iter()
.find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
.map(|&d| d);
err.help("items from traits can only be used if the trait is in scope");
let msg = format!(
"the following {traits_are} implemented but not in scope; \
@ -1212,6 +1219,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
self.suggest_use_candidates(err, msg, candidates);
if let Some(did) = edition_fix {
err.note(&format!(
"'{}' is included in the prelude starting in Edition 2021",
with_crate_prefix(|| self.tcx.def_path_str(did))
));
}
true
} else {
false

View File

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

View File

@ -1257,7 +1257,7 @@ impl CStr {
#[inline]
#[must_use]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")]
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
// SAFETY: Casting to CStr is safe because its internal representation
// is a [u8] too (safe only inside std).

View File

@ -0,0 +1,13 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(ICE)]
pub fn derive(_: TokenStream) -> TokenStream {
r#"#[allow(missing_docs)] struct X { }"#.parse().unwrap()
}

View File

@ -0,0 +1,15 @@
// aux-build:issue-89971-outer-attr-following-inner-attr-ice.rs
#[macro_use]
extern crate issue_89971_outer_attr_following_inner_attr_ice;
fn main() {
Mew();
X {};
}
#![deny(missing_docs)]
//~^ ERROR an inner attribute is not permitted in this context
#[derive(ICE)]
#[deny(missing_docs)]
struct Mew();

View File

@ -0,0 +1,18 @@
error: an inner attribute is not permitted in this context
--> $DIR/issue-89971-outer-attr-following-inner-attr-ice.rs:11:1
|
LL | #![deny(missing_docs)]
| ^^^^^^^^^^^^^^^^^^^^^^
...
LL | struct Mew();
| ------------- the inner attribute doesn't annotate this struct
|
= note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
help: to annotate the struct, change the attribute from inner to outer style
|
LL - #![deny(missing_docs)]
LL + #[deny(missing_docs)]
|
error: aborting due to previous error

View File

@ -15,6 +15,7 @@ LL | fn try_into(self) -> Result<T, Self::Error>;
| the method is available for `Rc<u8>` here
|
= help: items from traits can only be used if the trait is in scope
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
help: consider wrapping the receiver expression with the appropriate type
|
LL | let _: u32 = Box::new(3u8).try_into().unwrap();

View File

@ -0,0 +1,31 @@
// Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions
// Edition 2021 change
// edition:2018
fn test() {
let _i: i16 = 0_i32.try_into().unwrap();
//~^ ERROR no method named `try_into` found for type `i32` in the current scope
//~| NOTE method not found in `i32`
//~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
let _i: i16 = TryFrom::try_from(0_i32).unwrap();
//~^ ERROR failed to resolve: use of undeclared type
//~| NOTE not found in this scope
//~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
//~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
let _i: i16 = TryInto::try_into(0_i32).unwrap();
//~^ ERROR failed to resolve: use of undeclared type
//~| NOTE not found in this scope
//~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
//~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021
let _v: Vec<_> = FromIterator::from_iter(&[1]);
//~^ ERROR failed to resolve: use of undeclared type
//~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
//~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
}
fn main() {
test();
}

View File

@ -0,0 +1,76 @@
error[E0433]: failed to resolve: use of undeclared type `TryFrom`
--> $DIR/suggest-tryinto-edition-change.rs:11:19
|
LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap();
| ^^^^^^^ not found in this scope
|
= note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021
= note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021
help: consider importing one of these items
|
LL | use core::convert::TryFrom;
|
LL | use std::convert::TryFrom;
|
error[E0433]: failed to resolve: use of undeclared type `TryInto`
--> $DIR/suggest-tryinto-edition-change.rs:17:19
|
LL | let _i: i16 = TryInto::try_into(0_i32).unwrap();
| ^^^^^^^ not found in this scope
|
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
= note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021
help: consider importing one of these items
|
LL | use core::convert::TryInto;
|
LL | use std::convert::TryInto;
|
error[E0433]: failed to resolve: use of undeclared type `FromIterator`
--> $DIR/suggest-tryinto-edition-change.rs:23:22
|
LL | let _v: Vec<_> = FromIterator::from_iter(&[1]);
| ^^^^^^^^^^^^
|
::: $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
LL | pub trait IntoIterator {
| ---------------------- similarly named trait `IntoIterator` defined here
|
= note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021
= note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021
help: a trait with a similar name exists
|
LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]);
| ~~~~~~~~~~~~
help: consider importing one of these items
|
LL | use core::iter::FromIterator;
|
LL | use std::iter::FromIterator;
|
error[E0599]: no method named `try_into` found for type `i32` in the current scope
--> $DIR/suggest-tryinto-edition-change.rs:6:25
|
LL | let _i: i16 = 0_i32.try_into().unwrap();
| ^^^^^^^^ method not found in `i32`
|
::: $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
LL | fn try_into(self) -> Result<T, Self::Error>;
| -------- the method is available for `i32` here
|
= help: items from traits can only be used if the trait is in scope
= note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
LL | use std::convert::TryInto;
|
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0433, E0599.
For more information about an error, try `rustc --explain E0433`.

View File

@ -0,0 +1,7 @@
// check-pass
pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
<&mut () as Clone>::clone(&s);
}
fn main() {}