Skip to content

Handle associated types in const context #70056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,18 +639,22 @@ impl<'hir> Map<'hir> {
/// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
/// Used exclusively for diagnostics, to avoid suggestion function calls.
pub fn is_const_context(&self, hir_id: HirId) -> bool {
let parent_id = self.get_parent_item(hir_id);
match self.get(parent_id) {
Node::Item(&Item { kind: ItemKind::Const(..), .. })
| Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. })
| Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. })
| Node::AnonConst(_)
| Node::Item(&Item { kind: ItemKind::Static(..), .. }) => true,
Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => {
sig.header.constness == Constness::Const
for (_, node) in self.parent_iter(hir_id) {
match node {
Node::Item(&Item { kind: ItemKind::Const(..), .. })
| Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. })
| Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. })
| Node::AnonConst(_)
| Node::Item(&Item { kind: ItemKind::Static(..), .. }) => return true,
Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => {
if sig.header.constness == Constness::Const {
return true;
}
}
_ => {}
}
_ => false,
}
false
}

/// Whether `hir_id` corresponds to a `mod` or a crate.
Expand Down
1 change: 1 addition & 0 deletions src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ rustc_queries! {
desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
}

query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
cache_on_disk_if { key.is_local() }
load_cached(tcx, id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
ty::Projection(projection) => (false, Some(projection)),
_ => return,
};
if self.tcx.hir().is_const_context(body_id) {
err.note(
"associated types cannot be referenced in `const` contexts, \
like the length of an array",
);
return;
}

