Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 270c94e

Browse files
committedDec 28, 2022
Auto merge of rust-lang#106215 - matthiaskrgr:rollup-53r89ww, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - rust-lang#106028 (docs/test: add UI test and long-form error docs for `E0461`) - rust-lang#106172 (Suggest `impl Iterator` when possible for `_` return type) - rust-lang#106173 (Deduplicate `op` methods) - rust-lang#106176 (Recover `fn` keyword as `Fn` trait in bounds) - rust-lang#106194 (rustdoc: combine common sidebar background color CSS rules) - rust-lang#106199 (Silence knock-down errors on `[type error]` bindings) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 83a28ef + d37cb3f commit 270c94e

File tree

36 files changed

+500
-395
lines changed

36 files changed

+500
-395
lines changed
 

‎compiler/rustc_error_codes/src/error_codes.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ E0457: include_str!("./error_codes/E0457.md"),
244244
E0458: include_str!("./error_codes/E0458.md"),
245245
E0459: include_str!("./error_codes/E0459.md"),
246246
E0460: include_str!("./error_codes/E0460.md"),
247+
E0461: include_str!("./error_codes/E0461.md"),
247248
E0462: include_str!("./error_codes/E0462.md"),
248249
E0463: include_str!("./error_codes/E0463.md"),
249250
E0464: include_str!("./error_codes/E0464.md"),
@@ -595,7 +596,6 @@ E0791: include_str!("./error_codes/E0791.md"),
595596
// E0421, // merged into 531
596597
// E0427, // merged into 530
597598
// E0456, // plugin `..` is not available for triple `..`
598-
E0461, // couldn't find crate `..` with expected target triple ..
599599
E0465, // multiple .. candidates for `..` found
600600
// E0467, // removed
601601
// E0470, // removed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Couldn't find crate `..` with expected target triple `..`.
2+
3+
Example of erroneous code:
4+
5+
`a.rs`
6+
```ignore (cannot-link-with-other-tests)
7+
#![crate_type = "lib"]
8+
9+
fn foo() {}
10+
```
11+
12+
`main.rs`
13+
```ignore (cannot-link-with-other-tests)
14+
extern crate a;
15+
16+
fn main() {
17+
a::foo();
18+
}
19+
```
20+
21+
`a.rs` is then compiled with `--target powerpc-unknown-linux-gnu` and `b.rs`
22+
with `--target x86_64-unknown-linux-gnu`. `a.rs` is compiled into a binary
23+
format incompatible with `b.rs`; PowerPC and x86 are totally different
24+
architectures. This issue also extends to any difference in target triples, as
25+
`std` is operating-system specific.
26+
27+
This error can be fixed by:
28+
* Using [Cargo](../cargo/index.html), the Rust package manager, automatically
29+
fixing this issue.
30+
* Recompiling either crate so that they target a consistent target triple.

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,6 @@ parse_invalid_identifier_with_leading_number = expected identifier, found number
365365
366366
parse_maybe_fn_typo_with_impl = you might have meant to write `impl` instead of `fn`
367367
.suggestion = replace `fn` with `impl` here
368+
369+
parse_expected_fn_path_found_fn_keyword = expected identifier, found keyword `fn`
370+
.suggestion = use `Fn` to refer to the trait

‎compiler/rustc_expand/src/build.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ impl<'a> ExtCtxt<'a> {
626626

627627
// Builds `#[name = val]`.
628628
//
629-
// Note: `span` is used for both the identifer and the value.
629+
// Note: `span` is used for both the identifier and the value.
630630
pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
631631
let g = &self.sess.parse_sess.attr_id_generator;
632632
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)

‎compiler/rustc_hir_analysis/src/collect.rs‎

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,18 @@ use rustc_hir as hir;
2424
use rustc_hir::def_id::{DefId, LocalDefId};
2525
use rustc_hir::intravisit::{self, Visitor};
2626
use rustc_hir::{GenericParamKind, Node};
27+
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
28+
use rustc_infer::infer::TyCtxtInferExt;
2729
use rustc_middle::hir::nested_filter;
2830
use rustc_middle::ty::query::Providers;
2931
use rustc_middle::ty::util::{Discr, IntTypeExt};
3032
use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
3133
use rustc_span::symbol::{kw, sym, Ident, Symbol};
3234
use rustc_span::Span;
3335
use rustc_target::spec::abi;
36+
use rustc_trait_selection::infer::InferCtxtExt;
3437
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
38+
use rustc_trait_selection::traits::ObligationCtxt;
3539
use std::iter;
3640

3741
mod generics_of;
@@ -1224,7 +1228,17 @@ fn infer_return_ty_for_fn_sig<'tcx>(
12241228
// to prevent the user from getting a papercut while trying to use the unique closure
12251229
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
12261230
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1227-
diag.note("for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html");
1231+
diag.note(
1232+
"for more information on `Fn` traits and closure types, see \
1233+
https://doc.rust-lang.org/book/ch13-01-closures.html",
1234+
);
1235+
} else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) {
1236+
diag.span_suggestion(
1237+
ty.span,
1238+
"replace with an appropriate return type",
1239+
format!("impl Iterator<Item = {}>", i_ty),
1240+
Applicability::MachineApplicable,
1241+
);
12281242
}
12291243
diag.emit();
12301244

@@ -1242,6 +1256,51 @@ fn infer_return_ty_for_fn_sig<'tcx>(
12421256
}
12431257
}
12441258

1259+
fn suggest_impl_iterator<'tcx>(
1260+
tcx: TyCtxt<'tcx>,
1261+
ret_ty: Ty<'tcx>,
1262+
span: Span,
1263+
hir_id: hir::HirId,
1264+
def_id: LocalDefId,
1265+
) -> Option<Ty<'tcx>> {
1266+
let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; };
1267+
let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; };
1268+
if !tcx
1269+
.infer_ctxt()
1270+
.build()
1271+
.type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id))
1272+
.must_apply_modulo_regions()
1273+
{
1274+
return None;
1275+
}
1276+
let infcx = tcx.infer_ctxt().build();
1277+
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
1278+
// Find the type of `Iterator::Item`.
1279+
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
1280+
let ty_var = infcx.next_ty_var(origin);
1281+
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
1282+
ty::ProjectionPredicate {
1283+
projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())),
1284+
term: ty_var.into(),
1285+
},
1286+
)));
1287+
// Add `<ret_ty as Iterator>::Item = _` obligation.
1288+
ocx.register_obligation(crate::traits::Obligation::misc(
1289+
tcx,
1290+
span,
1291+
hir_id,
1292+
tcx.param_env(def_id),
1293+
projection,
1294+
));
1295+
if ocx.select_where_possible().is_empty()
1296+
&& let item_ty = infcx.resolve_vars_if_possible(ty_var)
1297+
&& item_ty.is_suggestable(tcx, false)
1298+
{
1299+
return Some(item_ty);
1300+
}
1301+
None
1302+
}
1303+
12451304
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
12461305
let icx = ItemCtxt::new(tcx, def_id);
12471306
let item = tcx.hir().expect_item(def_id.expect_local());

