Skip to content

Commit 1146560

Browse files
committedJan 6, 2023
Auto merge of rust-lang#106529 - Dylan-DPC:rollup-mvncmrk, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - rust-lang#106400 (Point at expressions where inference refines an unexpected type) - rust-lang#106491 (Fix error-index redirect to work with the back button.) - rust-lang#106494 (Add regression test for rust-lang#58355) - rust-lang#106499 (fix [type error] for error E0029 and E0277) - rust-lang#106502 (rustdoc: remove legacy user-select CSS) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents ce8fbe7 + dd97619 commit 1146560

24 files changed

+515
-24
lines changed
 

‎compiler/rustc_hir_typeck/src/demand.rs

+220-3
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
use crate::FnCtxt;
22
use rustc_ast::util::parser::PREC_POSTFIX;
3+
use rustc_data_structures::fx::FxHashMap;
34
use rustc_errors::MultiSpan;
45
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
56
use rustc_hir as hir;
67
use rustc_hir::def::CtorKind;
8+
use rustc_hir::intravisit::Visitor;
79
use rustc_hir::lang_items::LangItem;
810
use rustc_hir::{is_range_literal, Node};
911
use rustc_infer::infer::InferOk;
1012
use rustc_middle::lint::in_external_macro;
1113
use rustc_middle::middle::stability::EvalResult;
1214
use rustc_middle::ty::adjustment::AllowTwoPhase;
1315
use rustc_middle::ty::error::{ExpectedFound, TypeError};
14-
use rustc_middle::ty::print::with_no_trimmed_paths;
15-
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut};
16+
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder};
17+
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
18+
use rustc_middle::ty::relate::TypeRelation;
19+
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeVisitable};
1620
use rustc_span::symbol::{sym, Symbol};
1721
use rustc_span::{BytePos, Span};
1822
use rustc_trait_selection::infer::InferCtxtExt as _;
23+
use rustc_trait_selection::traits::error_reporting::method_chain::CollectAllMismatches;
1924
use rustc_trait_selection::traits::ObligationCause;
2025

2126
use super::method::probe;
@@ -40,7 +45,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4045
self.annotate_alternative_method_deref(err, expr, error);
4146

4247
// Use `||` to give these suggestions a precedence
43-
let _ = self.suggest_missing_parentheses(err, expr)
48+
let suggested = self.suggest_missing_parentheses(err, expr)
4449
|| self.suggest_remove_last_method_call(err, expr, expected)
4550
|| self.suggest_associated_const(err, expr, expected)
4651
|| self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
@@ -54,6 +59,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5459
|| self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
5560
|| self.suggest_into(err, expr, expr_ty, expected)
5661
|| self.suggest_floating_point_literal(err, expr, expected);
62+
if !suggested {
63+
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected);
64+
}
5765
}
5866

5967
pub fn emit_coerce_suggestions(
@@ -205,6 +213,215 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
205213
(expected, Some(err))
206214
}
207215

