Auto merge of #119821 - oli-obk:reveal_all_const_evals, r=lcnr

Always use RevealAll for const eval queries

implements what is described in https://github.com/rust-lang/rust/pull/116803#discussion_r1364089471

Using `UserFacing` for const eval does not make sense anymore, unless we significantly change things like avoiding revealing opaque types.

New tests are copied from https://github.com/rust-lang/rust/pull/101478
This commit is contained in:
bors 2024-01-20 04:57:51 +00:00
commit 5378c1cf07
32 changed files with 362 additions and 107 deletions

View File

@ -225,17 +225,10 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
// see comment in eval_to_allocation_raw_provider for what we're doing here
if key.param_env.reveal() == Reveal::All {
let mut key = key;
key.param_env = key.param_env.with_user_facing();
match tcx.eval_to_const_value_raw(key) {
// try again with reveal all as requested
Err(ErrorHandled::TooGeneric(_)) => {}
// deduplicate calls
other => return other,
}
}
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
// types that are not specified in the opaque type.
assert_eq!(key.param_env.reveal(), Reveal::All);
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
@ -265,24 +258,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
// Because the constant is computed twice (once per value of `Reveal`), we are at risk of
// reporting the same error twice here. To resolve this, we check whether we can evaluate the
// constant in the more restrictive `Reveal::UserFacing`, which most likely already was
// computed. For a large percentage of constants that will already have succeeded. Only
// associated constants of generic functions will fail due to not enough monomorphization
// information being available.
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
// types that are not specified in the opaque type.
// In case we fail in the `UserFacing` variant, we just do the real computation.
if key.param_env.reveal() == Reveal::All {
let mut key = key;
key.param_env = key.param_env.with_user_facing();
match tcx.eval_to_allocation_raw(key) {
// try again with reveal all as requested
Err(ErrorHandled::TooGeneric(_)) => {}
// deduplicate calls
other => return other,
}
}
assert_eq!(key.param_env.reveal(), Reveal::All);
if cfg!(debug_assertions) {
// Make sure we format the instance even if we do not print it.
// This serves as a regression test against an ICE on printing.

View File

@ -145,7 +145,7 @@ pub fn const_eval_global_id(
) -> EvalToConstValueResult<'tcx> {
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries.
let inputs = self.erase_regions(param_env.and(cid));
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
if let Some(span) = span {
// The query doesn't know where it is being invoked, so we need to fix the span.
self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span))
@ -164,7 +164,7 @@ pub fn const_eval_global_id_for_typeck(
) -> EvalToValTreeResult<'tcx> {
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries.
let inputs = self.erase_regions(param_env.and(cid));
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid));
debug!(?inputs);
if let Some(span) = span {
// The query doesn't know where it is being invoked, so we need to fix the span.

View File

@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`.
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
| ^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:27
|

View File

@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `DEFAULT_REF_BA
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:30
|

View File

@ -9,11 +9,6 @@ note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
| ^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:28
|

View File

@ -7,7 +7,6 @@ LL | const X: i32 = 1 / 0;
query stack during panic:
#0 [eval_to_allocation_raw] const-evaluating + checking `X`
#1 [eval_to_const_value_raw] simplifying constant for the type system `X`
#2 [eval_to_const_value_raw] simplifying constant for the type system `X`
#3 [lint_mod] linting top-level module
#4 [analysis] running analysis passes on this crate
#2 [lint_mod] linting top-level module
#3 [analysis] running analysis passes on this crate
end of query stack

View File

@ -7,11 +7,6 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()]
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
--> $DIR/const-size_of-cycle.rs:4:17
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
--> $DIR/const-size_of-cycle.rs:4:17
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...

View File