‎compiler/rustc_hir_analysis/src/collect/type_of.rs‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_hir::intravisit;
55
use rustc_hir::intravisit::Visitor;
66
use rustc_hir::{HirId, Node};
77
use rustc_middle::hir::nested_filter;
8+
use rustc_middle::ty::print::with_forced_trimmed_paths;
89
use rustc_middle::ty::subst::InternalSubsts;
910
use rustc_middle::ty::util::IntTypeExt;
1011
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
@@ -907,10 +908,10 @@ fn infer_placeholder_type<'a>(
907908
Applicability::MachineApplicable,
908909
);
909910
} else {
910-
err.span_note(
911+
with_forced_trimmed_paths!(err.span_note(
911912
tcx.hir().body(body_id).value.span,
912-
&format!("however, the inferred type `{}` cannot be named", ty),
913-
);
913+
&format!("however, the inferred type `{ty}` cannot be named"),
914+
));
914915
}
915916
}
916917

@@ -931,10 +932,10 @@ fn infer_placeholder_type<'a>(
931932
Applicability::MaybeIncorrect,
932933
);
933934
} else {
934-
diag.span_note(
935+
with_forced_trimmed_paths!(diag.span_note(
935936
tcx.hir().body(body_id).value.span,
936-
&format!("however, the inferred type `{}` cannot be named", ty),
937-
);
937+
&format!("however, the inferred type `{ty}` cannot be named"),
938+
));
938939
}
939940
}
940941

‎compiler/rustc_hir_typeck/src/callee.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
241241
});
242242

243243
if let Some(ok) = self.lookup_method_in_trait(
244-
call_expr.span,
244+
self.misc(call_expr.span),
245245
method_name,
246246
trait_def_id,
247247
adjusted_ty,

‎compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13071307
// Type check the initializer.
13081308
if let Some(ref init) = decl.init {
13091309
let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
1310-
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty);
1310+
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
13111311
}
13121312

13131313
// Does the expected pattern type originate from an expression and what is the span?
@@ -1322,7 +1322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13221322
// Type check the pattern. Override if necessary to avoid knock-on errors.
13231323
self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
13241324
let pat_ty = self.node_ty(decl.pat.hir_id);
1325-
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty);
1325+
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
13261326

13271327
if let Some(blk) = decl.els {
13281328
let previous_diverges = self.diverges.get();
@@ -1627,14 +1627,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16271627
&self,
16281628
hir_id: hir::HirId,
16291629
pat: &'tcx hir::Pat<'tcx>,
1630-
decl_ty: Ty<'tcx>,
16311630
ty: Ty<'tcx>,
16321631
) {
16331632
if ty.references_error() {
16341633
// Override the types everywhere with `err()` to avoid knock on errors.
1635-
self.write_ty(hir_id, ty);
1636-
self.write_ty(pat.hir_id, ty);
1637-
let local_ty = LocalTy { decl_ty, revealed_ty: ty };
1634+
let err = self.tcx.ty_error();
1635+
self.write_ty(hir_id, err);
1636+
self.write_ty(pat.hir_id, err);
1637+
let local_ty = LocalTy { decl_ty: err, revealed_ty: err };
16381638
self.locals.borrow_mut().insert(hir_id, local_ty);
16391639
self.locals.borrow_mut().insert(pat.hir_id, local_ty);
16401640
}

‎compiler/rustc_hir_typeck/src/method/mod.rs‎

Lines changed: 18 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub use self::suggest::SelfSource;
1111
pub use self::MethodError::*;
1212

1313
use crate::errors::OpMethodGenericParams;
14-
use crate::{Expectation, FnCtxt};
14+
use crate::FnCtxt;
1515
use rustc_data_structures::sync::Lrc;
1616
use rustc_errors::{Applicability, Diagnostic};
1717
use rustc_hir as hir;
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
264264

265265
pub(super) fn obligation_for_method(
266266
&self,
267-
span: Span,
267+
cause: ObligationCause<'tcx>,
268268
trait_def_id: DefId,
269269
self_ty: Ty<'tcx>,
270270
opt_input_types: Option<&[Ty<'tcx>]>,
@@ -282,71 +282,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
282282
}
283283
}
284284
}
285-
self.var_for_def(span, param)
286-
});
287-
288-
let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
289-
290-
// Construct an obligation
291-
let poly_trait_ref = ty::Binder::dummy(trait_ref);
292-
(
293-
traits::Obligation::misc(
294-
self.tcx,
295-
span,
296-
self.body_id,
297-
self.param_env,
298-
poly_trait_ref.without_const(),
299-
),
300-
substs,
301-
)
302-
}
303-
304-
pub(super) fn obligation_for_op_method(
305-
&self,
306-
span: Span,
307-
trait_def_id: DefId,
308-
self_ty: Ty<'tcx>,
309-
opt_input_type: Option<Ty<'tcx>>,
310-
opt_input_expr: Option<&'tcx hir::Expr<'tcx>>,
311-
expected: Expectation<'tcx>,
312-
) -> (traits::Obligation<'tcx, ty::Predicate<'tcx>>, &'tcx ty::List<ty::subst::GenericArg<'tcx>>)
313-
{
314-
// Construct a trait-reference `self_ty : Trait<input_tys>`
315-
let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| {
316-
match param.kind {
317-
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {}
318-
GenericParamDefKind::Type { .. } => {
319-
if param.index == 0 {
320-
return self_ty.into();
321-
} else if let Some(input_type) = opt_input_type {
322-
return input_type.into();
323-
}
324-
}
325-
}
326-
self.var_for_def(span, param)
285+
self.var_for_def(cause.span, param)
327286
});
328287

329288
let trait_ref = self.tcx.mk_trait_ref(trait_def_id, substs);
330289