216+
pub fn point_at_expr_source_of_inferred_type(
217+
&self,
218+
err: &mut Diagnostic,
219+
expr: &hir::Expr<'_>,
220+
found: Ty<'tcx>,
221+
expected: Ty<'tcx>,
222+
) -> bool {
223+
let map = self.tcx.hir();
224+
225+
let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; };
226+
let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; };
227+
let hir::def::Res::Local(hir_id) = p.res else { return false; };
228+
let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; };
229+
let Some(hir::Node::Local(hir::Local {
230+
ty: None,
231+
init: Some(init),
232+
..
233+
})) = map.find_parent(pat.hir_id) else { return false; };
234+
let Some(ty) = self.node_ty_opt(init.hir_id) else { return false; };
235+
if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() {
236+
return false;
237+
}
238+
239+
// Locate all the usages of the relevant binding.
240+
struct FindExprs<'hir> {
241+
hir_id: hir::HirId,
242+
uses: Vec<&'hir hir::Expr<'hir>>,
243+
}
244+
impl<'v> Visitor<'v> for FindExprs<'v> {
245+
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
246+
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind
247+
&& let hir::def::Res::Local(hir_id) = path.res
248+
&& hir_id == self.hir_id
249+
{
250+
self.uses.push(ex);
251+
}
252+
hir::intravisit::walk_expr(self, ex);
253+
}
254+
}
255+
256+
let mut expr_finder = FindExprs { hir_id, uses: vec![] };
257+
let id = map.get_parent_item(hir_id);
258+
let hir_id: hir::HirId = id.into();
259+
260+
let Some(node) = map.find(hir_id) else { return false; };
261+
let Some(body_id) = node.body_id() else { return false; };
262+
let body = map.body(body_id);
263+
expr_finder.visit_expr(body.value);
264+
// Hack to make equality checks on types with inference variables and regions useful.
265+
let mut eraser = BottomUpFolder {
266+
tcx: self.tcx,
267+
lt_op: |_| self.tcx.lifetimes.re_erased,
268+
ct_op: |c| c,
269+
ty_op: |t| match *t.kind() {
270+
ty::Infer(ty::TyVar(vid)) => self.tcx.mk_ty_infer(ty::TyVar(self.root_var(vid))),
271+
ty::Infer(ty::IntVar(_)) => {
272+
self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 }))
273+
}
274+
ty::Infer(ty::FloatVar(_)) => {
275+
self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 }))
276+
}
277+
_ => t,
278+
},
279+
};
280+
let mut prev = eraser.fold_ty(ty);
281+
let mut prev_span = None;
282+
283+
for binding in expr_finder.uses {
284+
// In every expression where the binding is referenced, we will look at that
285+
// expression's type and see if it is where the incorrect found type was fully
286+
// "materialized" and point at it. We will also try to provide a suggestion there.
287+
if let Some(hir::Node::Expr(expr)
288+
| hir::Node::Stmt(hir::Stmt {
289+
kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr),
290+
..
291+
})) = &map.find_parent(binding.hir_id)
292+
&& let hir::ExprKind::MethodCall(segment, rcvr, args, _span) = expr.kind
293+
&& rcvr.hir_id == binding.hir_id
294+
&& let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id)
295+
{
296+
// We special case methods, because they can influence inference through the
297+
// call's arguments and we can provide a more explicit span.
298+
let sig = self.tcx.fn_sig(def_id);
299+
let def_self_ty = sig.input(0).skip_binder();
300+
let rcvr_ty = self.node_ty(rcvr.hir_id);
301+
// Get the evaluated type *after* calling the method call, so that the influence
302+
// of the arguments can be reflected in the receiver type. The receiver
303+
// expression has the type *before* theis analysis is done.
304+
let ty = match self.lookup_probe(
305+
segment.ident,
306+
rcvr_ty,
307+
expr,
308+
probe::ProbeScope::TraitsInScope,
309+
) {
310+
Ok(pick) => pick.self_ty,
311+
Err(_) => rcvr_ty,
312+
};
313+
// Remove one layer of references to account for `&mut self` and
314+
// `&self`, so that we can compare it against the binding.
315+
let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) {
316+
(ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty),
317+
_ => (ty, def_self_ty),
318+
};
319+
let mut param_args = FxHashMap::default();
320+
let mut param_expected = FxHashMap::default();
321+
let mut param_found = FxHashMap::default();
322+
if self.can_eq(self.param_env, ty, found).is_ok() {
323+
// We only point at the first place where the found type was inferred.
324+
for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() {
325+
if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
326+
// We found an argument that references a type parameter in `Self`,
327+
// so we assume that this is the argument that caused the found
328+
// type, which we know already because of `can_eq` above was first
329+
// inferred in this method call.
330+
let arg = &args[i];
331+
let arg_ty = self.node_ty(arg.hir_id);
332+
err.span_label(
333+
arg.span,
334+
&format!(
335+
"this is of type `{arg_ty}`, which causes `{ident}` to be \
336+
inferred as `{ty}`",
337+
),
338+
);
339+
param_args.insert(param_ty, (arg, arg_ty));
340+
}
341+
}
342+
}
343+
344+
// Here we find, for a type param `T`, the type that `T` is in the current
345+
// method call *and* in the original expected type. That way, we can see if we
346+
// can give any structured suggestion for the function argument.
347+
let mut c = CollectAllMismatches {
348+
infcx: &self.infcx,
349+
param_env: self.param_env,
350+
errors: vec![],
351+
};
352+
let _ = c.relate(def_self_ty, ty);
353+
for error in c.errors {
354+
if let TypeError::Sorts(error) = error {
355+
param_found.insert(error.expected, error.found);
356+
}
357+
}
358+
c.errors = vec![];
359+
let _ = c.relate(def_self_ty, expected);
360+
for error in c.errors {
361+
if let TypeError::Sorts(error) = error {
362+
param_expected.insert(error.expected, error.found);
363+
}
364+
}
365+
for (param, (arg, arg_ty)) in param_args.iter() {
366+
let Some(expected) = param_expected.get(param) else { continue; };
367+
let Some(found) = param_found.get(param) else { continue; };
368+
if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; }
369+
self.emit_coerce_suggestions(err, arg, *found, *expected, None, None);
370+
}
371+
372+
let ty = eraser.fold_ty(ty);
373+
if ty.references_error() {
374+
break;
375+
}
376+
if ty != prev
377+
&& param_args.is_empty()
378+
&& self.can_eq(self.param_env, ty, found).is_ok()
379+
{
380+
// We only point at the first place where the found type was inferred.
381+
err.span_label(
382+
segment.ident.span,
383+
with_forced_trimmed_paths!(format!(
384+
"here the type of `{ident}` is inferred to be `{ty}`",
385+
)),
386+
);
387+
break;
388+
} else if !param_args.is_empty() {
389+
break;
390+
}
391+
prev = ty;
392+
} else {
393+
let ty = eraser.fold_ty(self.node_ty(binding.hir_id));
394+
if ty.references_error() {
395+
break;
396+
}
397+
if ty != prev
398+
&& let Some(span) = prev_span
399+
&& self.can_eq(self.param_env, ty, found).is_ok()
400+
{
401+
// We only point at the first place where the found type was inferred.
402+
// We use the *previous* span because if the type is known *here* it means
403+
// it was *evaluated earlier*. We don't do this for method calls because we
404+
// evaluate the method's self type eagerly, but not in any other case.
405+
err.span_label(
406+
span,
407+
with_forced_trimmed_paths!(format!(
408+
"here the type of `{ident}` is inferred to be `{ty}`",
409+
)),
410+
);
411+
break;
412+
}
413+
prev = ty;
414+
}
415+
if binding.hir_id == expr.hir_id {
416+
// Do not look at expressions that come after the expression we were originally
417+
// evaluating and had a type error.
418+
break;
419+
}
420+
prev_span = Some(binding.span);
421+
}
422+
true
423+
}
424+
208425
fn annotate_expected_due_to_let_ty(
209426
&self,
210427
err: &mut Diagnostic,

‎compiler/rustc_hir_typeck/src/expr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
234234
) => self.check_expr_path(qpath, expr, args),
235235
_ => self.check_expr_kind(expr, expected),
236236
});
237+
let ty = self.resolve_vars_if_possible(ty);
237238

