Skip to content

Commit b0935b1

Browse files
Rollup merge of #98497 - compiler-errors:span-inference-note, r=lcnr
Improve some inference diagnostics - Properly point out point location where "type must be known at this point", or else omit the note if it's not associated with a useful span. - Fix up some type ambiguity diagnostics, errors shouldn't say "cannot infer type for reference `&'a ()`" when the given type has no inference variables.
2 parents bda659e + 6711313 commit b0935b1

File tree

52 files changed

+195
-135
lines changed

Some content is hidden

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

52 files changed

+195
-135
lines changed

Diff for: compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
313313
pub fn emit_inference_failure_err(
314314
&self,
315315
body_id: Option<hir::BodyId>,
316-
span: Span,
316+
failure_span: Span,
317317
arg: GenericArg<'tcx>,
318318
// FIXME(#94483): Either use this or remove it.
319319
_impl_candidates: Vec<ty::TraitRef<'tcx>>,
320320
error_code: TypeAnnotationNeeded,
321+
should_label_span: bool,
321322
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
322323
let arg = self.resolve_vars_if_possible(arg);
323324
let arg_data = self.extract_inference_diagnostics_data(arg, None);
@@ -326,7 +327,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
326327
// If we don't have any typeck results we're outside
327328
// of a body, so we won't be able to get better info
328329
// here.
329-
return self.bad_inference_failure_err(span, arg_data, error_code);
330+
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
330331
};
331332
let typeck_results = typeck_results.borrow();
332333
let typeck_results = &typeck_results;
@@ -338,7 +339,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
338339
}
339340

340341
let Some(InferSource { span, kind }) = local_visitor.infer_source else {
341-
return self.bad_inference_failure_err(span, arg_data, error_code)
342+
return self.bad_inference_failure_err(failure_span, arg_data, error_code)
342343
};
343344

344345
let error_code = error_code.into();
@@ -347,6 +348,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
347348
&format!("type annotations needed{}", kind.ty_msg(self)),
348349
error_code,
349350
);
351+
352+
if should_label_span && !failure_span.overlaps(span) {
353+
err.span_label(failure_span, "type must be known at this point");
354+
}
355+
350356
match kind {
351357
InferSourceKind::LetBinding { insert_span, pattern_name, ty } => {
352358
let suggestion_msg = if let Some(name) = pattern_name {

Diff for: compiler/rustc_middle/src/ty/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -914,9 +914,17 @@ impl<'tcx> Term<'tcx> {
914914
pub fn ty(&self) -> Option<Ty<'tcx>> {
915915
if let Term::Ty(ty) = self { Some(*ty) } else { None }
916916
}
917+
917918
pub fn ct(&self) -> Option<Const<'tcx>> {
918919
if let Term::Const(c) = self { Some(*c) } else { None }
919920
}
921+
922+
pub fn into_arg(self) -> GenericArg<'tcx> {
923+
match self {
924+
Term::Ty(ty) => ty.into(),
925+
Term::Const(c) => c.into(),
926+
}
927+
}
920928
}
921929

922930
/// This kind of predicate has no *direct* correspondent in the

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+59-40
Original file line numberDiff line numberDiff line change
@@ -1958,26 +1958,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
19581958
if predicate.references_error() {
19591959
return;
19601960
}
1961-
// Typically, this ambiguity should only happen if
1962-
// there are unresolved type inference variables
1963-
// (otherwise it would suggest a coherence
1964-
// failure). But given #21974 that is not necessarily
1965-
// the case -- we can have multiple where clauses that
1966-
// are only distinguished by a region, which results
1967-
// in an ambiguity even when all types are fully
1968-
// known, since we don't dispatch based on region
1969-
// relationships.
1970-
1971-
// Pick the first substitution that still contains inference variables as the one
1972-
// we're going to emit an error for. If there are none (see above), fall back to
1973-
// the substitution for `Self`.
1974-
let subst = {
1975-
let substs = data.trait_ref.substs;
1976-
substs
1977-
.iter()
1978-
.find(|s| s.has_infer_types_or_consts())
1979-
.unwrap_or_else(|| substs[0])
1980-
};
19811961

19821962
// This is kind of a hack: it frequently happens that some earlier
19831963
// error prevents types from being fully inferred, and then we get
@@ -1999,27 +1979,54 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
19991979
self.emit_inference_failure_err(
20001980
body_id,
20011981
span,
2002-
subst,
1982+
trait_ref.self_ty().skip_binder().into(),
20031983
vec![],
20041984
ErrorCode::E0282,
1985+
false,
20051986
)
20061987
.emit();
20071988
}
20081989
return;
20091990
}
20101991