let suggest_restriction =
|generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
Expand Down
46 changes: 23 additions & 23 deletions src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,11 +598,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
checked_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>,
) -> bool {
if self.tcx.hir().is_const_context(expr.hir_id) {
// Shouldn't suggest `.into()` on `const`s.
// FIXME(estebank): modify once we decide to suggest `as` casts
return false;
}
// Shouldn't suggest `.into()` on `const`s.
// FIXME(estebank): modify once we decide to suggest `as` casts
let is_const_context = self.tcx.hir().is_const_context(expr.hir_id);
if self.tcx.sess.source_map().is_imported(expr.span) {
// Ignore if span is from within a macro.
return false;
Expand Down Expand Up @@ -728,24 +726,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let suggest_to_change_suffix_or_into =
|err: &mut DiagnosticBuilder<'_>, is_fallible: bool| {
let into_sugg = into_suggestion.clone();
err.span_suggestion(
expr.span,
if literal_is_ty_suffixed(expr) {
&lit_msg
} else if is_fallible {
&try_msg
} else {
&msg
},
if literal_is_ty_suffixed(expr) {
suffix_suggestion.clone()
} else if is_fallible {
try_into_suggestion
} else {
into_sugg
},
Applicability::MachineApplicable,
);
if !is_const_context || literal_is_ty_suffixed(expr) {
err.span_suggestion(
expr.span,
if literal_is_ty_suffixed(expr) {
&lit_msg
} else if is_fallible {
&try_msg
} else {
&msg
},
if literal_is_ty_suffixed(expr) {
suffix_suggestion.clone()
} else if is_fallible {
try_into_suggestion
} else {
into_sugg
},
Applicability::MachineApplicable,
);
}
};

match (&expected_ty.kind, &checked_ty.kind) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ LL | const Y: usize;
LL | let _array = [4; <A as Foo>::Y];
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
|
help: consider further restricting this bound with `+ Foo`
--> $DIR/associated-const-type-parameter-arrays-2.rs:15:16
|
LL | pub fn test<A: Foo, B: Foo>() {
| ^^^
= note: associated types cannot be referenced in `const` contexts, like the length of an array

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ LL | const Y: usize;
LL | let _array: [u32; <A as Foo>::Y];
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
|
help: consider further restricting this bound with `+ Foo`
--> $DIR/associated-const-type-parameter-arrays.rs:15:16
|
LL | pub fn test<A: Foo, B: Foo>() {
| ^^^
= note: associated types cannot be referenced in `const` contexts, like the length of an array

error: aborting due to previous error

Expand Down
18 changes: 0 additions & 18 deletions src/test/ui/consts/const-integer-bool-ops.rs
Original file line number Diff line number Diff line change
@@ -1,76 +1,58 @@
const X: usize = 42 && 39;
//~^ ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `usize`, found `bool`
const ARR: [i32; X] = [99; 34];
//~^ ERROR evaluation of constant value failed

const X1: usize = 42 || 39;
//~^ ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `usize`, found `bool`
const ARR1: [i32; X1] = [99; 47];
//~^ ERROR evaluation of constant value failed

const X2: usize = -42 || -39;
//~^ ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `usize`, found `bool`
const ARR2: [i32; X2] = [99; 18446744073709551607];
//~^ ERROR evaluation of constant value failed

const X3: usize = -42 && -39;
//~^ ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `bool`, found integer
//~| ERROR mismatched types
//~| expected `usize`, found `bool`
const ARR3: [i32; X3] = [99; 6];
//~^ ERROR evaluation of constant value failed

const Y: usize = 42.0 == 42.0;
//~^ ERROR mismatched types
//~| expected `usize`, found `bool`
const ARRR: [i32; Y] = [99; 1];
//~^ ERROR evaluation of constant value failed

const Y1: usize = 42.0 >= 42.0;
//~^ ERROR mismatched types
//~| expected `usize`, found `bool`
const ARRR1: [i32; Y1] = [99; 1];
//~^ ERROR evaluation of constant value failed

const Y2: usize = 42.0 <= 42.0;
//~^ ERROR mismatched types
//~| expected `usize`, found `bool`
const ARRR2: [i32; Y2] = [99; 1];
//~^ ERROR evaluation of constant value failed

const Y3: usize = 42.0 > 42.0;
//~^ ERROR mismatched types
//~| expected `usize`, found `bool`
const ARRR3: [i32; Y3] = [99; 0];
//~^ ERROR evaluation of constant value failed

const Y4: usize = 42.0 < 42.0;
//~^ ERROR mismatched types
//~| expected `usize`, found `bool`
const ARRR4: [i32; Y4] = [99; 0];
//~^ ERROR evaluation of constant value failed

const Y5: usize = 42.0 != 42.0;
//~^ ERROR mismatched types
//~| expected `usize`, found `bool`
const ARRR5: [i32; Y5] = [99; 0];
//~^ ERROR evaluation of constant value failed

Expand Down
50 changes: 25 additions & 25 deletions src/test/ui/consts/const-integer-bool-ops.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,151 +17,151 @@ LL | const X: usize = 42 && 39;
| ^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:8:18
--> $DIR/const-integer-bool-ops.rs:5:18
|
LL | const ARR: [i32; X] = [99; 34];
| ^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:11:19
--> $DIR/const-integer-bool-ops.rs:8:19
|
LL | const X1: usize = 42 || 39;
| ^^ expected `bool`, found integer

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:11:25
--> $DIR/const-integer-bool-ops.rs:8:25
|
LL | const X1: usize = 42 || 39;
| ^^ expected `bool`, found integer

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:11:19
--> $DIR/const-integer-bool-ops.rs:8:19
|
LL | const X1: usize = 42 || 39;
| ^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:18:19
--> $DIR/const-integer-bool-ops.rs:12:19
|
LL | const ARR1: [i32; X1] = [99; 47];
| ^^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:21:19
--> $DIR/const-integer-bool-ops.rs:15:19
|
LL | const X2: usize = -42 || -39;
| ^^^ expected `bool`, found integer

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:21:26
--> $DIR/const-integer-bool-ops.rs:15:26
|
LL | const X2: usize = -42 || -39;
| ^^^ expected `bool`, found integer

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:21:19
--> $DIR/const-integer-bool-ops.rs:15:19
|
LL | const X2: usize = -42 || -39;
| ^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:28:19
--> $DIR/const-integer-bool-ops.rs:19:19
|
LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
| ^^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:31:19
--> $DIR/const-integer-bool-ops.rs:22:19
|
LL | const X3: usize = -42 && -39;
| ^^^ expected `bool`, found integer

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:31:26
--> $DIR/const-integer-bool-ops.rs:22:26
|
LL | const X3: usize = -42 && -39;
| ^^^ expected `bool`, found integer

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:31:19
--> $DIR/const-integer-bool-ops.rs:22:19
|
LL | const X3: usize = -42 && -39;
| ^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:38:19
--> $DIR/const-integer-bool-ops.rs:26:19
|
LL | const ARR3: [i32; X3] = [99; 6];
| ^^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:41:18
--> $DIR/const-integer-bool-ops.rs:29:18
|
LL | const Y: usize = 42.0 == 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:44:19
--> $DIR/const-integer-bool-ops.rs:31:19
|
LL | const ARRR: [i32; Y] = [99; 1];
| ^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:47:19
--> $DIR/const-integer-bool-ops.rs:34:19
|
LL | const Y1: usize = 42.0 >= 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:50:20
--> $DIR/const-integer-bool-ops.rs:36:20
|
LL | const ARRR1: [i32; Y1] = [99; 1];
| ^^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:53:19
--> $DIR/const-integer-bool-ops.rs:39:19
|
LL | const Y2: usize = 42.0 <= 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:56:20
--> $DIR/const-integer-bool-ops.rs:41:20
|
LL | const ARRR2: [i32; Y2] = [99; 1];
| ^^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:59:19
--> $DIR/const-integer-bool-ops.rs:44:19
|
LL | const Y3: usize = 42.0 > 42.0;
| ^^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:62:20
--> $DIR/const-integer-bool-ops.rs:46:20
|
LL | const ARRR3: [i32; Y3] = [99; 0];
| ^^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:65:19
--> $DIR/const-integer-bool-ops.rs:49:19
|
LL | const Y4: usize = 42.0 < 42.0;
| ^^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:68:20
--> $DIR/const-integer-bool-ops.rs:51:20
|
LL | const ARRR4: [i32; Y4] = [99; 0];
| ^^ referenced constant has errors

error[E0308]: mismatched types
--> $DIR/const-integer-bool-ops.rs:71:19
--> $DIR/const-integer-bool-ops.rs:54:19
|
LL | const Y5: usize = 42.0 != 42.0;
| ^^^^^^^^^^^^ expected `usize`, found `bool`

error[E0080]: evaluation of constant value failed
--> $DIR/const-integer-bool-ops.rs:74:20
--> $DIR/const-integer-bool-ops.rs:56:20
|
LL | const ARRR5: [i32; Y5] = [99; 0];
| ^^ referenced constant has errors
Expand Down
Loading