Skip to content

Commit 3702d43

Browse files
committed
correctly handle uninferred consts
1 parent 7c59a81 commit 3702d43

File tree

4 files changed

+89
-5
lines changed

4 files changed

+89
-5
lines changed

Diff for: src/librustc_infer/infer/error_reporting/need_type_info.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,19 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
172172
}
173173

174174
pub enum TypeAnnotationNeeded {
175+
/// ```compile_fail,E0282
176+
/// let x = "hello".chars().rev().collect();
177+
/// ```
175178
E0282,
179+
/// An implementation cannot be chosen unambiguously because of lack of information.
180+
/// ```compile_fail,E0283
181+
/// let _ = Default::default();
182+
/// ```
176183
E0283,
184+
/// ```compile_fail,E0284
185+
/// let mut d: u64 = 2;
186+
/// d = d % 1u32.into();
187+
/// ```
177188
E0284,
178189
}
179190

@@ -261,7 +272,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
261272
printer.name_resolver = Some(Box::new(&getter));
262273
let _ = if let ty::FnDef(..) = ty.kind {
263274
// We don't want the regular output for `fn`s because it includes its path in
264-
// invalid pseduo-syntax, we want the `fn`-pointer output instead.
275+
// invalid pseudo-syntax, we want the `fn`-pointer output instead.
265276
ty.fn_sig(self.tcx).print(printer)
266277
} else {
267278
ty.print(printer)
@@ -518,6 +529,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
518529
err
519530
}
520531

532+
// FIXME(const_generics): We should either try and merge this with `need_type_info_err`
533+
// or improve the errors created here.
534+
//
535+
// Unlike for type inference variables, we don't yet store the origin of const inference variables.
536+
// This is needed for to get a more relevant error span.
537+
pub fn need_type_info_err_const(
538+
&self,
539+
body_id: Option<hir::BodyId>,
540+
span: Span,
541+
ct: &'tcx ty::Const<'tcx>,
542+
error_code: TypeAnnotationNeeded,
543+
) -> DiagnosticBuilder<'tcx> {
544+
let mut local_visitor = FindHirNodeVisitor::new(&self, ct.into(), span);
545+
if let Some(body_id) = body_id {
546+
let expr = self.tcx.hir().expect_expr(body_id.hir_id);
547+
local_visitor.visit_expr(expr);
548+
}
549+
550+
let error_code = error_code.into();
551+
let mut err = self.tcx.sess.struct_span_err_with_code(
552+
local_visitor.target_span,
553+
&format!("type annotations needed"),
554+
error_code,
555+
);
556+
557+
err.note("unable to infer the value of a const parameter");
558+
559+
err
560+
}
561+
521562
/// If the `FnSig` for the method call can be found and type arguments are identified as
522563
/// needed, suggest annotating the call, otherwise point out the resulting type of the call.
523564
fn annotate_method_call(

Diff for: src/librustc_typeck/check/writeback.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -647,13 +647,26 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
647647
Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false }
648648
}
649649

650-
fn report_error(&self, t: Ty<'tcx>) {
650+
fn report_type_error(&self, t: Ty<'tcx>) {
651651
if !self.tcx.sess.has_errors() {
652652
self.infcx
653653
.need_type_info_err(Some(self.body.id()), self.span.to_span(self.tcx), t, E0282)
654654
.emit();
655655
}
656656
}
657+
658+
fn report_const_error(&self, c: &'tcx ty::Const<'tcx>) {
659+
if !self.tcx.sess.has_errors() {
660+
self.infcx
661+
.need_type_info_err_const(
662+
Some(self.body.id()),
663+
self.span.to_span(self.tcx),
664+
c,
665+
E0282,
666+
)
667+
.emit();
668+
}
669+
}
657670
}
658671

659672
impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
@@ -666,7 +679,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
666679
Ok(t) => self.infcx.tcx.erase_regions(&t),
667680
Err(_) => {
668681
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
669-
self.report_error(t);
682+
self.report_type_error(t);
670683
self.replaced_with_error = true;
671684
self.tcx().types.err
672685
}
@@ -683,8 +696,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
683696
Ok(ct) => self.infcx.tcx.erase_regions(&ct),
684697
Err(_) => {
685698
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
686-
// FIXME: we'd like to use `self.report_error`, but it doesn't yet
687-
// accept a &'tcx ty::Const.
699+
self.report_const_error(ct);
688700
self.replaced_with_error = true;
689701
self.tcx().mk_const(ty::Const { val: ty::ConstKind::Error, ty: ct.ty })
690702
}

Diff for: src/test/ui/const-generics/uninferred-consts.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(const_generics)]
2+
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
3+
4+
// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
5+
struct Foo;
6+
impl Foo {
7+
fn foo<const N: usize>(self) {}
8+
}
9+
fn main() {
10+
Foo.foo();
11+
//~^ ERROR type annotations needed
12+
}

Diff for: src/test/ui/const-generics/uninferred-consts.stderr

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
2+
--> $DIR/uninferred-consts.rs:1:12
3+
|
4+
LL | #![feature(const_generics)]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+
9+
error[E0282]: type annotations needed
10+
--> $DIR/uninferred-consts.rs:10:5
11+
|
12+
LL | Foo.foo();
13+
| ^^^^^^^^^
14+
|
15+
= note: unable to infer the value of a const parameter
16+
17+
error: aborting due to previous error; 1 warning emitted
18+
19+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)