Skip to content

Commit 7bdda8f

Browse files
committed
Auto merge of #105686 - matthiaskrgr:rollup-bedfk3j, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #103644 (Add docs for question mark operator for Option) - #105161 (Refine when invalid prefix case error arises) - #105491 (Illegal sized bounds: only suggest mutability change if needed) - #105502 (Suggest impl in the scenario of typo with fn) - #105523 (Suggest `collect`ing into `Vec<_>`) - #105595 (Suggest dereferencing receiver arguments properly) - #105611 (fold instead of obliterating args) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents dc30b92 + 0146969 commit 7bdda8f

File tree

54 files changed

+637
-189
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+637
-189
lines changed

compiler/rustc_error_messages/locales/en-US/parse.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,6 @@ parse_fn_ptr_with_generics = function pointer types may not have generic paramet
362362
363363
parse_invalid_identifier_with_leading_number = expected identifier, found number literal
364364
.label = identifiers cannot start with a number
365+
366+
parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
367+
.suggestion = replace `fn` with `impl` here

compiler/rustc_hir_typeck/src/method/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
209209
ProbeScope::TraitsInScope,
210210
) {
211211
Ok(ref new_pick) if pick.differs_from(new_pick) => {
212-
needs_mut = true;
212+
needs_mut = new_pick.self_ty.ref_mutability() != self_ty.ref_mutability();
213213
}
214214
_ => {}
215215
}

compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+66-38
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
2020
use rustc_middle::ty::{self, DefIdTree, InferConst};
2121
use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
2222
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
23-
use rustc_span::symbol::{kw, Ident};
23+
use rustc_span::symbol::{kw, sym, Ident};
2424
use rustc_span::{BytePos, Span};
2525
use std::borrow::Cow;
2626
use std::iter;
@@ -79,7 +79,7 @@ impl InferenceDiagnosticsData {
7979

8080
fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
8181
if in_type.is_ty_infer() {
82-
"empty"
82+
""
8383
} else if self.name == "_" {
8484
// FIXME: Consider specializing this message if there is a single `_`
8585
// in the type.
@@ -183,13 +183,24 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
183183
printer
184184
}
185185

186-
fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
186+
fn ty_to_string<'tcx>(
187+
infcx: &InferCtxt<'tcx>,
188+
ty: Ty<'tcx>,
189+
called_method_def_id: Option<DefId>,
190+
) -> String {
187191
let printer = fmt_printer(infcx, Namespace::TypeNS);
188192
let ty = infcx.resolve_vars_if_possible(ty);
189-
match ty.kind() {
193+
match (ty.kind(), called_method_def_id) {
190194
// We don't want the regular output for `fn`s because it includes its path in
191195
// invalid pseudo-syntax, we want the `fn`-pointer output instead.
192-
ty::FnDef(..) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
196+
(ty::FnDef(..), _) => ty.fn_sig(infcx.tcx).print(printer).unwrap().into_buffer(),
197+
(_, Some(def_id))
198+
if ty.is_ty_infer()
199+
&& infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
200+
{
201+
"Vec<_>".to_string()
202+
}
203+
_ if ty.is_ty_infer() => "/* Type */".to_string(),
193204
// FIXME: The same thing for closures, but this only works when the closure
194205
// does not capture anything.
195206
//
@@ -213,15 +224,15 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
213224
.map(|args| {
214225
args.tuple_fields()
215226
.iter()
216-
.map(|arg| ty_to_string(infcx, arg))
227+
.map(|arg| ty_to_string(infcx, arg, None))
217228
.collect::<Vec<_>>()
218229
.join(", ")
219230
})
220231
.unwrap_or_default();
221232
let ret = if fn_sig.output().skip_binder().is_unit() {
222233
String::new()
223234
} else {
224-
format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder()))
235+
format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
225236
};
226237
format!("fn({}){}", args, ret)
227238
}
@@ -368,6 +379,7 @@ impl<'tcx> InferCtxt<'tcx> {
368379
}
369380

370381
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
382+
#[instrument(level = "debug", skip(self, error_code))]
371383
pub fn emit_inference_failure_err(
372384
&self,
373385
body_id: Option<hir::BodyId>,
@@ -406,7 +418,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
406418
let mut infer_subdiags = Vec::new();
407419
let mut multi_suggestions = Vec::new();
408420
match kind {
409-
InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
421+
InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
410422
infer_subdiags.push(SourceKindSubdiag::LetLike {
411423
span: insert_span,
412424
name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
@@ -415,7 +427,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
415427
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
416428
arg_name: arg_data.name,
417429
kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
418-
type_name: ty_to_string(self, ty),
430+
type_name: ty_to_string(self, ty, def_id),
419431
});
420432
}
421433
InferSourceKind::ClosureArg { insert_span, ty } => {
@@ -427,7 +439,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
427439
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
428440
arg_name: arg_data.name,
429441
kind: "closure",
430-
type_name: ty_to_string(self, ty),
442+
type_name: ty_to_string(self, ty, None),
431443
});
432444
}
433445
InferSourceKind::GenericArg {
@@ -456,33 +468,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
456468
parent_name,
457469
});
458470

