Skip to content

Commit 804c047

Browse files
committed
Load missing type of impl associated constant from trait definition
1 parent b13a71a commit 804c047

File tree

6 files changed

+89
-17
lines changed

6 files changed

+89
-17
lines changed

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,20 @@ fn typeck_with_fallback<'tcx>(
192192
check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params);
193193
} else {
194194
let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty {
195-
Some(fcx.next_ty_var(TypeVariableOrigin {
196-
kind: TypeVariableOriginKind::TypeInference,
197-
span,
198-
}))
195+
if let Some(item) = tcx.opt_associated_item(def_id.into())
196+
&& let ty::AssocKind::Const = item.kind
197+
&& let ty::ImplContainer = item.container
198+
&& let Some(trait_item) = item.trait_item_def_id
199+
{
200+
let args =
201+
tcx.impl_trait_ref(item.container_id(tcx)).unwrap().instantiate_identity().args;
202+
Some(tcx.type_of(trait_item).instantiate(tcx, args))
203+
} else {
204+
Some(fcx.next_ty_var(TypeVariableOrigin {
205+
kind: TypeVariableOriginKind::TypeInference,
206+
span,
207+
}))
208+
}
199209
} else if let Node::AnonConst(_) = node {
200210
match tcx.parent_hir_node(id) {
201211
Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref anon_const), .. })
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//! Test that we compute the right type for associated constants
2+
//! of impls, even if the type is missing. We know it from the trait
3+
//! declaration after all.
4+
5+
trait Range {
6+
const FIRST: u8;
7+
const LAST: u8;
8+
}
9+
10+
struct TwoDigits;
11+
impl Range for TwoDigits {
12+
const FIRST: = 10;
13+
//~^ ERROR: missing type for `const` item
14+
const LAST: u8 = 99;
15+
}
16+
17+
const fn digits(x: u8) -> usize {
18+
match x {
19+
TwoDigits::FIRST..=TwoDigits::LAST => 0,
20+
0..=9 | 100..=255 => panic!(),
21+
}
22+
}
23+
24+
const FOOMP: [(); {
25+
digits(42)
26+
}] = [];
27+
28+
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: missing type for `const` item
2+
--> $DIR/missing_assoc_const_type.rs:12:17
3+
|
4+
LL | const FIRST: = 10;
5+
| ^ help: provide a type for the associated constant: `u8`
6+
7+
error: aborting due to 1 previous error
8+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//! Test that we compute the right type for associated constants
2+
//! of impls, even if the type is missing. We know it from the trait
3+
//! declaration after all.
4+
5+
trait Range {
6+
const FIRST: u8;
7+
const LAST: u8;
8+
}
9+
10+
struct TwoDigits;
11+
impl Range for TwoDigits {
12+
const FIRST: = 10;
13+
//~^ ERROR: missing type
14+
const LAST: u8 = 99;
15+
}
16+
17+
const FOOMP: [(); {
18+
TwoDigits::FIRST as usize
19+
}] = [(); 10];
20+
21+
fn main() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: missing type for `const` item
2+
--> $DIR/missing_assoc_const_type2.rs:12:17
3+
|
4+
LL | const FIRST: = 10;
5+
| ^ help: provide a type for the associated constant: `u8`
6+
7+
error: aborting due to 1 previous error
8+

tests/ui/typeck/typeck_type_placeholder_item.stderr

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,15 @@ help: use type parameters instead
546546
LL | fn fn_test10<T>(&self, _x : T) { }
547547
| +++ ~
548548

549+
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
550+
--> $DIR/typeck_type_placeholder_item.rs:194:14
551+
|
552+
LL | const D: _ = 42;
553+
| ^
554+
| |
555+
| not allowed in type signatures
556+
| help: replace with the correct type: `i32`
557+
549558
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
550559
--> $DIR/typeck_type_placeholder_item.rs:217:31
551560
|
@@ -574,19 +583,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures
574583
--> $DIR/typeck_type_placeholder_item.rs:209:14
575584
|
576585
LL | const D: _ = 42;
577-
| ^
578-
| |
579-
| not allowed in type signatures
580-
| help: replace with the correct type: `i32`
581-
582-
error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
583-
--> $DIR/typeck_type_placeholder_item.rs:194:14
584-
|
585-
LL | const D: _ = 42;
586-
| ^
587-
| |
588-
| not allowed in type signatures
589-
| help: replace with the correct type: `i32`
586+
| ^ not allowed in type signatures
590587

591588
error[E0046]: not all trait items implemented, missing: `F`
592589
--> $DIR/typeck_type_placeholder_item.rs:200:1

0 commit comments

Comments
 (0)