238239
// Warn for non-block expressions with diverging children.
239240
match expr.kind {

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

+12
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
798798
full_call_span,
799799
format!("arguments to this {} are incorrect", call_name),
800800
);
801+
if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) =
802+
(callee_ty, &call_expr.kind)
803+
{
804+
// Type that would have accepted this argument if it hadn't been inferred earlier.
805+
// FIXME: We leave an inference variable for now, but it'd be nice to get a more
806+
// specific type to increase the accuracy of the diagnostic.
807+
let expected = self.infcx.next_ty_var(TypeVariableOrigin {
808+
kind: TypeVariableOriginKind::MiscVariable,
809+
span: full_call_span,
810+
});
811+
self.point_at_expr_source_of_inferred_type(&mut err, rcvr, expected, callee_ty);
812+
}
801813
// Call out where the function is defined
802814
self.label_fn_like(
803815
&mut err,

‎compiler/rustc_hir_typeck/src/pat.rs

+3
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
553553
(lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs),
554554
_ => span_bug!(span, "Impossible, verified above."),
555555
}
556+
if (lhs, rhs).references_error() {
557+
err.downgrade_to_delayed_bug();
558+
}
556559
if self.tcx.sess.teach(&err.get_code().unwrap()) {
557560
err.note(
558561
"In a match expression, only numbers and characters can be matched \

‎compiler/rustc_infer/src/infer/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'tcx> InferCtxt<'tcx> {
6161
.as_local()
6262
.map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some())
6363
};
64-
let value = value.fold_with(&mut ty::fold::BottomUpFolder {
64+
let value = value.fold_with(&mut BottomUpFolder {
6565
tcx: self.tcx,
6666
lt_op: |lt| lt,
6767
ct_op: |ct| ct,

‎compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1407,7 +1407,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
14071407

14081408
self.note_obligation_cause(&mut err, &obligation);
14091409
self.point_at_returns_when_relevant(&mut err, &obligation);
1410-
14111410
err.emit();
14121411
}
14131412
}

‎compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ pub trait TypeErrCtxtExt<'tcx> {
248248

249249
fn point_at_returns_when_relevant(
250250
&self,
251-
err: &mut Diagnostic,
251+
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
252252
obligation: &PredicateObligation<'tcx>,
253253
);
254254

@@ -1685,7 +1685,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
16851685

16861686
fn point_at_returns_when_relevant(
16871687
&self,
1688-
err: &mut Diagnostic,
1688+
err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
16891689
obligation: &PredicateObligation<'tcx>,
16901690
) {
16911691
match obligation.cause.code().peel_derives() {
@@ -1707,7 +1707,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
17071707
for expr in &visitor.returns {
17081708
if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) {
17091709
let ty = self.resolve_vars_if_possible(returned_ty);
1710-
err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
1710+
if ty.references_error() {
1711+
// don't print out the [type error] here
1712+
err.delay_as_bug();
1713+
} else {
1714+
err.span_label(
1715+
expr.span,
1716+
&format!("this returned value is of type `{}`", ty),
1717+
);
1718+
}
17111719
}
17121720
}
17131721
}

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

-2
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,6 @@ ul.block, .block li {
538538
overflow: initial;
539539
text-align: right;
540540
-webkit-user-select: none;
541-
-moz-user-select: none;
542-
-ms-user-select: none;
543541
user-select: none;
544542
padding: 14px 8px;
545543
color: var(--src-line-numbers-span-color);

‎src/test/ui/type/issue-58355.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![crate_type = "lib"]
2+
3+
pub fn foo(callback: fn() -> dyn ToString) {
4+
let mut x: Option<Box<dyn Fn() -> dyn ToString>> = None;
5+
x = Some(Box::new(callback));
6+
//~^ ERROR: the size for values of type `dyn ToString` cannot be known at compilation time
7+
}

‎src/test/ui/type/issue-58355.stderr

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time
2+
--> $DIR/issue-58355.rs:5:14
3+
|
4+
LL | x = Some(Box::new(callback));
5+
| ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
6+
|
7+
= help: within `fn() -> dyn ToString`, the trait `Sized` is not implemented for `dyn ToString`
8+
= note: required because it appears within the type `fn() -> dyn ToString`
9+
= note: required for the cast from `fn() -> dyn ToString` to the object type `dyn Fn() -> (dyn ToString + 'static)`
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0277`.

‎src/test/ui/type/type-check/assignment-in-if.stderr

+9
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ LL | x == 5
6767
error[E0308]: mismatched types
6868
--> $DIR/assignment-in-if.rs:44:18
6969
|
70+
LL | if y = (Foo { foo: x }) {
71+
| - here the type of `x` is inferred to be `usize`
72+
...
7073
LL | if x == x && x = x && x == x {
7174
| ------ ^ expected `bool`, found `usize`
7275
| |
@@ -75,6 +78,9 @@ LL | if x == x && x = x && x == x {
7578
error[E0308]: mismatched types
7679
--> $DIR/assignment-in-if.rs:44:22
7780
|
81+
LL | if y = (Foo { foo: x }) {
82+
| - here the type of `x` is inferred to be `usize`
83+
...
7884
LL | if x == x && x = x && x == x {
7985
| ^ expected `bool`, found `usize`
8086

@@ -92,6 +98,9 @@ LL | if x == x && x == x && x == x {
9298
error[E0308]: mismatched types
9399
--> $DIR/assignment-in-if.rs:51:28
94100
|
101+
LL | if y = (Foo { foo: x }) {
102+
| - here the type of `x` is inferred to be `usize`
103+
...
95104
LL | if x == x && x == x && x = x {
96105
| ---------------- ^ expected `bool`, found `usize`
97106
| |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn bar(_: Vec<i32>) {}
2+
fn baz(_: &Vec<&i32>) {}
3+
fn main() {
4+
let v = vec![&1];
5+
bar(v); //~ ERROR E0308
6+
let v = vec![];
7+
baz(&v);
8+
baz(&v);
9+
bar(v); //~ ERROR E0308
10+
let v = vec![];
11+
baz(&v);
12+
bar(v); //~ ERROR E0308
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/point-at-inference-2.rs:5:9
3+
|
4+
LL | bar(v);
5+
| --- ^ expected `i32`, found `&{integer}`
6+
| |
7+
| arguments to this function are incorrect
8+
|
9+
= note: expected struct `Vec<i32>`
10+
found struct `Vec<&{integer}>`
11+
note: function defined here
12+
--> $DIR/point-at-inference-2.rs:1:4
13+
|
14+
LL | fn bar(_: Vec<i32>) {}
15+
| ^^^ -----------
16+
17+
error[E0308]: mismatched types
18+
--> $DIR/point-at-inference-2.rs:9:9
19+
|
20+
LL | baz(&v);
21+
| - here the type of `v` is inferred to be `Vec<&i32>`
22+
LL | baz(&v);
23+
LL | bar(v);
24+
| --- ^ expected `i32`, found `&i32`
25+
| |
26+
| arguments to this function are incorrect
27+
|
28+
= note: expected struct `Vec<i32>`
29+
found struct `Vec<&i32>`
30+
note: function defined here
31+
--> $DIR/point-at-inference-2.rs:1:4
32+
|
33+
LL | fn bar(_: Vec<i32>) {}
34+
| ^^^ -----------
35+
36+
error[E0308]: mismatched types
37+
--> $DIR/point-at-inference-2.rs:12:9
38+
|
39+
LL | baz(&v);
40+
| - here the type of `v` is inferred to be `Vec<&i32>`
41+
LL | bar(v);
42+
| --- ^ expected `i32`, found `&i32`
43+
| |
44+
| arguments to this function are incorrect
45+
|
46+
= note: expected struct `Vec<i32>`
47+
found struct `Vec<&i32>`
48+
note: function defined here
49+
--> $DIR/point-at-inference-2.rs:1:4
50+
|
51+
LL | fn bar(_: Vec<i32>) {}
52+
| ^^^ -----------
53+
54+
error: aborting due to 3 previous errors
55+
56+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
fn main() {
3+
let mut v = Vec::new();
4+
v.push(0i32);
5+
//~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
6+
v.push(0);
7+
v.push(1i32); //~ ERROR mismatched types
8+
//~^ NOTE expected `i32`, found `u32`
9+
//~| NOTE arguments to this method are incorrect
10+
//~| NOTE associated function defined here
11+
//~| HELP change the type of the numeric literal from `u32` to `i32`
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
fn main() {
3+
let mut v = Vec::new();
4+
v.push(0i32);
5+
//~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
6+
v.push(0);
7+
v.push(1u32); //~ ERROR mismatched types
8+
//~^ NOTE expected `i32`, found `u32`
9+
//~| NOTE arguments to this method are incorrect
10+
//~| NOTE associated function defined here
11+
//~| HELP change the type of the numeric literal from `u32` to `i32`
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/point-at-inference-3.rs:7:12
3+
|
4+
LL | v.push(0i32);
5+
| ---- this is of type `i32`, which causes `v` to be inferred as `Vec<i32>`
6+
...
7+
LL | v.push(1u32);
8+
| ---- ^^^^ expected `i32`, found `u32`
9+
| |
10+
| arguments to this method are incorrect
11+
|
12+
note: associated function defined here
13+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
14+
help: change the type of the numeric literal from `u32` to `i32`
15+
|
16+
LL | v.push(1i32);
17+
| ~~~
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// run-rustfix
2+
fn bar(_: Vec<i32>) {}
3+
fn baz(_: &impl std::any::Any) {}
4+
fn main() {
5+
let v = vec![1, 2, 3, 4, 5];
6+
let mut foo = vec![];
7+
baz(&foo);
8+
for i in &v {
9+
foo.push(*i);
10+
}
11+
baz(&foo);
12+
bar(foo); //~ ERROR E0308
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// run-rustfix
2+
fn bar(_: Vec<i32>) {}
3+
fn baz(_: &impl std::any::Any) {}
4+
fn main() {
5+
let v = vec![1, 2, 3, 4, 5];
6+
let mut foo = vec![];
7+
baz(&foo);
8+
for i in &v {
9+
foo.push(i);
10+
}
11+
baz(&foo);
12+
bar(foo); //~ ERROR E0308
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/point-at-inference.rs:12:9
3+
|
4+
LL | foo.push(i);
5+
| - this is of type `&{integer}`, which causes `foo` to be inferred as `Vec<&{integer}>`
6+
...
7+
LL | bar(foo);
8+
| --- ^^^ expected `i32`, found `&{integer}`
9+
| |
10+
| arguments to this function are incorrect
11+
|
12+
= note: expected struct `Vec<i32>`
13+
found struct `Vec<&{integer}>`
14+
note: function defined here
15+
--> $DIR/point-at-inference.rs:2:4
16+
|
17+
LL | fn bar(_: Vec<i32>) {}
18+
| ^^^ -----------
19+
help: consider dereferencing the borrow
20+
|
21+
LL | foo.push(*i);
22+
| +
23+
24+
error: aborting due to previous error
25+
26+
For more information about this error, try `rustc --explain E0308`.

‎src/test/ui/typeck/issue-105946.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn digit() -> str {
2+
return {};
3+
//~^ ERROR: mismatched types [E0308]
4+
}
5+
fn main() {
6+
let [_y..] = [box 1, box 2];
7+
//~^ ERROR: cannot find value `_y` in this scope [E0425]
8+
//~| ERROR: `X..` patterns in slices are experimental [E0658]
9+
//~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658]
10+
//~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658]
11+
//~| ERROR: pattern requires 1 element but array has 2 [E0527]
12+
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error[E0425]: cannot find value `_y` in this scope
2+
--> $DIR/issue-105946.rs:6:10
3+
|
4+
LL | let [_y..] = [box 1, box 2];
5+
| ^^ not found in this scope
6+
7+
error[E0658]: `X..` patterns in slices are experimental
8+
--> $DIR/issue-105946.rs:6:10
9+
|
10+
LL | let [_y..] = [box 1, box 2];
11+
| ^^^^
12+
|
13+
= note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
14+
= help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
15+
16+
error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
17+
--> $DIR/issue-105946.rs:6:19
18+
|
19+
LL | let [_y..] = [box 1, box 2];
20+
| ^^^^^
21+
|
22+
= note: see issue #49733 <https://github.com/rust-lang/rust/issues/49733> for more information
23+
= help: add `#![feature(box_syntax)]` to the crate attributes to enable
24+
25+
error[E0658]: box expression syntax is experimental; you can call `Box::new` instead
26+
--> $DIR/issue-105946.rs:6:26
27+
|
28+
LL | let [_y..] = [box 1, box 2];
29+
| ^^^^^
30+
|
31+
= note: see issue #49733 <https://github.com/rust-lang/rust/issues/49733> for more information
32+
= help: add `#![feature(box_syntax)]` to the crate attributes to enable
33+
34+
error[E0308]: mismatched types
35+
--> $DIR/issue-105946.rs:2:10
36+
|
37+
LL | return {};
38+
| ^^ expected `str`, found `()`
39+
40+
error[E0527]: pattern requires 1 element but array has 2
41+
--> $DIR/issue-105946.rs:6:9
42+
|
43+
LL | let [_y..] = [box 1, box 2];
44+
| ^^^^^^ expected 2 elements
45+
46+
error: aborting due to 6 previous errors
47+
48+
Some errors have detailed explanations: E0308, E0425, E0527, E0658.
49+
For more information about an error, try `rustc --explain E0308`.

‎src/tools/error_index_generator/book_config.toml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ src = ""
77
git-repository-url = "https://github.com/rust-lang/rust/"
88
additional-css = ["error-index.css"]
99
additional-js = ["error-index.js"]
10+
input-404 = ""
1011

1112
[output.html.search]
1213
enable = true

‎src/tools/error_index_generator/main.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,7 @@ fn add_rust_attribute_on_codeblock(explanation: &str) -> String {
9898

9999
fn render_html(output_path: &Path) -> Result<(), Box<dyn Error>> {
100100
let mut introduction = format!(
101-
"<script src='redirect.js'></script>
102-
# Rust error codes index
101+
"# Rust error codes index
103102
104103
This page lists all the error codes emitted by the Rust compiler.
105104
@@ -149,7 +148,12 @@ This page lists all the error codes emitted by the Rust compiler.
149148
book.book.sections.push(BookItem::Chapter(chapter));
150149
book.build()?;
151150

152-
// We can't put this content into another file, otherwise `mbdbook` will also put it into the
151+
// The error-index used to be generated manually (without mdbook), and the
152+
// index was located at the top level. Now that it is generated with
153+
// mdbook, error-index.html has moved to error_codes/error-index.html.
154+
// This adds a redirect so that old links go to the new location.
155+
//
156+
// We can't put this content into another file, otherwise `mdbook` will also put it into the
153157
// output directory, making a duplicate.
154158
fs::write(
155159
output_path.join("error-index.html"),
@@ -163,14 +167,10 @@ This page lists all the error codes emitted by the Rust compiler.
163167
</head>
164168
<body>
165169
<div>If you are not automatically redirected to the error code index, please <a id="index-link" href="./error_codes/error-index.html">here</a>.
166-
<script>document.getElementById("index-link").click()</script>
167170
</body>
168171
</html>"#,
169172
)?;
170173

171-
// No need for a 404 file, it's already handled by the server.
172-
fs::remove_file(output_path.join("error_codes/404.html"))?;
173-
174174
Ok(())
175175
}
176176

‎src/tools/error_index_generator/redirect.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,10 @@
33
let code = window.location.hash.replace(/^#/, '');
44
// We have to make sure this pattern matches to avoid inadvertently creating an
55
// open redirect.
6-
if (!/^E[0-9]+$/.test(code)) {
6+
if (/^E[0-9]+$/.test(code)) {
7+
window.location.replace('./error_codes/' + code + '.html');
78
return;
89
}
9-
if (window.location.pathname.indexOf("/error_codes/") !== -1) {
10-
// We're not at the top level, so we don't prepend with "./error_codes/".
11-
window.location = './' + code + '.html';
12-
} else {
13-
window.location = './error_codes/' + code + '.html';
14-
}
1510
}
11+
window.location.replace('./error_codes/error-index.html');
1612
})()

0 commit comments

Comments
 (0)
Please sign in to comment.