459-
let args = fmt_printer(self, Namespace::TypeNS)
460-
.comma_sep(generic_args.iter().copied().map(|arg| {
461-
if arg.is_suggestable(self.tcx, true) {
462-
return arg;
463-
}
471+
let args = if self.infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn)
472+
== Some(generics_def_id)
473+
{
474+
"Vec<_>".to_string()
475+
} else {
476+
fmt_printer(self, Namespace::TypeNS)
477+
.comma_sep(generic_args.iter().copied().map(|arg| {
478+
if arg.is_suggestable(self.tcx, true) {
479+
return arg;
480+
}
464481

465-
match arg.unpack() {
466-
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
467-
GenericArgKind::Type(_) => self
468-
.next_ty_var(TypeVariableOrigin {
469-
span: rustc_span::DUMMY_SP,
470-
kind: TypeVariableOriginKind::MiscVariable,
471-
})
472-
.into(),
473-
GenericArgKind::Const(arg) => self
474-
.next_const_var(
475-
arg.ty(),
476-
ConstVariableOrigin {
482+
match arg.unpack() {
483+
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
484+
GenericArgKind::Type(_) => self
485+
.next_ty_var(TypeVariableOrigin {
477486
span: rustc_span::DUMMY_SP,
478-
kind: ConstVariableOriginKind::MiscVariable,
479-
},
480-
)
481-
.into(),
482-
}
483-
}))
484-
.unwrap()
485-
.into_buffer();
487+
kind: TypeVariableOriginKind::MiscVariable,
488+
})
489+
.into(),
490+
GenericArgKind::Const(arg) => self
491+
.next_const_var(
492+
arg.ty(),
493+
ConstVariableOrigin {
494+
span: rustc_span::DUMMY_SP,
495+
kind: ConstVariableOriginKind::MiscVariable,
496+
},
497+
)
498+
.into(),
499+
}
500+
}))
501+
.unwrap()
502+
.into_buffer()
503+
};
486504

487505
if !have_turbofish {
488506
infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
@@ -520,7 +538,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
520538
));
521539
}
522540
InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
523-
let ty_info = ty_to_string(self, ty);
541+
let ty_info = ty_to_string(self, ty, None);
524542
multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
525543
ty_info,
526544
data,
@@ -608,6 +626,7 @@ enum InferSourceKind<'tcx> {
608626
insert_span: Span,
609627
pattern_name: Option<Ident>,
610628
ty: Ty<'tcx>,
629+
def_id: Option<DefId>,
611630
},
612631
ClosureArg {
613632
insert_span: Span,
@@ -662,7 +681,7 @@ impl<'tcx> InferSourceKind<'tcx> {
662681
if ty.is_closure() {
663682
("closure", closure_as_fn_str(infcx, ty))
664683
} else if !ty.is_ty_infer() {
665-
("normal", ty_to_string(infcx, ty))
684+
("normal", ty_to_string(infcx, ty, None))
666685
} else {
667686
("other", String::new())
668687
}
@@ -788,10 +807,18 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
788807
/// Uses `fn source_cost` to determine whether this inference source is preferable to
789808
/// previous sources. We generally prefer earlier sources.
790809
#[instrument(level = "debug", skip(self))]
791-
fn update_infer_source(&mut self, new_source: InferSource<'tcx>) {
810+
fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
792811
let cost = self.source_cost(&new_source) + self.attempt;
793812
debug!(?cost);
794813
self.attempt += 1;
814+
if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, ..}, .. }) = self.infer_source
815+
&& let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..} = new_source.kind
816+
&& ty.is_ty_infer()
817+
{
818+
// Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
819+
// `let x: _ = iter.collect();`, as this is a very common case.
820+
*def_id = Some(did);
821+
}
795822
if cost < self.infer_source_cost {
796823
self.infer_source_cost = cost;
797824
self.infer_source = Some(new_source);
@@ -1092,6 +1119,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
10921119
insert_span: local.pat.span.shrink_to_hi(),
10931120
pattern_name: local.pat.simple_ident(),
10941121
ty,
1122+
def_id: None,
10951123
},
10961124
})
10971125
}