2011-
let impl_candidates = self
2012-
.find_similar_impl_candidates(trait_ref)
2013-
.into_iter()
2014-
.map(|candidate| candidate.trait_ref)
2015-
.collect();
2016-
let mut err = self.emit_inference_failure_err(
2017-
body_id,
2018-
span,
2019-
subst,
2020-
impl_candidates,
2021-
ErrorCode::E0283,
2022-
);
1992+
// Typically, this ambiguity should only happen if
1993+
// there are unresolved type inference variables
1994+
// (otherwise it would suggest a coherence
1995+
// failure). But given #21974 that is not necessarily
1996+
// the case -- we can have multiple where clauses that
1997+
// are only distinguished by a region, which results
1998+
// in an ambiguity even when all types are fully
1999+
// known, since we don't dispatch based on region
2000+
// relationships.
2001+
2002+
// Pick the first substitution that still contains inference variables as the one
2003+
// we're going to emit an error for. If there are none (see above), fall back to
2004+
// a more general error.
2005+
let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts());
2006+
2007+
let mut err = if let Some(subst) = subst {
2008+
let impl_candidates = self
2009+
.find_similar_impl_candidates(trait_ref)
2010+
.into_iter()
2011+
.map(|candidate| candidate.trait_ref)
2012+
.collect();
2013+
self.emit_inference_failure_err(
2014+
body_id,
2015+
span,
2016+
subst,
2017+
impl_candidates,
2018+
ErrorCode::E0283,
2019+
true,
2020+
)
2021+
} else {
2022+
struct_span_err!(
2023+
self.tcx.sess,
2024+
span,
2025+
E0283,
2026+
"type annotations needed: cannot satisfy `{}`",
2027+
predicate,
2028+
)
2029+
};
20232030

20242031
let obligation = Obligation::new(
20252032
obligation.cause.clone(),
@@ -2110,7 +2117,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
21102117
return;
21112118
}
21122119

2113-
self.emit_inference_failure_err(body_id, span, arg, vec![], ErrorCode::E0282)
2120+
self.emit_inference_failure_err(body_id, span, arg, vec![], ErrorCode::E0282, false)
21142121
}
21152122

21162123
ty::PredicateKind::Subtype(data) => {
@@ -2124,26 +2131,38 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
21242131
let SubtypePredicate { a_is_expected: _, a, b } = data;
21252132
// both must be type variables, or the other would've been instantiated
21262133
assert!(a.is_ty_var() && b.is_ty_var());
2127-
self.emit_inference_failure_err(body_id, span, a.into(), vec![], ErrorCode::E0282)
2134+
self.emit_inference_failure_err(
2135+
body_id,
2136+
span,
2137+
a.into(),
2138+
vec![],
2139+
ErrorCode::E0282,
2140+
true,
2141+
)
21282142
}
21292143
ty::PredicateKind::Projection(data) => {
2130-
let self_ty = data.projection_ty.self_ty();
2131-
let term = data.term;
21322144
if predicate.references_error() || self.is_tainted_by_errors() {
21332145
return;
21342146
}
2135-
if self_ty.needs_infer() && term.needs_infer() {
2136-
// We do this for the `foo.collect()?` case to produce a suggestion.
2147+
let subst = data
2148+
.projection_ty
2149+
.substs
2150+
.iter()
2151+
.chain(Some(data.term.into_arg()))
2152+
.find(|g| g.has_infer_types_or_consts());
2153+
if let Some(subst) = subst {
21372154
let mut err = self.emit_inference_failure_err(
21382155
body_id,
21392156
span,
2140-
self_ty.into(),
2157+
subst,
21412158
vec![],
21422159
ErrorCode::E0284,
2160+
true,
21432161
);
21442162
err.note(&format!("cannot satisfy `{}`", predicate));
21452163
err
21462164
} else {
2165+
// If we can't find a substitution, just print a generic error
21472166
let mut err = struct_span_err!(
21482167
self.tcx.sess,
21492168
span,

Diff for: compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1538,9 +1538,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15381538
ty
15391539
} else {
15401540
if !self.is_tainted_by_errors() {
1541-
self.emit_inference_failure_err((**self).body_id, sp, ty.into(), vec![], E0282)
1542-
.note("type must be known at this point")
1543-
.emit();
1541+
self.emit_inference_failure_err(
1542+
(**self).body_id,
1543+
sp,
1544+
ty.into(),
1545+
vec![],
1546+
E0282,
1547+
true,
1548+
)
1549+
.emit();
15441550
}
15451551
let err = self.tcx.ty_error();
15461552
self.demand_suptype(sp, err, ty);

Diff for: compiler/rustc_typeck/src/check/writeback.rs

+2
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
694694
t.into(),
695695
vec![],
696696
E0282,
697+
false,
697698
)
698699
.emit();
699700
}
@@ -708,6 +709,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
708709
c.into(),
709710
vec![],
710711
E0282,
712+
false,
711713
)
712714
.emit();
713715
}

Diff for: src/test/ui/array-slice-vec/infer_array_len.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ error[E0282]: type annotations needed
44
LL | let [_, _] = a.into();
55
| ^^^^^^
66
|
7-
= note: type must be known at this point
87
help: consider giving this pattern a type
98
|
109
LL | let [_, _]: _ = a.into();

Diff for: src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ error[E0282]: type annotations needed
2727
|
2828
LL | [] => {}
2929
| ^^ cannot infer type
30-
|
31-
= note: type must be known at this point
3230

3331
error: aborting due to 5 previous errors
3432