331290
// Construct an obligation
332291
let poly_trait_ref = ty::Binder::dummy(trait_ref);
333-
let output_ty = expected.only_has_type(self).and_then(|ty| (!ty.needs_infer()).then(|| ty));
334-
335292
(
336293
traits::Obligation::new(
337294
self.tcx,
338-
traits::ObligationCause::new(
339-
span,
340-
self.body_id,
341-
traits::BinOp {
342-
rhs_span: opt_input_expr.map(|expr| expr.span),
343-
is_lit: opt_input_expr
344-
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
345-
output_ty,
346-
},
347-
),
295+
cause,
348296
self.param_env,
349-
poly_trait_ref,
297+
poly_trait_ref.without_const(),
350298
),
351299
substs,
352300
)
@@ -357,69 +305,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
357305
/// In particular, it doesn't really do any probing: it simply constructs
358306
/// an obligation for a particular trait with the given self type and checks
359307
/// whether that trait is implemented.
360-
#[instrument(level = "debug", skip(self, span))]
308+
#[instrument(level = "debug", skip(self))]
361309
pub(super) fn lookup_method_in_trait(
362310
&self,
363-
span: Span,
311+
cause: ObligationCause<'tcx>,
364312
m_name: Ident,
365313
trait_def_id: DefId,
366314
self_ty: Ty<'tcx>,
367315
opt_input_types: Option<&[Ty<'tcx>]>,
368316
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
369317
let (obligation, substs) =
370-
self.obligation_for_method(span, trait_def_id, self_ty, opt_input_types);
371-
self.construct_obligation_for_trait(
372-
span,
373-
m_name,
374-
trait_def_id,
375-
obligation,
376-
substs,
377-
None,
378-
false,
379-
)
380-
}
381-
382-
pub(super) fn lookup_op_method_in_trait(
383-
&self,
384-
span: Span,
385-
m_name: Ident,
386-
trait_def_id: DefId,
387-
self_ty: Ty<'tcx>,
388-
opt_input_type: Option<Ty<'tcx>>,
389-
opt_input_expr: Option<&'tcx hir::Expr<'tcx>>,
390-
expected: Expectation<'tcx>,
391-
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
392-
let (obligation, substs) = self.obligation_for_op_method(
393-
span,
394-
trait_def_id,
395-
self_ty,
396-
opt_input_type,
397-
opt_input_expr,
398-
expected,
399-
);
400-
self.construct_obligation_for_trait(
401-
span,
402-
m_name,
403-
trait_def_id,
404-
obligation,
405-
substs,
406-
opt_input_expr,
407-
true,
408-
)
318+
self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
319+
self.construct_obligation_for_trait(m_name, trait_def_id, obligation, substs)
409320
}
410321

411322
// FIXME(#18741): it seems likely that we can consolidate some of this
412323
// code with the other method-lookup code. In particular, the second half
413324
// of this method is basically the same as confirmation.
414325
fn construct_obligation_for_trait(
415326
&self,
416-
span: Span,
417327
m_name: Ident,
418328
trait_def_id: DefId,
419329
obligation: traits::PredicateObligation<'tcx>,
420330
substs: &'tcx ty::List<ty::subst::GenericArg<'tcx>>,
421-
opt_input_expr: Option<&'tcx hir::Expr<'tcx>>,
422-
is_op: bool,
423331
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
424332
debug!(?obligation);
425333

@@ -435,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
435343
let tcx = self.tcx;
436344
let Some(method_item) = self.associated_value(trait_def_id, m_name) else {
437345
tcx.sess.delay_span_bug(
438-
span,
346+
obligation.cause.span,
439347
"operator trait does not have corresponding operator method",
440348
);
441349
return None;
@@ -461,24 +369,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
461369
// with bound regions.
462370
let fn_sig = tcx.bound_fn_sig(def_id);
463371
let fn_sig = fn_sig.subst(self.tcx, substs);
464-
let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig);
465-
466-
let cause = if is_op {
467-
ObligationCause::new(
468-
span,
469-
self.body_id,
470-
traits::BinOp {
471-
rhs_span: opt_input_expr.map(|expr| expr.span),
472-
is_lit: opt_input_expr
473-
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
474-
output_ty: None,
475-
},
476-
)
477-
} else {
478-
traits::ObligationCause::misc(span, self.body_id)
479-
};
372+
let fn_sig =
373+
self.replace_bound_vars_with_fresh_vars(obligation.cause.span, infer::FnCall, fn_sig);
480374

481-
let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(fn_sig);
375+
let InferOk { value, obligations: o } =
376+
self.at(&obligation.cause, self.param_env).normalize(fn_sig);
482377
let fn_sig = {
483378
obligations.extend(o);
484379
value
@@ -494,15 +389,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
494389
// any late-bound regions appearing in its bounds.
495390
let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs);
496391

497-
let InferOk { value, obligations: o } = self.at(&cause, self.param_env).normalize(bounds);
392+
let InferOk { value, obligations: o } =
393+
self.at(&obligation.cause, self.param_env).normalize(bounds);
498394
let bounds = {
499395
obligations.extend(o);
500396
value
501397
};
502398

503399
assert!(!bounds.has_escaping_bound_vars());
504400

505-
let predicates_cause = cause.clone();
401+
let predicates_cause = obligation.cause.clone();
506402
obligations.extend(traits::predicates_for_generics(
507403
move |_, _| predicates_cause.clone(),
508404
self.param_env,
@@ -517,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
517413
);
518414
obligations.push(traits::Obligation::new(
519415
tcx,
520-
cause,
416+
obligation.cause,
521417
self.param_env,
522418
ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())),
523419
));

‎compiler/rustc_hir_typeck/src/op.rs‎

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ use rustc_middle::ty::adjustment::{
1212
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
1313
};
1414
use rustc_middle::ty::print::with_no_trimmed_paths;
15-
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
15+
use rustc_middle::ty::{
16+
self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable,
17+
};
1618
use rustc_session::errors::ExprParenthesesNeeded;
1719
use rustc_span::source_map::Spanned;
1820
use rustc_span::symbol::{sym, Ident};
1921
use rustc_span::Span;
2022
use rustc_trait_selection::infer::InferCtxtExt;
2123
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
22-
use rustc_trait_selection::traits::FulfillmentError;
24+
use rustc_trait_selection::traits::{self, FulfillmentError};
2325
use rustc_type_ir::sty::TyKind::*;
2426

2527
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -48,8 +50,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4850
if self
4951
.lookup_op_method(
5052
lhs_deref_ty,
51-
Some(rhs_ty),
52-
Some(rhs),
53+
Some((rhs, rhs_ty)),
5354
Op::Binary(op, IsAssign::Yes),
5455
expected,
5556
)
@@ -60,8 +61,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6061
if self
6162
.lookup_op_method(
6263
lhs_ty,
63-
Some(rhs_ty),
64-
Some(rhs),
64+
Some((rhs, rhs_ty)),
6565
Op::Binary(op, IsAssign::Yes),
6666
expected,
6767
)
@@ -248,8 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
248248

249249
let result = self.lookup_op_method(
250250
lhs_ty,
251-
Some(rhs_ty_var),
252-
Some(rhs_expr),
251+
Some((rhs_expr, rhs_ty_var)),
253252
Op::Binary(op, is_assign),
254253
expected,
255254
);
@@ -382,8 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
382381
if self
383382
.lookup_op_method(
384383
lhs_deref_ty,
385-
Some(rhs_ty),
386-
Some(rhs_expr),
384+
Some((rhs_expr, rhs_ty)),
387385
Op::Binary(op, is_assign),
388386
expected,
389387
)
@@ -410,8 +408,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
410408
let is_compatible = |lhs_ty, rhs_ty| {
411409
self.lookup_op_method(
412410
lhs_ty,
413-
Some(rhs_ty),
414-
Some(rhs_expr),
411+
Some((rhs_expr, rhs_ty)),
415412
Op::Binary(op, is_assign),
416413
expected,
417414
)
@@ -471,8 +468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
471468
let errors = self
472469
.lookup_op_method(
473470
lhs_ty,
474-
Some(rhs_ty),
475-
Some(rhs_expr),
471+
Some((rhs_expr, rhs_ty)),
476472
Op::Binary(op, is_assign),
477473
expected,
478474
)
@@ -492,6 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
492488
if let Some(output_def_id) = output_def_id
493489
&& let Some(trait_def_id) = trait_def_id
494490
&& self.tcx.parent(output_def_id) == trait_def_id
491+
&& output_ty.is_suggestable(self.tcx, false)
495492
{
496493
Some(("Output", *output_ty))
497494
} else {
@@ -625,7 +622,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
625622
expected: Expectation<'tcx>,
626623
) -> Ty<'tcx> {
627624
assert!(op.is_by_value());
628-
match self.lookup_op_method(operand_ty, None, None, Op::Unary(op, ex.span), expected) {
625+
match self.lookup_op_method(operand_ty, None, Op::Unary(op, ex.span), expected) {
629626
Ok(method) => {
630627
self.write_method_call(ex.hir_id, method);
631628
method.sig.output()
@@ -712,8 +709,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
712709
fn lookup_op_method(
713710
&self,
714711
lhs_ty: Ty<'tcx>,
715-
other_ty: Option<Ty<'tcx>>,
716-
other_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
712+
opt_rhs: Option<(&'tcx hir::Expr<'tcx>, Ty<'tcx>)>,
717713
op: Op,
718714
expected: Expectation<'tcx>,
719715
) -> Result<MethodCallee<'tcx>, Vec<FulfillmentError<'tcx>>> {
@@ -742,20 +738,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
742738
Op::Unary(..) => 0,
743739
},
744740
) {
741+
self.tcx
742+
.sess
743+
.delay_span_bug(span, "operator didn't have the right number of generic args");
745744
return Err(vec![]);
746745
}
747746

748747
let opname = Ident::with_dummy_span(opname);
748+
let input_types =
749+
opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
750+
let cause = self.cause(
751+
span,
752+
traits::BinOp {
753+
rhs_span: opt_rhs.map(|(expr, _)| expr.span),
754+
is_lit: opt_rhs
755+
.map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
756+
output_ty: expected.only_has_type(self),
757+
},
758+
);
759+
749760
let method = trait_did.and_then(|trait_did| {
750-
self.lookup_op_method_in_trait(
751-
span,
752-
opname,
753-
trait_did,
754-
lhs_ty,
755-
other_ty,
756-
other_ty_expr,
757-
expected,
758-
)
761+
self.lookup_method_in_trait(cause.clone(), opname, trait_did, lhs_ty, Some(input_types))
759762
});
760763

761764
match (method, trait_did) {
@@ -766,14 +769,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
766769
}
767770
(None, None) => Err(vec![]),
768771
(None, Some(trait_did)) => {
769-
let (obligation, _) = self.obligation_for_op_method(
770-
span,
771-
trait_did,
772-
lhs_ty,
773-
other_ty,
774-
other_ty_expr,
775-
expected,
776-
);
772+
let (obligation, _) =
773+
self.obligation_for_method(cause, trait_did, lhs_ty, Some(input_types));
777774
Err(rustc_trait_selection::traits::fully_solve_obligation(self, obligation))
778775
}
779776
}

‎compiler/rustc_hir_typeck/src/place_op.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
225225

226226
imm_tr.and_then(|trait_did| {
227227
self.lookup_method_in_trait(
228-
span,
228+
self.misc(span),
229229
Ident::with_dummy_span(imm_op),
230230
trait_did,
231231
base_ty,
@@ -264,7 +264,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
264264

265265
mut_tr.and_then(|trait_did| {
266266
self.lookup_method_in_trait(
267-
span,
267+
self.misc(span),
268268
Ident::with_dummy_span(mut_op),
269269
trait_did,
270270
base_ty,

‎compiler/rustc_lexer/src/lib.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ impl Cursor<'_> {
851851
}
852852

853853
// Eats the identifier. Note: succeeds on `_`, which isn't a valid
854-
// identifer.
854+
// identifier.
855855
fn eat_identifier(&mut self) {
856856
if !is_id_start(self.first()) {
857857
return;

‎compiler/rustc_parse/src/errors.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,3 +1229,11 @@ pub(crate) struct FnTypoWithImpl {
12291229
#[suggestion(applicability = "maybe-incorrect", code = "impl", style = "verbose")]
12301230
pub fn_span: Span,
12311231
}
1232+
1233+
#[derive(Diagnostic)]
1234+
#[diag(parse_expected_fn_path_found_fn_keyword)]
1235+
pub(crate) struct ExpectedFnPathFoundFnKeyword {
1236+
#[primary_span]
1237+
#[suggestion(applicability = "machine-applicable", code = "Fn", style = "verbose")]
1238+
pub fn_token_span: Span,
1239+
}

‎compiler/rustc_parse/src/parser/ty.rs‎

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use super::{Parser, PathStyle, TokenType};
22

3-
use crate::errors::{FnPtrWithGenerics, FnPtrWithGenericsSugg};
3+
use crate::errors::{ExpectedFnPathFoundFnKeyword, FnPtrWithGenerics, FnPtrWithGenericsSugg};
44
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
55

6+
use ast::DUMMY_NODE_ID;
67
use rustc_ast::ptr::P;
78
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
89
use rustc_ast::util::case::Case;
@@ -12,7 +13,9 @@ use rustc_ast::{
1213
};
1314
use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
1415
use rustc_span::source_map::Span;
15-
use rustc_span::symbol::{kw, sym};
16+
use rustc_span::symbol::{kw, sym, Ident};
17+
use rustc_span::Symbol;
18+
use thin_vec::thin_vec;
1619

1720
/// Any `?` or `~const` modifiers that appear at the start of a bound.
1821
struct BoundModifiers {
@@ -931,7 +934,14 @@ impl<'a> Parser<'a> {
931934
modifiers: BoundModifiers,
932935
) -> PResult<'a, GenericBound> {
933936
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
934-
let path = self.parse_path(PathStyle::Type)?;
937+
let path = if self.token.is_keyword(kw::Fn)
938+
&& self.look_ahead(1, |tok| tok.kind == TokenKind::OpenDelim(Delimiter::Parenthesis))
939+
&& let Some(path) = self.recover_path_from_fn()
940+
{
941+
path
942+
} else {
943+
self.parse_path(PathStyle::Type)?
944+
};
935945
if has_parens {
936946
if self.token.is_like_plus() {
937947
// Someone has written something like `&dyn (Trait + Other)`. The correct code
@@ -960,6 +970,38 @@ impl<'a> Parser<'a> {
960970
Ok(GenericBound::Trait(poly_trait, modifier))
961971
}
962972

973+
// recovers a `Fn(..)` parenthesized-style path from `fn(..)`
974+
fn recover_path_from_fn(&mut self) -> Option<ast::Path> {
975+
let fn_token_span = self.token.span;
976+
self.bump();
977+
let args_lo = self.token.span;
978+
let snapshot = self.create_snapshot_for_diagnostic();
979+
match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
980+
Ok(decl) => {
981+
self.sess.emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
982+
Some(ast::Path {
983+
span: fn_token_span.to(self.prev_token.span),
984+
segments: thin_vec![ast::PathSegment {
985+
ident: Ident::new(Symbol::intern("Fn"), fn_token_span),
986+
id: DUMMY_NODE_ID,
987+
args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
988+
span: args_lo.to(self.prev_token.span),
989+
inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
990+
inputs_span: args_lo.until(decl.output.span()),
991+
output: decl.output.clone(),
992+
}))),
993+
}],
994+
tokens: None,
995+
})
996+
}
997+
Err(diag) => {
998+
diag.cancel();
999+
self.restore_snapshot(snapshot);
1000+
None
1001+
}
1002+
}
1003+
}
1004+
9631005
/// Optionally parses `for<$generic_params>`.
9641006
pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
9651007
if self.eat_keyword(kw::For) {

‎compiler/rustc_span/src/symbol.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ symbols! {
213213
Is,
214214
ItemContext,
215215
Iterator,
216+
IteratorItem,
216217
Layout,
217218
Left,
218219
LinkedList,

‎library/core/src/iter/traits/iterator.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
6666
#[must_use = "iterators are lazy and do nothing unless consumed"]
6767
pub trait Iterator {
6868
/// The type of the elements being iterated over.
69+
#[rustc_diagnostic_item = "IteratorItem"]
6970
#[stable(feature = "rust1", since = "1.0.0")]
7071
type Item;
7172

‎src/librustdoc/html/static/css/rustdoc.css‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,6 @@ img {
378378
filter: var(--rust-logo-filter);
379379
}
380380

381-
.sidebar, .mobile-topbar, .sidebar-menu-toggle {
382-
background-color: var(--sidebar-background-color);
383-
}
384-
385381
.sidebar {
386382
font-size: 0.875rem;
387383
flex: 0 0 200px;
@@ -400,7 +396,8 @@ img {
400396
overflow-y: hidden;
401397
}
402398

403-
.source .sidebar, #src-sidebar-toggle, #source-sidebar {
399+
.sidebar, .mobile-topbar, .sidebar-menu-toggle,
400+
#src-sidebar-toggle, #source-sidebar {
404401
background-color: var(--sidebar-background-color);
405402
}
406403

‎src/test/rustdoc-gui/sidebar-source-code.goml‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,52 @@
11
// The goal of this test is to ensure that the sidebar is working as expected in the source
22
// code pages.
33
goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
4-
// First: desktop mode.
4+
show-text: true
5+
6+
// First, check the sidebar colors.
7+
define-function: (
8+
"check-colors",
9+
(theme, color, background_color),
10+
[
11+
("local-storage", {
12+
"rustdoc-theme": |theme|,
13+
"rustdoc-use-system-theme": "false",
14+
}),
15+
("reload"),
16+
// Checking results colors.
17+
("assert-css", (".source .sidebar", {
18+
"color": |color|,
19+
"background-color": |background_color|
20+
}, ALL)),
21+
],
22+
)
23+
24+
call-function: (
25+
"check-colors",
26+
{
27+
"theme": "ayu",
28+
"color": "rgb(197, 197, 197)",
29+
"background_color": "rgb(20, 25, 31)",
30+
}
31+
)
32+
call-function: (
33+
"check-colors",
34+
{
35+
"theme": "dark",
36+
"color": "rgb(221, 221, 221)",
37+
"background_color": "rgb(80, 80, 80)",
38+
}
39+
)
40+
call-function: (
41+
"check-colors",
42+
{
43+
"theme": "light",
44+
"color": "rgb(0, 0, 0)",
45+
"background_color": "rgb(245, 245, 245)",
46+
}
47+
)
48+
49+
// Next, desktop mode layout.
550
size: (1100, 800)
651
// We check that the sidebar isn't expanded and has the expected width.
752
assert-css: ("nav.sidebar", {"width": "50px"})

‎src/test/rustdoc-gui/sidebar.goml‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,50 @@
22
goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
33
assert-property: (".sidebar", {"clientWidth": "200"})
44
show-text: true
5+
6+
// First, check the sidebar colors.
7+
define-function: (
8+
"check-colors",
9+
(theme, color, background_color),
10+
[
11+
("local-storage", {
12+
"rustdoc-theme": |theme|,
13+
"rustdoc-use-system-theme": "false",
14+
}),
15+
("reload"),
16+
// Checking results colors.
17+
("assert-css", (".sidebar", {
18+
"color": |color|,
19+
"background-color": |background_color|
20+
}, ALL)),
21+
],
22+
)
23+
24+
call-function: (
25+
"check-colors",
26+
{
27+
"theme": "ayu",
28+
"color": "rgb(197, 197, 197)",
29+
"background_color": "rgb(20, 25, 31)",
30+
}
31+
)
32+
call-function: (
33+
"check-colors",
34+
{
35+
"theme": "dark",
36+
"color": "rgb(221, 221, 221)",
37+
"background_color": "rgb(80, 80, 80)",
38+
}
39+
)
40+
call-function: (
41+
"check-colors",
42+
{
43+
"theme": "light",
44+
"color": "rgb(0, 0, 0)",
45+
"background_color": "rgb(245, 245, 245)",
46+
}
47+
)
48+
549
local-storage: {"rustdoc-theme": "light"}
650
// We reload the page so the local storage settings are being used.
751
reload:

‎src/test/ui/error-codes/E0033-teach.rs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
// compile-flags: -Z teach
2-
32
trait SomeTrait {
4-
fn foo(); //~ associated function `foo` has no `self` parameter
3+
fn foo(&self);
4+
}
5+
struct S;
6+
impl SomeTrait for S {
7+
fn foo(&self) {}
58
}
6-
79
fn main() {
8-
let trait_obj: &dyn SomeTrait = SomeTrait;
9-
//~^ ERROR expected value, found trait `SomeTrait`
10-
//~| ERROR E0038
10+
let trait_obj: &dyn SomeTrait = &S;
1111

1212
let &invalid = trait_obj;
1313
//~^ ERROR E0033
Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,3 @@
1-
error[E0423]: expected value, found trait `SomeTrait`
2-
--> $DIR/E0033-teach.rs:8:37
3-
|
4-
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
5-
| ^^^^^^^^^ not a value
6-
7-
error[E0038]: the trait `SomeTrait` cannot be made into an object
8-
--> $DIR/E0033-teach.rs:8:20
9-
|
10-
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
11-
| ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object
12-
|
13-
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
14-
--> $DIR/E0033-teach.rs:4:8
15-
|
16-
LL | trait SomeTrait {
17-
| --------- this trait cannot be made into an object...
18-
LL | fn foo();
19-
| ^^^ ...because associated function `foo` has no `self` parameter
20-
help: consider turning `foo` into a method by giving it a `&self` argument
21-
|
22-
LL | fn foo(&self);
23-
| +++++
24-
help: alternatively, consider constraining `foo` so it does not apply to trait objects
25-
|
26-
LL | fn foo() where Self: Sized;
27-
| +++++++++++++++++
28-
291
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
302
--> $DIR/E0033-teach.rs:12:9
313
|
@@ -36,7 +8,6 @@ LL | let &invalid = trait_obj;
368

379
You can read more about trait objects in the Trait Objects section of the Reference: https://doc.rust-lang.org/reference/types.html#trait-objects
3810

39-
error: aborting due to 3 previous errors
11+
error: aborting due to previous error
4012

41-
Some errors have detailed explanations: E0033, E0038, E0423.
42-
For more information about an error, try `rustc --explain E0033`.
13+
For more information about this error, try `rustc --explain E0033`.

‎src/test/ui/error-codes/E0033.rs‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
trait SomeTrait {
2-
fn foo(); //~ associated function `foo` has no `self` parameter
2+
fn foo(&self);
3+
}
4+
struct S;
5+
impl SomeTrait for S {
6+
fn foo(&self) {}
37
}
4-
58
fn main() {
6-
let trait_obj: &dyn SomeTrait = SomeTrait;
7-
//~^ ERROR expected value, found trait `SomeTrait`
8-
//~| ERROR E0038
9+
let trait_obj: &dyn SomeTrait = &S;
910

1011
let &invalid = trait_obj;
1112
//~^ ERROR E0033
Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,9 @@
1-
error[E0423]: expected value, found trait `SomeTrait`
2-
--> $DIR/E0033.rs:6:37
3-
|
4-
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
5-
| ^^^^^^^^^ not a value
6-
7-
error[E0038]: the trait `SomeTrait` cannot be made into an object
8-
--> $DIR/E0033.rs:6:20
9-
|
10-
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
11-
| ^^^^^^^^^^^^^^ `SomeTrait` cannot be made into an object
12-
|
13-
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
14-
--> $DIR/E0033.rs:2:8
15-
|
16-
LL | trait SomeTrait {
17-
| --------- this trait cannot be made into an object...
18-
LL | fn foo();
19-
| ^^^ ...because associated function `foo` has no `self` parameter
20-
help: consider turning `foo` into a method by giving it a `&self` argument
21-
|
22-
LL | fn foo(&self);
23-
| +++++
24-
help: alternatively, consider constraining `foo` so it does not apply to trait objects
25-
|
26-
LL | fn foo() where Self: Sized;
27-
| +++++++++++++++++
28-
291
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
30-
--> $DIR/E0033.rs:10:9
2+
--> $DIR/E0033.rs:11:9
313
|
324
LL | let &invalid = trait_obj;
335
| ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced
346

35-
error: aborting due to 3 previous errors
7+
error: aborting due to previous error
368

37-
Some errors have detailed explanations: E0033, E0038, E0423.
38-
For more information about an error, try `rustc --explain E0033`.
9+
For more information about this error, try `rustc --explain E0033`.

‎src/test/ui/lexer/lex-bad-char-literals-6.rs‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ fn main() {
77
//~^ ERROR: character literal may only contain one codepoint
88

99
if x == y {}
10-
//~^ ERROR: can't compare `&str` with `char`
1110
if y == z {} // no error here
1211
if x == z {}
13-
//~^ ERROR: can't compare `&str` with `char`
1412

1513
let a: usize = "";
1614
//~^ ERROR: mismatched types

‎src/test/ui/lexer/lex-bad-char-literals-6.stderr‎

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,49 +31,14 @@ help: if you meant to write a `str` literal, use double quotes
3131
LL | let z = "ef";
3232
| ~~~~
3333

34-
error[E0277]: can't compare `&str` with `char`
35-
--> $DIR/lex-bad-char-literals-6.rs:9:10
36-
|
37-
LL | if x == y {}
38-
| ^^ no implementation for `&str == char`
39-
|
40-
= help: the trait `PartialEq<char>` is not implemented for `&str`
41-
= help: the following other types implement trait `PartialEq<Rhs>`:
42-
<&'a str as PartialEq<OsString>>
43-
<&'a str as PartialEq<String>>
44-
<&'b str as PartialEq<Cow<'a, str>>>
45-
<str as PartialEq<Cow<'a, str>>>
46-
<str as PartialEq<OsStr>>
47-
<str as PartialEq<OsString>>
48-
<str as PartialEq<String>>
49-
<str as PartialEq>
50-
5134
error[E0308]: mismatched types
52-
--> $DIR/lex-bad-char-literals-6.rs:15:20
35+
--> $DIR/lex-bad-char-literals-6.rs:13:20
5336
|
5437
LL | let a: usize = "";
5538
| ----- ^^ expected `usize`, found `&str`
5639
| |
5740
| expected due to this
5841

59-
error[E0277]: can't compare `&str` with `char`
60-
--> $DIR/lex-bad-char-literals-6.rs:12:10
61-
|
62-
LL | if x == z {}
63-
| ^^ no implementation for `&str == char`
64-
|
65-
= help: the trait `PartialEq<char>` is not implemented for `&str`
66-
= help: the following other types implement trait `PartialEq<Rhs>`:
67-
<&'a str as PartialEq<OsString>>
68-
<&'a str as PartialEq<String>>
69-
<&'b str as PartialEq<Cow<'a, str>>>
70-
<str as PartialEq<Cow<'a, str>>>
71-
<str as PartialEq<OsStr>>
72-
<str as PartialEq<OsString>>
73-
<str as PartialEq<String>>
74-
<str as PartialEq>
75-
76-
error: aborting due to 6 previous errors
42+
error: aborting due to 4 previous errors
7743

78-
Some errors have detailed explanations: E0277, E0308.
79-
For more information about an error, try `rustc --explain E0277`.
44+
For more information about this error, try `rustc --explain E0308`.

‎src/test/ui/parser/kw-in-trait-bounds.rs‎

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,13 @@ fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
44
//~^ ERROR expected identifier, found keyword `fn`
55
//~| ERROR expected identifier, found keyword `fn`
66
//~| ERROR expected identifier, found keyword `fn`
7-
//~| ERROR cannot find trait `r#fn` in this scope
8-
//~| ERROR cannot find trait `r#fn` in this scope
9-
//~| ERROR cannot find trait `r#fn` in this scope
10-
//~| HELP a trait with a similar name exists
11-
//~| HELP a trait with a similar name exists
12-
//~| HELP a trait with a similar name exists
13-
//~| HELP escape `fn` to use it as an identifier
14-
//~| HELP escape `fn` to use it as an identifier
15-
//~| HELP escape `fn` to use it as an identifier
7+
//~| HELP use `Fn` to refer to the trait
8+
//~| HELP use `Fn` to refer to the trait
9+
//~| HELP use `Fn` to refer to the trait
1610
where
1711
G: fn(),
1812
//~^ ERROR expected identifier, found keyword `fn`
19-
//~| ERROR cannot find trait `r#fn` in this scope
20-
//~| HELP a trait with a similar name exists
21-
//~| HELP escape `fn` to use it as an identifier
13+
//~| HELP use `Fn` to refer to the trait
2214
{}
2315

2416
fn _g<A: struct, B>(_: impl struct, _: &dyn struct)

‎src/test/ui/parser/kw-in-trait-bounds.stderr‎

Lines changed: 26 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,48 @@ error: expected identifier, found keyword `fn`
22
--> $DIR/kw-in-trait-bounds.rs:3:10
33
|
44
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
5-
| ^^ expected identifier, found keyword
5+
| ^^
66
|
7-
help: escape `fn` to use it as an identifier
7+
help: use `Fn` to refer to the trait
88
|
9-
LL | fn _f<F: r#fn(), G>(_: impl fn(), _: &dyn fn())
10-
| ++
9+
LL | fn _f<F: Fn(), G>(_: impl fn(), _: &dyn fn())
10+
| ~~
1111

1212
error: expected identifier, found keyword `fn`
1313
--> $DIR/kw-in-trait-bounds.rs:3:27
1414
|
1515
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
16-
| ^^ expected identifier, found keyword
16+
| ^^
1717
|
18-
help: escape `fn` to use it as an identifier
18+
help: use `Fn` to refer to the trait
1919
|
20-
LL | fn _f<F: fn(), G>(_: impl r#fn(), _: &dyn fn())
21-
| ++
20+
LL | fn _f<F: fn(), G>(_: impl Fn(), _: &dyn fn())
21+
| ~~
2222

2323
error: expected identifier, found keyword `fn`
2424
--> $DIR/kw-in-trait-bounds.rs:3:41
2525
|
2626
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
27-
| ^^ expected identifier, found keyword
27+
| ^^
2828
|
29-
help: escape `fn` to use it as an identifier
29+
help: use `Fn` to refer to the trait
3030
|
31-
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn r#fn())
32-
| ++
31+
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn Fn())
32+
| ~~
3333

3434
error: expected identifier, found keyword `fn`
35-
--> $DIR/kw-in-trait-bounds.rs:17:4
35+
--> $DIR/kw-in-trait-bounds.rs:11:4
3636
|
3737
LL | G: fn(),
38-
| ^^ expected identifier, found keyword
38+
| ^^
3939
|
40-
help: escape `fn` to use it as an identifier
40+
help: use `Fn` to refer to the trait
4141
|
42-
LL | G: r#fn(),
43-
| ++
42+
LL | G: Fn(),
43+
| ~~
4444

4545
error: expected identifier, found keyword `struct`
46-
--> $DIR/kw-in-trait-bounds.rs:24:10
46+
--> $DIR/kw-in-trait-bounds.rs:16:10
4747
|
4848
LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
4949
| ^^^^^^ expected identifier, found keyword
@@ -54,7 +54,7 @@ LL | fn _g<A: r#struct, B>(_: impl struct, _: &dyn struct)
5454
| ++
5555

5656
error: expected identifier, found keyword `struct`
57-
--> $DIR/kw-in-trait-bounds.rs:24:29
57+
--> $DIR/kw-in-trait-bounds.rs:16:29
5858
|
5959
LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
6060
| ^^^^^^ expected identifier, found keyword
@@ -65,7 +65,7 @@ LL | fn _g<A: struct, B>(_: impl r#struct, _: &dyn struct)
6565
| ++
6666

6767
error: expected identifier, found keyword `struct`
68-
--> $DIR/kw-in-trait-bounds.rs:24:45
68+
--> $DIR/kw-in-trait-bounds.rs:16:45
6969
|
7070
LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
7171
| ^^^^^^ expected identifier, found keyword
@@ -76,7 +76,7 @@ LL | fn _g<A: struct, B>(_: impl struct, _: &dyn r#struct)
7676
| ++
7777

7878
error: expected identifier, found keyword `struct`
79-
--> $DIR/kw-in-trait-bounds.rs:38:8
79+
--> $DIR/kw-in-trait-bounds.rs:30:8
8080
|
8181
LL | B: struct,
8282
| ^^^^^^ expected identifier, found keyword
@@ -86,44 +86,8 @@ help: escape `struct` to use it as an identifier
8686
LL | B: r#struct,
8787
| ++
8888

89-
error[E0405]: cannot find trait `r#fn` in this scope
90-
--> $DIR/kw-in-trait-bounds.rs:3:10
91-
|
92-
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
93-
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
94-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
95-
|
96-
= note: similarly named trait `Fn` defined here
97-
98-
error[E0405]: cannot find trait `r#fn` in this scope
99-
--> $DIR/kw-in-trait-bounds.rs:17:4
100-
|
101-
LL | G: fn(),
102-
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
103-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
104-
|
105-
= note: similarly named trait `Fn` defined here
106-
107-
error[E0405]: cannot find trait `r#fn` in this scope
108-
--> $DIR/kw-in-trait-bounds.rs:3:27
109-
|
110-
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
111-
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
112-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
113-
|
114-
= note: similarly named trait `Fn` defined here
115-
116-
error[E0405]: cannot find trait `r#fn` in this scope
117-
--> $DIR/kw-in-trait-bounds.rs:3:41
118-
|
119-
LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
120-
| ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
121-
--> $SRC_DIR/core/src/ops/function.rs:LL:COL
122-
|
123-
= note: similarly named trait `Fn` defined here
124-
12589
error[E0405]: cannot find trait `r#struct` in this scope
126-
--> $DIR/kw-in-trait-bounds.rs:24:10
90+
--> $DIR/kw-in-trait-bounds.rs:16:10
12791
|
12892
LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
12993
| ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
@@ -132,7 +96,7 @@ LL | trait Struct {}
13296
| ------------ similarly named trait `Struct` defined here
13397

13498
error[E0405]: cannot find trait `r#struct` in this scope
135-
--> $DIR/kw-in-trait-bounds.rs:38:8
99+
--> $DIR/kw-in-trait-bounds.rs:30:8
136100
|
137101
LL | B: struct,
138102
| ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
@@ -141,7 +105,7 @@ LL | trait Struct {}
141105
| ------------ similarly named trait `Struct` defined here
142106

143107
error[E0405]: cannot find trait `r#struct` in this scope
144-
--> $DIR/kw-in-trait-bounds.rs:24:29
108+
--> $DIR/kw-in-trait-bounds.rs:16:29
145109
|
146110
LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
147111
| ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
@@ -150,14 +114,14 @@ LL | trait Struct {}
150114
| ------------ similarly named trait `Struct` defined here
151115

152116
error[E0405]: cannot find trait `r#struct` in this scope
153-
--> $DIR/kw-in-trait-bounds.rs:24:45
117+
--> $DIR/kw-in-trait-bounds.rs:16:45
154118
|
155119
LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
156120
| ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
157121
...
158122
LL | trait Struct {}
159123
| ------------ similarly named trait `Struct` defined here
160124

161-
error: aborting due to 16 previous errors
125+
error: aborting due to 12 previous errors
162126

163127
For more information about this error, try `rustc --explain E0405`.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn foo(_: impl fn() -> i32) {}
2+
//~^ ERROR expected identifier, found keyword `fn`
3+
4+
fn foo2<T: fn(i32)>(_: T) {}
5+
//~^ ERROR expected identifier, found keyword `fn`
6+
7+
fn main() {
8+
foo(|| ());
9+
//~^ mismatched types
10+
foo2(|_: ()| {});
11+
//~^ type mismatch in closure arguments
12+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error: expected identifier, found keyword `fn`
2+
--> $DIR/recover-fn-trait-from-fn-kw.rs:1:16
3+
|
4+
LL | fn foo(_: impl fn() -> i32) {}
5+
| ^^
6+
|
7+
help: use `Fn` to refer to the trait
8+
|
9+
LL | fn foo(_: impl Fn() -> i32) {}
10+
| ~~
11+
12+
error: expected identifier, found keyword `fn`
13+
--> $DIR/recover-fn-trait-from-fn-kw.rs:4:12
14+
|
15+
LL | fn foo2<T: fn(i32)>(_: T) {}
16+
| ^^
17+
|
18+
help: use `Fn` to refer to the trait
19+
|
20+
LL | fn foo2<T: Fn(i32)>(_: T) {}
21+
| ~~
22+
23+
error[E0308]: mismatched types
24+
--> $DIR/recover-fn-trait-from-fn-kw.rs:8:12
25+
|
26+
LL | foo(|| ());
27+
| ^^ expected `i32`, found `()`
28+
29+
error[E0631]: type mismatch in closure arguments
30+
--> $DIR/recover-fn-trait-from-fn-kw.rs:10:5
31+
|
32+
LL | foo2(|_: ()| {});
33+
| ^^^^ ------- found signature defined here
34+
| |
35+
| expected due to this
36+
|
37+
= note: expected closure signature `fn(i32) -> _`
38+
found closure signature `fn(()) -> _`
39+
note: required by a bound in `foo2`
40+
--> $DIR/recover-fn-trait-from-fn-kw.rs:4:12
41+
|
42+
LL | fn foo2<T: fn(i32)>(_: T) {}
43+
| ^^^^^^^ required by this bound in `foo2`
44+
45+
error: aborting due to 4 previous errors
46+
47+
Some errors have detailed explanations: E0308, E0631.
48+
For more information about an error, try `rustc --explain E0308`.
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
// The purpose of this test is not to validate the output of the compiler.
22
// Instead, it ensures the suggestion is generated without performing an arithmetic overflow.
33

4+
struct S;
5+
impl S {
6+
fn foo(&self) {}
7+
}
48
fn main() {
5-
let x = not_found; //~ ERROR cannot find value `not_found` in this scope
6-
simd_gt::<()>(x);
9+
let x = S;
10+
foo::<()>(x);
711
//~^ ERROR this associated function takes 0 generic arguments but 1 generic argument was supplied
8-
//~| ERROR cannot find function `simd_gt` in this scope
12+
//~| ERROR cannot find function `foo` in this scope
913
}
Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
error[E0425]: cannot find value `not_found` in this scope
2-
--> $DIR/issue-104287.rs:5:13
3-
|
4-
LL | let x = not_found;
5-
| ^^^^^^^^^ not found in this scope
6-
71
error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
8-
--> $DIR/issue-104287.rs:6:5
2+
--> $DIR/issue-104287.rs:10:5
93
|
10-
LL | simd_gt::<()>(x);
11-
| ^^^^^^^------ help: remove these generics
4+
LL | foo::<()>(x);
5+
| ^^^------ help: remove these generics
126
| |
137
| expected 0 generic arguments
8+
|
9+
note: associated function defined here, with 0 generic parameters
10+
--> $DIR/issue-104287.rs:6:8
11+
|
12+
LL | fn foo(&self) {}
13+
| ^^^
1414

15-
error[E0425]: cannot find function `simd_gt` in this scope
16-
--> $DIR/issue-104287.rs:6:5
15+
error[E0425]: cannot find function `foo` in this scope
16+
--> $DIR/issue-104287.rs:10:5
1717
|
18-
LL | simd_gt::<()>(x);
19-
| ^^^^^^^ not found in this scope
18+
LL | foo::<()>(x);
19+
| ^^^ not found in this scope
2020
|
21-
help: use the `.` operator to call the method `SimdPartialOrd::simd_gt` on `[type error]`
21+
help: use the `.` operator to call the method `foo` on `&S`
2222
|
23-
LL - simd_gt::<()>(x);
24-
LL + x.simd_gt();
23+
LL - foo::<()>(x);
24+
LL + x.foo();
2525
|
2626

27-
error: aborting due to 3 previous errors
27+
error: aborting due to 2 previous errors
2828

2929
Some errors have detailed explanations: E0107, E0425.
3030
For more information about an error, try `rustc --explain E0107`.

‎src/test/ui/suggestions/unnamable-types.stderr‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
1919
LL | const C: _ = || 42;
2020
| ^ not allowed in type signatures
2121
|
22-
note: however, the inferred type `[closure@$DIR/unnamable-types.rs:17:14: 17:16]` cannot be named
22+
note: however, the inferred type `[closure@unnamable-types.rs:17:14]` cannot be named
2323
--> $DIR/unnamable-types.rs:17:14
2424
|
2525
LL | const C: _ = || 42;
@@ -31,7 +31,7 @@ error: missing type for `const` item
3131
LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
3232
| ^
3333
|
34-
note: however, the inferred type `S<[closure@$DIR/unnamable-types.rs:23:31: 23:45]>` cannot be named
34+
note: however, the inferred type `S<[closure@unnamable-types.rs:23:31]>` cannot be named
3535
--> $DIR/unnamable-types.rs:23:11
3636
|
3737
LL | const D = S { t: { let i = 0; move || -> i32 { i } } };
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// fn foo() -> String {
2+
// String::new()
3+
// }
4+
5+
fn test(s: &str) {
6+
println!("{}", s);
7+
}
8+
9+
fn test2(s: String) {
10+
println!("{}", s);
11+
}
12+
13+
fn main() {
14+
let x = foo(); //~ERROR cannot find function `foo` in this scope
15+
test(&x);
16+
test2(x); // Does not complain about `x` being a `&str`.
17+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0425]: cannot find function `foo` in this scope
2+
--> $DIR/quiet-type-err-let-binding.rs:14:13
3+
|
4+
LL | let x = foo();
5+
| ^^^ not found in this scope
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0425`.

‎src/test/ui/typeck/typeck_type_placeholder_item.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,11 @@ fn value() -> Option<&'static _> {
220220

221221
const _: Option<_> = map(value);
222222
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
223+
224+
fn evens_squared(n: usize) -> _ {
225+
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
226+
(1..n).filter(|x| x % 2 == 0).map(|x| x * x)
227+
}
228+
229+
const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
230+
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants

‎src/test/ui/typeck/typeck_type_placeholder_item.stderr‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,27 @@ LL | const _: Option<_> = map(value);
428428
| not allowed in type signatures
429429
| help: replace with the correct type: `Option<u8>`
430430

431+
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
432+
--> $DIR/typeck_type_placeholder_item.rs:224:31
433+
|
434+
LL | fn evens_squared(n: usize) -> _ {
435+
| ^
436+
| |
437+
| not allowed in type signatures
438+
| help: replace with an appropriate return type: `impl Iterator<Item = usize>`
439+
440+
error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
441+
--> $DIR/typeck_type_placeholder_item.rs:229:10
442+
|
443+
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
444+
| ^ not allowed in type signatures
445+
|
446+
note: however, the inferred type `Map<Filter<Range<i32>, [closure@typeck_type_placeholder_item.rs:229:29]>, [closure@typeck_type_placeholder_item.rs:229:49]>` cannot be named
447+
--> $DIR/typeck_type_placeholder_item.rs:229:14
448+
|
449+
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
450+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
451+
431452
error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
432453
--> $DIR/typeck_type_placeholder_item.rs:140:31
433454
|
@@ -636,7 +657,7 @@ LL | const D: _ = 42;
636657
| not allowed in type signatures
637658
| help: replace with the correct type: `i32`
638659

639-
error: aborting due to 69 previous errors
660+
error: aborting due to 71 previous errors
640661

641662
Some errors have detailed explanations: E0121, E0282, E0403.
642663
For more information about an error, try `rustc --explain E0121`.

0 commit comments

Comments
 (0)
Please sign in to comment.