compiler/rustc_infer/src/infer/mod.rs

+38-15
Original file line numberDiff line numberDiff line change
@@ -2014,31 +2014,54 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
20142014
tcx: TyCtxt<'tcx>,
20152015
substs: SubstsRef<'tcx>,
20162016
) -> SubstsRef<'tcx> {
2017-
tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
2018-
match arg.unpack() {
2019-
GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
2020-
tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
2017+
struct ReplaceParamAndInferWithPlaceholder<'tcx> {
2018+
tcx: TyCtxt<'tcx>,
2019+
idx: usize,
2020+
}
2021+
2022+
impl<'tcx> TypeFolder<'tcx> for ReplaceParamAndInferWithPlaceholder<'tcx> {
2023+
fn tcx(&self) -> TyCtxt<'tcx> {
2024+
self.tcx
2025+
}
2026+
2027+
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
2028+
if let ty::Infer(_) = t.kind() {
2029+
self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
20212030
universe: ty::UniverseIndex::ROOT,
2022-
name: ty::BoundVar::from_usize(idx),
2031+
name: ty::BoundVar::from_usize({
2032+
let idx = self.idx;
2033+
self.idx += 1;
2034+
idx
2035+
}),
20232036
}))
2024-
.into()
2037+
} else {
2038+
t.super_fold_with(self)
20252039
}
2026-
GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
2027-
let ty = ct.ty();
2028-
// If the type references param or infer, replace that too...
2040+
}
2041+
2042+
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
2043+
if let ty::ConstKind::Infer(_) = c.kind() {
2044+
let ty = c.ty();
2045+
// If the type references param or infer then ICE ICE ICE
20292046
if ty.has_non_region_param() || ty.has_non_region_infer() {
2030-
bug!("const `{ct}`'s type should not reference params or types");
2047+
bug!("const `{c}`'s type should not reference params or types");
20312048
}
2032-
tcx.mk_const(
2049+
self.tcx.mk_const(
20332050
ty::PlaceholderConst {
20342051
universe: ty::UniverseIndex::ROOT,
2035-
name: ty::BoundVar::from_usize(idx),
2052+
name: ty::BoundVar::from_usize({
2053+
let idx = self.idx;
2054+
self.idx += 1;
2055+
idx
2056+
}),
20362057
},
20372058
ty,
20382059
)
2039-
.into()
2060+
} else {
2061+
c.super_fold_with(self)
20402062
}
2041-
_ => arg,
20422063
}
2043-
}))
2064+
}
2065+
2066+
substs.fold_with(&mut ReplaceParamAndInferWithPlaceholder { tcx, idx: 0 })
20442067
}

compiler/rustc_parse/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1221,3 +1221,11 @@ pub(crate) struct UnexpectedIfWithIf(
12211221
#[suggestion(applicability = "machine-applicable", code = " ", style = "verbose")]
12221222
pub Span,
12231223
);
1224+
1225+
#[derive(Diagnostic)]
1226+
#[diag(parse_maybe_fn_typo_with_impl)]
1227+
pub(crate) struct FnTypoWithImpl {
1228+
#[primary_span]
1229+
#[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
1230+
pub fn_span: Span,
1231+
}

compiler/rustc_parse/src/parser/item.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
33
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
44
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
55
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
6+
use crate::errors::FnTypoWithImpl;
67
use rustc_ast::ast::*;
78
use rustc_ast::ptr::P;
89
use rustc_ast::token::{self, Delimiter, TokenKind};
@@ -2131,11 +2132,26 @@ impl<'a> Parser<'a> {
21312132
vis: &Visibility,
21322133
case: Case,
21332134
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
2135+
let fn_span = self.token.span;
21342136
let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
21352137
let ident = self.parse_ident()?; // `foo`
21362138
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
2137-
let decl =
2138-
self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
2139+
let decl = match self.parse_fn_decl(
2140+
fn_parse_mode.req_name,
2141+
AllowPlus::Yes,
2142+
RecoverReturnSign::Yes,
2143+
) {
2144+
Ok(decl) => decl,
2145+
Err(old_err) => {
2146+
// If we see `for Ty ...` then user probably meant `impl` item.
2147+
if self.token.is_keyword(kw::For) {
2148+
old_err.cancel();
2149+
return Err(self.sess.create_err(FnTypoWithImpl { fn_span }));
2150+
} else {
2151+
return Err(old_err);
2152+
}
2153+
}
2154+
};
21392155
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
21402156

21412157
let mut sig_hi = self.prev_token.span;

0 commit comments

Comments
 (0)