Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #90347

Merged
merged 16 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions compiler/rustc_ast/src/tokenstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
56 changes: 49 additions & 7 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
});
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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()) {
Expand All @@ -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 {
Expand All @@ -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);
Expand All @@ -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);
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
descr: "module",
path,
accessible: true,
note: None,
},
));
} else {
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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; \
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
Original file line number Diff line number Diff line change
@@ -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();
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
31 changes: 31 additions & 0 deletions src/test/ui/suggestions/suggest-tryinto-edition-change.rs
Original file line number Diff line number Diff line change
@@ -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();
}
76 changes: 76 additions & 0 deletions src/test/ui/suggestions/suggest-tryinto-edition-change.stderr
Original file line number Diff line number Diff line change
@@ -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`.
7 changes: 7 additions & 0 deletions src/test/ui/trait-bounds/issue-75961.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// check-pass

pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
<&mut () as Clone>::clone(&s);
}

fn main() {}