@ -20,11 +20,17 @@ note: ...which requires const-evaluating + checking `A`...
LL | const A: isize = Foo::B as isize;
| ^^^^^^^^^^^^^^^
= note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}`
--> $DIR/issue-36163.rs:4:9
note: cycle used when collecting item types in top-level module
--> $DIR/issue-36163.rs:1:1
|
LL | B = A,
| ^
LL | / const A: isize = Foo::B as isize;
LL | |
LL | | enum Foo {
LL | | B = A,
LL | | }
LL | |
LL | | fn main() {}
| |____________^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error

View File

@ -7,11 +7,6 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
--> $DIR/issue-44415.rs:6:17
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
--> $DIR/issue-44415.rs:6:17
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `Foo`...

View File

@ -1,15 +1,10 @@
error[E0391]: cycle detected when const-evaluating + checking `FOO`
--> $DIR/recursive-zst-static.rs:10:1
|
LL | static FOO: () = FOO;
| ^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `FOO`...
--> $DIR/recursive-zst-static.rs:10:18
|
LL | static FOO: () = FOO;
| ^^^
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
= note: ...which immediately requires const-evaluating + checking `FOO` again
note: cycle used when linting top-level module
--> $DIR/recursive-zst-static.rs:10:1
|

View File

@ -1,15 +1,10 @@
error[E0391]: cycle detected when const-evaluating + checking `FOO`
--> $DIR/recursive-zst-static.rs:10:1
|
LL | static FOO: () = FOO;
| ^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `FOO`...
--> $DIR/recursive-zst-static.rs:10:18
|
LL | static FOO: () = FOO;
| ^^^
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
= note: ...which immediately requires const-evaluating + checking `FOO` again
note: cycle used when linting top-level module
--> $DIR/recursive-zst-static.rs:10:1
|

View File

@ -5,17 +5,12 @@ LL | pub static mut B: () = unsafe { A = 1; };
| ^^^^^ modifying a static's initial value from another static's initializer
error[E0391]: cycle detected when const-evaluating + checking `C`
--> $DIR/write-to-static-mut-in-static.rs:5:1
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `C`...
--> $DIR/write-to-static-mut-in-static.rs:5:34
|
LL | pub static mut C: u32 = unsafe { C = 1; 0 };
| ^^^^^
= note: ...which again requires const-evaluating + checking `C`, completing the cycle
|
= note: ...which immediately requires const-evaluating + checking `C` again
note: cycle used when linting top-level module
--> $DIR/write-to-static-mut-in-static.rs:1:1
|

View File

@ -0,0 +1,16 @@
//! Check that const eval can use the size of opaque types.
// check-pass
use std::mem;
fn returns_opaque() -> impl Sized {
0u8
}
struct NamedOpaqueType {
data: [mem::MaybeUninit<u8>; size_of_fut(returns_opaque)],
}
const fn size_of_fut<FUT>(x: fn() -> FUT) -> usize {
mem::size_of::<FUT>()
}
fn main() {}

View File

@ -0,0 +1,22 @@
//! Check that array lengths can observe associated types of opaque types
// check-pass
trait MyTrait: Copy {
const ASSOC: usize;
}
impl MyTrait for u8 {
const ASSOC: usize = 32;
}
const fn yeet() -> impl MyTrait {
0u8
}
const fn output<T: MyTrait>(_: T) -> usize {
<T as MyTrait>::ASSOC
}
fn main() {
let x = [0u8; output(yeet())];
println!("{:?}", x);
}

View File

@ -0,0 +1,26 @@
//! check that const eval can observe associated types of opaque types.
// check-pass
trait MyTrait: Copy {
const ASSOC: usize;
}
impl MyTrait for u8 {
const ASSOC: usize = 32;
}
const fn yeet() -> impl MyTrait {
0u8
}
const fn output<T: MyTrait>(_: T) -> usize {
<T as MyTrait>::ASSOC
}
#[repr(usize)]
enum Foo {
Bar = output(yeet()),
}
fn main() {
println!("{}", Foo::Bar as usize);
}

View File

@ -0,0 +1,29 @@
//! This test ensures that we do look at the hidden types of
//! opaque types during const eval in order to obtain the exact type
//! of associated types.
// check-pass
trait MyTrait: Copy {
const ASSOC: usize;
}
impl MyTrait for u8 {
const ASSOC: usize = 32;
}
const fn yeet() -> impl MyTrait {
0u8
}
const fn output<T: MyTrait>(_: T) -> usize {
<T as MyTrait>::ASSOC
}
struct Foo<'a>(&'a ());
const NEED_REVEAL_ALL: usize = output(yeet());
fn promote_div() -> &'static usize {
&(10 / NEED_REVEAL_ALL)
}
fn main() {}

View File

@ -0,0 +1,24 @@
//! Check that pattern matching can observe the hidden type of opaque types.
// check-pass
trait MyTrait: Copy {
const ASSOC: u8;
}
impl MyTrait for () {
const ASSOC: u8 = 0;
}
const fn yeet() -> impl MyTrait {}
const fn output<T: MyTrait>(_: T) -> u8 {
<T as MyTrait>::ASSOC
}
const CT: u8 = output(yeet());
fn main() {
match 0 {
CT => (),
1.. => (),
}
}

View File

@ -0,0 +1,14 @@
// This causes a query cycle due to using `Reveal::All`,
// in #119821 const eval was changed to always use `Reveal::All`
//
// See that PR for more details.
use std::mem::transmute;
fn foo() -> impl Sized {
//~^ ERROR cycle detected when computing type of
unsafe {
transmute::<_, u8>(foo());
}
0u8
}
fn main() {}

View File

@ -0,0 +1,29 @@
error[E0391]: cycle detected when computing type of `foo::{opaque#0}`
--> $DIR/in-defining-scope.rs:6:13
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^
|
note: ...which requires computing type of opaque `foo::{opaque#0}`...
--> $DIR/in-defining-scope.rs:6:13
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^
note: ...which requires type-checking `foo`...
--> $DIR/in-defining-scope.rs:6:1
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing layout of `foo::{opaque#0}`...
= note: ...which requires normalizing `foo::{opaque#0}`...
= note: ...which again requires computing type of `foo::{opaque#0}`, completing the cycle
note: cycle used when checking that `foo::{opaque#0}` is well-formed
--> $DIR/in-defining-scope.rs:6:13
|
LL | fn foo() -> impl Sized {
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0391`.

View File

@ -0,0 +1,12 @@
//! Check that typeck can observe the size of an opaque type.
// check-pass
use std::mem::transmute;
fn foo() -> impl Sized {
0u8
}
fn main() {
unsafe {
transmute::<_, u8>(foo());
}
}

View File

@ -10,11 +10,15 @@ note: ...which requires const-evaluating + checking `X::A::{constant#0}`...
LL | A = X::A as isize,
| ^^^^^^^^^^^^^
= note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle
note: cycle used when simplifying constant for the type system `X::A::{constant#0}`
--> $DIR/issue-23302-1.rs:4:9
note: cycle used when collecting item types in top-level module
--> $DIR/issue-23302-1.rs:3:1
|
LL | A = X::A as isize,
| ^^^^^^^^^^^^^
LL | / enum X {
LL | | A = X::A as isize,
LL | | }
LL | |
LL | | fn main() { }
| |_____________^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error

View File

@ -10,11 +10,16 @@ note: ...which requires const-evaluating + checking `Y::A::{constant#0}`...
LL | A = Y::B as isize,
| ^^^^^^^^^^^^^
= note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle
note: cycle used when simplifying constant for the type system `Y::A::{constant#0}`
--> $DIR/issue-23302-2.rs:4:9
note: cycle used when collecting item types in top-level module
--> $DIR/issue-23302-2.rs:3:1
|
LL | A = Y::B as isize,
| ^^^^^^^^^^^^^
LL | / enum Y {
LL | | A = Y::B as isize,
LL | | B,
LL | | }
LL | |
LL | | fn main() { }
| |_____________^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error

View File

@ -20,11 +20,15 @@ note: ...which requires const-evaluating + checking `B`...
LL | const B: i32 = A;
| ^
= note: ...which again requires simplifying constant for the type system `A`, completing the cycle
note: cycle used when simplifying constant for the type system `A`
note: cycle used when linting top-level module
--> $DIR/issue-23302-3.rs:1:1
|
LL | const A: i32 = B;
| ^^^^^^^^^^^^
LL | / const A: i32 = B;
LL | |
LL | | const B: i32 = A;
LL | |
LL | | fn main() { }
| |_____________^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 1 previous error

View File

@ -1,15 +1,10 @@
error[E0391]: cycle detected when const-evaluating + checking `FOO`
--> $DIR/recursive-static-definition.rs:1:1
|
LL | pub static FOO: u32 = FOO;
| ^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating + checking `FOO`...
--> $DIR/recursive-static-definition.rs:1:23
|
LL | pub static FOO: u32 = FOO;
| ^^^
= note: ...which again requires const-evaluating + checking `FOO`, completing the cycle
|
= note: ...which immediately requires const-evaluating + checking `FOO` again
note: cycle used when linting top-level module
--> $DIR/recursive-static-definition.rs:1:1
|

View File

@ -0,0 +1,18 @@
//! Regression test for revealing associated types through specialization during const eval.
// check-pass
#![feature(specialization)]
//~^ WARNING the feature `specialization` is incomplete and may not be safe to use
trait Foo {
const ASSOC: usize;
}
impl Foo for u32 {
default const ASSOC: usize = 0;
}
fn foo() -> [u8; 0] {
[0; <u32 as Foo>::ASSOC]
}
fn main() {}

View File

@ -0,0 +1,12 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/default-assoc-const.rs:3:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View File

@ -0,0 +1,27 @@
//! Regression test showing that we can access associated types during const eval,
//! even if they rely on specialization.
// check-pass
#![feature(specialization)]
//~^ WARNING the feature `specialization` is incomplete and may not be safe to use
trait Foo {
type Assoc: Trait;
}
impl<T> Foo for Vec<T> {
default type Assoc = u32;
}
trait Trait {
const ASSOC: usize;
}
impl Trait for u32 {
const ASSOC: usize = 0;
}
fn foo() -> [u8; 0] {
[0; <<Vec<u32> as Foo>::Assoc as Trait>::ASSOC]
}
fn main() {}

View File

@ -0,0 +1,12 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/default-assoc-type.rs:4:12
|
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View File

@ -8,5 +8,5 @@ error: the compiler unexpectedly panicked. this is a bug.
query stack during panic:
#0 [eval_to_allocation_raw] const-evaluating + checking `C`
#1 [eval_to_allocation_raw] const-evaluating + checking `C`
#1 [lint_mod] linting top-level module
end of query stack

View File

@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Alph
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|
LL | V3 = Self::V1 {} as u8 + 2,
| ^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
--> $DIR/self-in-enum-definition.rs:5:10
|

View File

@ -0,0 +1,16 @@
//! We evaluate `1 + 2` with `Reveal::All` during typeck, causing
//! us to to get the concrete type of `Bar` while computing it.
//! This again requires type checking `foo`.
#![feature(type_alias_impl_trait)]
type Bar = impl Sized;
//~^ ERROR: cycle
//~| ERROR: cycle
fn foo() -> Bar
where
Bar: Send,
{
[0; 1 + 2]
}
fn main() {}

View File

@ -0,0 +1,50 @@
error[E0391]: cycle detected when computing type of `Bar::{opaque#0}`
--> $DIR/in-where-clause.rs:5:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
|
note: ...which requires computing type of opaque `Bar::{opaque#0}`...
--> $DIR/in-where-clause.rs:5:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
note: ...which requires type-checking `foo`...
--> $DIR/in-where-clause.rs:9:1
|
LL | / fn foo() -> Bar
LL | | where
LL | | Bar: Send,
| |______________^
= note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(<Bar as core::marker::Send>, polarity:Positive), bound_vars: [] }]`...
= note: ...which again requires computing type of `Bar::{opaque#0}`, completing the cycle
note: cycle used when checking that `Bar::{opaque#0}` is well-formed
--> $DIR/in-where-clause.rs:5:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error[E0391]: cycle detected when computing type of opaque `Bar::{opaque#0}`
--> $DIR/in-where-clause.rs:5:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
|
note: ...which requires type-checking `foo`...
--> $DIR/in-where-clause.rs:13:9
|
LL | [0; 1 + 2]
| ^^^^^
= note: ...which requires evaluating trait selection obligation `Bar: core::marker::Send`...
= note: ...which again requires computing type of opaque `Bar::{opaque#0}`, completing the cycle
note: cycle used when computing type of `Bar::{opaque#0}`
--> $DIR/in-where-clause.rs:5:12
|
LL | type Bar = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0391`.