Diff for: src/test/ui/cast/issue-85586.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ error[E0282]: type annotations needed
33
|
44
LL | let b = (a + 1) as usize;
55
| ^^^^^^^ cannot infer type
6-
|
7-
= note: type must be known at this point
86

97
error: aborting due to previous error
108

Diff for: src/test/ui/coherence/coherence-overlap-trait-alias.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0283]: type annotations needed
1+
error[E0283]: type annotations needed: cannot satisfy `u32: C`
22
--> $DIR/coherence-overlap-trait-alias.rs:15:6
33
|
44
LL | impl C for u32 {}
5-
| ^ cannot infer type for type `u32`
5+
| ^
66
|
77
note: multiple `impl`s satisfying `u32: C` found
88
--> $DIR/coherence-overlap-trait-alias.rs:14:1

Diff for: src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0283]: type annotations needed for `Mask<_, LANES>`
22
--> $DIR/issue-91614.rs:6:9
33
|
44
LL | let y = Mask::<_, _>::splat(false);
5-
| ^
5+
| ^ ------------------- type must be known at this point
66
|
77
= note: cannot satisfy `_: MaskElement`
88
note: required by a bound in `Mask::<T, LANES>::splat`

Diff for: src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,19 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
3434
= help: const parameters may only be used as standalone arguments, i.e. `J`
3535
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
3636

37-
error[E0283]: type annotations needed
37+
error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
3838
--> $DIR/issue-72787.rs:21:26
3939
|
4040
LL | IsLessOrEqual<I, 8>: True,
41-
| ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
41+
| ^^^^
4242
|
4343
= note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
4444

45-
error[E0283]: type annotations needed
45+
error[E0283]: type annotations needed: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
4646
--> $DIR/issue-72787.rs:21:26
4747
|
4848
LL | IsLessOrEqual<I, 8>: True,
49-
| ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
49+
| ^^^^
5050
|
5151
= note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
5252

Diff for: src/test/ui/const-generics/generic_const_exprs/issue-72787.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ struct S<const I: u32, const J: u32>;
1919
impl<const I: u32, const J: u32> S<I, J>
2020
where
2121
IsLessOrEqual<I, 8>: True,
22-
//[min]~^ Error type annotations needed [E0283]
23-
//[min]~| Error type annotations needed [E0283]
22+
//[min]~^ Error type annotations needed
23+
//[min]~| Error type annotations needed
2424
IsLessOrEqual<J, 8>: True,
2525
IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
2626
//[min]~^ Error generic parameters may not be used in const operations

Diff for: src/test/ui/impl-trait/hidden-type-is-opaque-2.stderr

-4
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@ error[E0282]: type annotations needed
33
|
44
LL | cont.reify_as();
55
| ^^^^ cannot infer type
6-
|
7-
= note: type must be known at this point
86

97
error[E0282]: type annotations needed
108
--> $DIR/hidden-type-is-opaque-2.rs:18:9
119
|
1210
LL | cont.reify_as();
1311
| ^^^^ cannot infer type
14-
|
15-
= note: type must be known at this point
1612

1713
error: aborting due to 2 previous errors
1814

Diff for: src/test/ui/inference/cannot-infer-partial-try-return.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ error[E0282]: type annotations needed for `Result<(), QualifiedError<_>>`
33
|
44
LL | let x = || -> Result<_, QualifiedError<_>> {
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
LL |
7+
LL | infallible()?;
8+
| ------------- type must be known at this point
69
|
710
help: try giving this closure an explicit return type
811
|

Diff for: src/test/ui/inference/erase-type-params-in-label.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0283]: type annotations needed for `Foo<i32, &str, W, Z>`
22
--> $DIR/erase-type-params-in-label.rs:2:9
33
|
44
LL | let foo = foo(1, "");
5-
| ^^^
5+
| ^^^ --- type must be known at this point
66
|
77
= note: cannot satisfy `_: Default`
88
note: required by a bound in `foo`
@@ -23,7 +23,7 @@ error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
2323
--> $DIR/erase-type-params-in-label.rs:5:9
2424
|
2525
LL | let bar = bar(1, "");
26-
| ^^^
26+
| ^^^ --- type must be known at this point
2727
|
2828
= note: cannot satisfy `_: Default`
2929
note: required by a bound in `bar`

Diff for: src/test/ui/inference/issue-72616.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error[E0283]: type annotations needed
22
--> $DIR/issue-72616.rs:20:37
33
|
44
LL | if String::from("a") == "a".try_into().unwrap() {}
5-
| ^^^^^^^^
5+
| -- ^^^^^^^^
6+
| |
7+
| type must be known at this point
68
|
79
= note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate:
810
- impl PartialEq for String;

Diff for: src/test/ui/inference/issue-72690.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ error[E0283]: type annotations needed for `&T`
5555
--> $DIR/issue-72690.rs:17:9
5656
|
5757
LL | let _ = "x".as_ref();
58-
| ^
58+
| ^ ------ type must be known at this point
5959
|
6060
= note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`:
6161
- impl AsRef<OsStr> for str;

0 commit comments

Comments
 (0)