Skip to content

Commit

Permalink
Auto merge of #94072 - matthiaskrgr:rollup-7uu2286, r=matthiaskrgr
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #89869 (Add documentation to more `From::from` implementations.)
 - #93479 (Use `optflag` for `--report-time`)
 - #93693 (Suggest deriving required supertraits)
 - #93981 (Fix suggestion to slice if scurtinee is a reference to `Result` or `Option`)
 - #93996 (Do not suggest "is a function" for free variables)
 - #94030 (Correctly mark the span of captured arguments in `format_args!()`)
 - #94031 ([diagnostics] Add mentions to `Copy` types being valid for `union` fields)
 - #94064 (Update dist-x86_64-musl to Ubuntu 20.04)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Feb 17, 2022
2 parents 930fc4f + aa83189 commit 582b696
Show file tree
Hide file tree
Showing 62 changed files with 545 additions and 189 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_builtin_macros/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,11 +700,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
Some(idx)
}
}
parse::ArgumentNamed(name) => match args.named_args.get(&name) {
parse::ArgumentNamed(name, span) => match args.named_args.get(&name) {
Some(&idx) => Some(idx),
None => {
let msg = format!("there is no argument named `{}`", name);
ecx.struct_span_err(span, &msg).emit();
ecx.struct_span_err(template_span.from_inner(span), &msg).emit();
None
}
},
Expand Down
26 changes: 13 additions & 13 deletions compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_errors::{pluralize, Applicability, DiagnosticBuilder};
use rustc_expand::base::{self, *};
use rustc_parse_format as parse;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{MultiSpan, Span};
use rustc_span::{InnerSpan, MultiSpan, Span};
use smallvec::SmallVec;

use std::borrow::Cow;
Expand All @@ -26,7 +26,7 @@ enum ArgumentType {
enum Position {
Exact(usize),
Capture(usize),
Named(Symbol),
Named(Symbol, InnerSpan),
}

struct Context<'a, 'b> {
Expand Down Expand Up @@ -247,13 +247,13 @@ impl<'a, 'b> Context<'a, 'b> {
match *p {
parse::String(_) => {}
parse::NextArgument(ref mut arg) => {
if let parse::ArgumentNamed(s) = arg.position {
if let parse::ArgumentNamed(s, _) = arg.position {
arg.position = parse::ArgumentIs(lookup(s));
}
if let parse::CountIsName(s) = arg.format.width {
if let parse::CountIsName(s, _) = arg.format.width {
arg.format.width = parse::CountIsParam(lookup(s));
}
if let parse::CountIsName(s) = arg.format.precision {
if let parse::CountIsName(s, _) = arg.format.precision {
arg.format.precision = parse::CountIsParam(lookup(s));
}
}
Expand All @@ -276,7 +276,7 @@ impl<'a, 'b> Context<'a, 'b> {
// it's written second, so it should come after width/precision.
let pos = match arg.position {
parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => Exact(i),
parse::ArgumentNamed(s) => Named(s),
parse::ArgumentNamed(s, span) => Named(s, span),
};

let ty = Placeholder(match arg.format.ty {
Expand Down Expand Up @@ -346,8 +346,8 @@ impl<'a, 'b> Context<'a, 'b> {
parse::CountIsParam(i) => {
self.verify_arg_type(Exact(i), Count);
}
parse::CountIsName(s) => {
self.verify_arg_type(Named(s), Count);
parse::CountIsName(s, span) => {
self.verify_arg_type(Named(s, span), Count);
}
}
}
Expand Down Expand Up @@ -533,7 +533,7 @@ impl<'a, 'b> Context<'a, 'b> {
}
}

Named(name) => {
Named(name, span) => {
match self.names.get(&name) {
Some(&idx) => {
// Treat as positional arg.
Expand All @@ -548,7 +548,7 @@ impl<'a, 'b> Context<'a, 'b> {
self.arg_types.push(Vec::new());
self.arg_unique_types.push(Vec::new());
let span = if self.is_literal {
*self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp)
self.fmtsp.from_inner(span)
} else {
self.fmtsp
};
Expand All @@ -559,7 +559,7 @@ impl<'a, 'b> Context<'a, 'b> {
} else {
let msg = format!("there is no argument named `{}`", name);
let sp = if self.is_literal {
*self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp)
self.fmtsp.from_inner(span)
} else {
self.fmtsp
};
Expand Down Expand Up @@ -629,7 +629,7 @@ impl<'a, 'b> Context<'a, 'b> {
}
parse::CountImplied => count(sym::Implied, None),
// should never be the case, names are already resolved
parse::CountIsName(_) => panic!("should never happen"),
parse::CountIsName(..) => panic!("should never happen"),
}
}

Expand Down Expand Up @@ -676,7 +676,7 @@ impl<'a, 'b> Context<'a, 'b> {

// should never be the case, because names are already
// resolved.
parse::ArgumentNamed(_) => panic!("should never happen"),
parse::ArgumentNamed(..) => panic!("should never happen"),
}
};

Expand Down
16 changes: 10 additions & 6 deletions compiler/rustc_parse_format/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub enum Position {
/// The argument is located at a specific index given in the format
ArgumentIs(usize),
/// The argument has a name.
ArgumentNamed(Symbol),
ArgumentNamed(Symbol, InnerSpan),
}

impl Position {
Expand Down Expand Up @@ -147,7 +147,7 @@ pub enum Count {
/// The count is specified explicitly.
CountIs(usize),
/// The count is specified by the argument with the given name.
CountIsName(Symbol),
CountIsName(Symbol, InnerSpan),
/// The count is specified by the argument at the given index.
CountIsParam(usize),
/// The count is implied and cannot be explicitly specified.
Expand Down Expand Up @@ -494,8 +494,11 @@ impl<'a> Parser<'a> {
Some(ArgumentIs(i))
} else {
match self.cur.peek() {
Some(&(_, c)) if rustc_lexer::is_id_start(c) => {
Some(ArgumentNamed(Symbol::intern(self.word())))
Some(&(start, c)) if rustc_lexer::is_id_start(c) => {
let word = self.word();
let end = start + word.len();
let span = self.to_span_index(start).to(self.to_span_index(end));
Some(ArgumentNamed(Symbol::intern(word), span))
}

// This is an `ArgumentNext`.
Expand Down Expand Up @@ -662,8 +665,9 @@ impl<'a> Parser<'a> {
if word.is_empty() {
self.cur = tmp;
(CountImplied, None)
} else if self.consume('$') {
(CountIsName(Symbol::intern(word)), None)
} else if let Some(end) = self.consume_pos('$') {
let span = self.to_span_index(start + 1).to(self.to_span_index(end));
(CountIsName(Symbol::intern(word), span), None)
} else {
self.cur = tmp;
(CountImplied, None)
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_parse_format/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ fn format_counts() {
fill: None,
align: AlignUnknown,
flags: 0,
precision: CountIsName(Symbol::intern("b")),
width: CountIsName(Symbol::intern("a")),
precision: CountIsName(Symbol::intern("b"), InnerSpan::new(6, 7)),
width: CountIsName(Symbol::intern("a"), InnerSpan::new(4, 4)),
precision_span: None,
width_span: None,
ty: "?",
Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,23 +309,23 @@ impl<'tcx> OnUnimplementedFormatString {
Piece::String(_) => (), // Normal string, no need to check it
Piece::NextArgument(a) => match a.position {
// `{Self}` is allowed
Position::ArgumentNamed(s) if s == kw::SelfUpper => (),
Position::ArgumentNamed(s, _) if s == kw::SelfUpper => (),
// `{ThisTraitsName}` is allowed
Position::ArgumentNamed(s) if s == name => (),
Position::ArgumentNamed(s, _) if s == name => (),
// `{from_method}` is allowed
Position::ArgumentNamed(s) if s == sym::from_method => (),
Position::ArgumentNamed(s, _) if s == sym::from_method => (),
// `{from_desugaring}` is allowed
Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
Position::ArgumentNamed(s, _) if s == sym::from_desugaring => (),
// `{ItemContext}` is allowed
Position::ArgumentNamed(s) if s == sym::ItemContext => (),
Position::ArgumentNamed(s, _) if s == sym::ItemContext => (),
// `{integral}` and `{integer}` and `{float}` are allowed
Position::ArgumentNamed(s)
Position::ArgumentNamed(s, _)
if s == sym::integral || s == sym::integer_ || s == sym::float =>
{
()
}
// So is `{A}` if A is a type parameter
Position::ArgumentNamed(s) => {
Position::ArgumentNamed(s, _) => {
match generics.params.iter().find(|param| param.name == s) {
Some(_) => (),
None => {
Expand Down Expand Up @@ -392,7 +392,7 @@ impl<'tcx> OnUnimplementedFormatString {
.map(|p| match p {
Piece::String(s) => s,
Piece::NextArgument(a) => match a.position {
Position::ArgumentNamed(s) => match generic_map.get(&s) {
Position::ArgumentNamed(s, _) => match generic_map.get(&s) {
Some(val) => val,
None if s == name => &trait_str,
None => {
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,15 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
tcx.sess,
field_span,
E0740,
"unions may not contain fields that need dropping"
"unions cannot contain fields that may need dropping"
)
.note(
"a type is guaranteed not to need dropping \
when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type",
)
.multipart_suggestion_verbose(
"wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped",
"when the type does not implement `Copy`, \
wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped",
vec![
(ty_span.shrink_to_lo(), format!("std::mem::ManuallyDrop<")),
(ty_span.shrink_to_hi(), ">".into()),
Expand Down
54 changes: 41 additions & 13 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, Node, QPath};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::traits::util::supertraits;
use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams};
use rustc_middle::ty::print::with_crate_prefix;
use rustc_middle::ty::ToPolyTraitRef;
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_span::lev_distance;
use rustc_span::symbol::{kw, sym, Ident};
Expand Down Expand Up @@ -40,7 +42,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Err(..) => return false,
};

// This conditional prevents us from asking to call errors and unresolved types.
// It might seem that we can use `predicate_must_hold_modulo_regions`,
// but since a Dummy binder is used to fill in the FnOnce trait's arguments,
// type resolution always gives a "maybe" here.
if self.autoderef(span, ty).any(|(ty, _)| {
info!("check deref {:?} error", ty);
matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
}) {
return false;
}

self.autoderef(span, ty).any(|(ty, _)| {
info!("check deref {:?} impl FnOnce", ty);
self.probe(|_| {
let fn_once_substs = tcx.mk_substs_trait(
ty,
Expand Down Expand Up @@ -1196,26 +1210,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(adt) if adt.did.is_local() => adt,
_ => continue,
};
let can_derive = match self.tcx.get_diagnostic_name(trait_pred.def_id()) {
Some(sym::Default) => !adt.is_enum(),
Some(
if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
let can_derive = match diagnostic_name {
sym::Default => !adt.is_enum(),
sym::Eq
| sym::PartialEq
| sym::Ord
| sym::PartialOrd
| sym::Clone
| sym::Copy
| sym::Hash
| sym::Debug,
) => true,
_ => false,
};
if can_derive {
derives.push((
format!("{}", trait_pred.self_ty()),
self.tcx.def_span(adt.did),
format!("{}", trait_pred.trait_ref.print_only_trait_name()),
));
| sym::Debug => true,
_ => false,
};
if can_derive {
let self_name = trait_pred.self_ty().to_string();
let self_span = self.tcx.def_span(adt.did);
if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() {
for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref())
{
if let Some(parent_diagnostic_name) =
self.tcx.get_diagnostic_name(super_trait.def_id())
{
derives.push((
self_name.clone(),
self_span.clone(),
parent_diagnostic_name.to_string(),
));
}
}
}
derives.push((self_name, self_span, diagnostic_name.to_string()));
} else {
traits.push(self.tcx.def_span(trait_pred.def_id()));
}
} else {
traits.push(self.tcx.def_span(trait_pred.def_id()));
}
Expand Down
56 changes: 32 additions & 24 deletions compiler/rustc_typeck/src/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2029,34 +2029,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("the semantics of slice patterns changed recently; see issue #62254");
}
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..)))
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
{
if let (Some(span), true) = (ti.span, ti.origin_expr) {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
let applicability = match self.resolve_vars_if_possible(ti.expected).kind() {
ty::Adt(adt_def, _)
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
{
// Slicing won't work here, but `.as_deref()` might (issue #91328).
err.span_suggestion(
span,
"consider using `as_deref` here",
format!("{}.as_deref()", snippet),
Applicability::MaybeIncorrect,
);
None
}
// FIXME: instead of checking for Vec only, we could check whether the
// type implements `Deref<Target=X>`; see
// https://github.com/rust-lang/rust/pull/91343#discussion_r761466979
ty::Adt(adt_def, _)
if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) =>
{
Some(Applicability::MachineApplicable)
let applicability = Autoderef::new(
&self.infcx,
self.param_env,
self.body_id,
span,
self.resolve_vars_if_possible(ti.expected),
span,
)
.find_map(|(ty, _)| {
match ty.kind() {
ty::Adt(adt_def, _)
if self.tcx.is_diagnostic_item(sym::Option, adt_def.did)
|| self.tcx.is_diagnostic_item(sym::Result, adt_def.did) =>
{
// Slicing won't work here, but `.as_deref()` might (issue #91328).
err.span_suggestion(
span,
"consider using `as_deref` here",
format!("{}.as_deref()", snippet),
Applicability::MaybeIncorrect,
);
Some(None)
}

ty::Slice(..) | ty::Array(..) => {
Some(Some(Applicability::MachineApplicable))
}

_ => None,
}
_ => Some(Applicability::MaybeIncorrect),
};
})
.unwrap_or(Some(Applicability::MaybeIncorrect));

if let Some(applicability) = applicability {
err.span_suggestion(
Expand Down
2 changes: 2 additions & 0 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2052,6 +2052,8 @@ where

#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<K: Ord, V, const N: usize> From<[(K, V); N]> for BTreeMap<K, V> {
/// Converts a `[(K, V); N]` into a `BTreeMap<(K, V)>`.
///
/// ```
/// use std::collections::BTreeMap;
///
Expand Down
2 changes: 2 additions & 0 deletions library/alloc/src/collections/btree/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,8 @@ impl<T: Ord> FromIterator<T> for BTreeSet<T> {

#[stable(feature = "std_collections_from_array", since = "1.56.0")]
impl<T: Ord, const N: usize> From<[T; N]> for BTreeSet<T> {
/// Converts a `[T; N]` into a `BTreeSet<T>`.
///
/// ```
/// use std::collections::BTreeSet;
///
Expand Down
Loading

0 comments on commit 582b696

Please sign in to comment.