Rollup merge of #70319 - lcnr:issue63695, r=eddyb
correctly normalize constants closes #70317 implements https://github.com/rust-lang/rust/issues/70125#issuecomment-602133708 r? eddyb cc @varkor
This commit is contained in:
commit
1154023118
16 changed files with 107 additions and 42 deletions
|
@ -57,7 +57,7 @@ use crate::traits::query::{
|
||||||
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
|
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
|
||||||
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
|
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
|
||||||
};
|
};
|
||||||
use crate::ty::subst::SubstsRef;
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
||||||
|
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::traits::query::{
|
||||||
};
|
};
|
||||||
use crate::ty::query::queries;
|
use crate::ty::query::queries;
|
||||||
use crate::ty::query::QueryDescription;
|
use crate::ty::query::QueryDescription;
|
||||||
use crate::ty::subst::SubstsRef;
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
||||||
|
|
||||||
|
@ -1114,10 +1114,10 @@ rustc_queries! {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
|
/// Do not call this query directly: invoke `normalize_erasing_regions` instead.
|
||||||
query normalize_ty_after_erasing_regions(
|
query normalize_generic_arg_after_erasing_regions(
|
||||||
goal: ParamEnvAnd<'tcx, Ty<'tcx>>
|
goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>
|
||||||
) -> Ty<'tcx> {
|
) -> GenericArg<'tcx> {
|
||||||
desc { "normalizing `{:?}`", goal }
|
desc { "normalizing `{}`", goal.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
query implied_outlives_bounds(
|
query implied_outlives_bounds(
|
||||||
|
|
|
@ -273,6 +273,20 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
|
||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
||||||
|
match c.val {
|
||||||
|
ty::ConstKind::Bound(debruijn, bound_var) if debruijn == self.binder_index => {
|
||||||
|
self.types.insert(
|
||||||
|
bound_var.as_u32(),
|
||||||
|
Symbol::intern(&format!("^{}", bound_var.as_u32())),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
c.super_visit_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||||
match r {
|
match r {
|
||||||
ty::ReLateBound(index, br) if *index == self.binder_index => match br {
|
ty::ReLateBound(index, br) if *index == self.binder_index => match br {
|
||||||
|
|
|
@ -978,17 +978,27 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
|
||||||
// ignore the inputs to a projection, as they may not appear
|
// ignore the inputs to a projection, as they may not appear
|
||||||
// in the normalized form
|
// in the normalized form
|
||||||
if self.just_constrained {
|
if self.just_constrained {
|
||||||
match t.kind {
|
if let ty::Projection(..) | ty::Opaque(..) = t.kind {
|
||||||
ty::Projection(..) | ty::Opaque(..) => {
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
|
||||||
|
// if we are only looking for "constrained" region, we have to
|
||||||
|
// ignore the inputs of an unevaluated const, as they may not appear
|
||||||
|
// in the normalized form
|
||||||
|
if self.just_constrained {
|
||||||
|
if let ty::ConstKind::Unevaluated(..) = c.val {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.super_visit_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
|
||||||
if let ty::ReLateBound(debruijn, br) = *r {
|
if let ty::ReLateBound(debruijn, br) = *r {
|
||||||
if debruijn == self.current_index {
|
if debruijn == self.current_index {
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
//!
|
//!
|
||||||
//! The methods in this file use a `TypeFolder` to recursively process
|
//! The methods in this file use a `TypeFolder` to recursively process
|
||||||
//! contents, invoking the underlying
|
//! contents, invoking the underlying
|
||||||
//! `normalize_ty_after_erasing_regions` query for each type found
|
//! `normalize_generic_arg_after_erasing_regions` query for each type
|
||||||
//! within. (This underlying query is what is cached.)
|
//! or constant found within. (This underlying query is what is cached.)
|
||||||
|
|
||||||
use crate::ty::fold::{TypeFoldable, TypeFolder};
|
use crate::ty::fold::{TypeFoldable, TypeFolder};
|
||||||
use crate::ty::subst::{Subst, SubstsRef};
|
use crate::ty::subst::{Subst, SubstsRef};
|
||||||
|
@ -94,6 +94,12 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
self.tcx.normalize_ty_after_erasing_regions(self.param_env.and(ty))
|
let arg = self.param_env.and(ty.into());
|
||||||
|
self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_ty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||||
|
let arg = self.param_env.and(c.into());
|
||||||
|
self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::mir;
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
use crate::ty::fast_reject::SimplifiedType;
|
use crate::ty::fast_reject::SimplifiedType;
|
||||||
use crate::ty::query::caches::DefaultCacheSelector;
|
use crate::ty::query::caches::DefaultCacheSelector;
|
||||||
use crate::ty::subst::SubstsRef;
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
use crate::ty::{self, Ty, TyCtxt};
|
use crate::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
@ -194,6 +194,17 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Key for GenericArg<'tcx> {
|
||||||
|
type CacheSelector = DefaultCacheSelector;
|
||||||
|
|
||||||
|
fn query_crate(&self) -> CrateNum {
|
||||||
|
LOCAL_CRATE
|
||||||
|
}
|
||||||
|
fn default_span(&self, _: TyCtxt<'_>) -> Span {
|
||||||
|
DUMMY_SP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Key for &'tcx ty::Const<'tcx> {
|
impl<'tcx> Key for &'tcx ty::Const<'tcx> {
|
||||||
type CacheSelector = DefaultCacheSelector;
|
type CacheSelector = DefaultCacheSelector;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ use crate::traits::specialization_graph;
|
||||||
use crate::traits::Clauses;
|
use crate::traits::Clauses;
|
||||||
use crate::traits::{self, Vtable};
|
use crate::traits::{self, Vtable};
|
||||||
use crate::ty::steal::Steal;
|
use crate::ty::steal::Steal;
|
||||||
use crate::ty::subst::SubstsRef;
|
use crate::ty::subst::{GenericArg, SubstsRef};
|
||||||
use crate::ty::util::AlwaysRequiresDrop;
|
use crate::ty::util::AlwaysRequiresDrop;
|
||||||
use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
|
use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
|
||||||
use crate::util::common::ErrorReported;
|
use crate::util::common::ErrorReported;
|
||||||
|
|
|
@ -128,6 +128,14 @@ impl<'tcx> GenericArg<'tcx> {
|
||||||
_ => bug!("expected a type, but found another kind"),
|
_ => bug!("expected a type, but found another kind"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unpack the `GenericArg` as a const when it is known certainly to be a const.
|
||||||
|
pub fn expect_const(self) -> &'tcx ty::Const<'tcx> {
|
||||||
|
match self.unpack() {
|
||||||
|
GenericArgKind::Const(c) => c,
|
||||||
|
_ => bug!("expected a const, but found another kind"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
|
impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
|
||||||
|
|
|
@ -150,7 +150,7 @@ pub struct PerfStats {
|
||||||
/// Total number of values canonicalized queries constructed.
|
/// Total number of values canonicalized queries constructed.
|
||||||
pub queries_canonicalized: AtomicUsize,
|
pub queries_canonicalized: AtomicUsize,
|
||||||
/// Number of times this query is invoked.
|
/// Number of times this query is invoked.
|
||||||
pub normalize_ty_after_erasing_regions: AtomicUsize,
|
pub normalize_generic_arg_after_erasing_regions: AtomicUsize,
|
||||||
/// Number of times this query is invoked.
|
/// Number of times this query is invoked.
|
||||||
pub normalize_projection_ty: AtomicUsize,
|
pub normalize_projection_ty: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
@ -707,8 +707,8 @@ impl Session {
|
||||||
self.perf_stats.queries_canonicalized.load(Ordering::Relaxed)
|
self.perf_stats.queries_canonicalized.load(Ordering::Relaxed)
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"normalize_ty_after_erasing_regions: {}",
|
"normalize_generic_arg_after_erasing_regions: {}",
|
||||||
self.perf_stats.normalize_ty_after_erasing_regions.load(Ordering::Relaxed)
|
self.perf_stats.normalize_generic_arg_after_erasing_regions.load(Ordering::Relaxed)
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"normalize_projection_ty: {}",
|
"normalize_projection_ty: {}",
|
||||||
|
@ -1080,7 +1080,7 @@ fn build_session_(
|
||||||
symbol_hash_time: Lock::new(Duration::from_secs(0)),
|
symbol_hash_time: Lock::new(Duration::from_secs(0)),
|
||||||
decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
|
decode_def_path_tables_time: Lock::new(Duration::from_secs(0)),
|
||||||
queries_canonicalized: AtomicUsize::new(0),
|
queries_canonicalized: AtomicUsize::new(0),
|
||||||
normalize_ty_after_erasing_regions: AtomicUsize::new(0),
|
normalize_generic_arg_after_erasing_regions: AtomicUsize::new(0),
|
||||||
normalize_projection_ty: AtomicUsize::new(0),
|
normalize_projection_ty: AtomicUsize::new(0),
|
||||||
},
|
},
|
||||||
code_stats: Default::default(),
|
code_stats: Default::default(),
|
||||||
|
|
|
@ -387,6 +387,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||||
|
let constant = constant.super_fold_with(self);
|
||||||
constant.eval(self.selcx.tcx(), self.param_env)
|
constant.eval(self.selcx.tcx(), self.param_env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,6 +191,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||||
|
let constant = constant.super_fold_with(self);
|
||||||
constant.eval(self.infcx.tcx, self.param_env)
|
constant.eval(self.infcx.tcx, self.param_env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
use rustc::traits::query::NoSolution;
|
use rustc::traits::query::NoSolution;
|
||||||
use rustc::ty::query::Providers;
|
use rustc::ty::query::Providers;
|
||||||
use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
use rustc::ty::subst::GenericArg;
|
||||||
|
use rustc::ty::{self, ParamEnvAnd, TyCtxt};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_trait_selection::traits::query::normalize::AtExt;
|
use rustc_trait_selection::traits::query::normalize::AtExt;
|
||||||
use rustc_trait_selection::traits::{Normalized, ObligationCause};
|
use rustc_trait_selection::traits::{Normalized, ObligationCause};
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
crate fn provide(p: &mut Providers<'_>) {
|
crate fn provide(p: &mut Providers<'_>) {
|
||||||
*p = Providers { normalize_ty_after_erasing_regions, ..*p };
|
*p = Providers { normalize_generic_arg_after_erasing_regions, ..*p };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normalize_ty_after_erasing_regions<'tcx>(
|
fn normalize_generic_arg_after_erasing_regions<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
goal: ParamEnvAnd<'tcx, Ty<'tcx>>,
|
goal: ParamEnvAnd<'tcx, GenericArg<'tcx>>,
|
||||||
) -> Ty<'tcx> {
|
) -> GenericArg<'tcx> {
|
||||||
debug!("normalize_ty_after_erasing_regions(goal={:#?})", goal);
|
debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal);
|
||||||
|
|
||||||
let ParamEnvAnd { param_env, value } = goal;
|
let ParamEnvAnd { param_env, value } = goal;
|
||||||
tcx.sess.perf_stats.normalize_ty_after_erasing_regions.fetch_add(1, Ordering::Relaxed);
|
tcx.sess.perf_stats.normalize_generic_arg_after_erasing_regions.fetch_add(1, Ordering::Relaxed);
|
||||||
tcx.infer_ctxt().enter(|infcx| {
|
tcx.infer_ctxt().enter(|infcx| {
|
||||||
let cause = ObligationCause::dummy();
|
let cause = ObligationCause::dummy();
|
||||||
match infcx.at(&cause, param_env).normalize(&value) {
|
match infcx.at(&cause, param_env).normalize(&value) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// ignore-tidy-linelength
|
// ignore-tidy-linelength
|
||||||
// ignore-wasm32-bare compiled with panic=abort by default
|
// ignore-wasm32-bare compiled with panic=abort by default
|
||||||
// compile-flags: -Z mir-opt-level=3
|
// compile-flags: -Z mir-opt-level=3
|
||||||
|
// only-64bit FIXME: the mir representation of RawVec depends on ptr size
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -55,7 +56,7 @@ fn main() {
|
||||||
// StorageLive(_2);
|
// StorageLive(_2);
|
||||||
// _2 = Box(std::vec::Vec<u32>);
|
// _2 = Box(std::vec::Vec<u32>);
|
||||||
// _4 = &mut (*_2);
|
// _4 = &mut (*_2);
|
||||||
// ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32>::NEW;
|
// ((*_4).0: alloc::raw_vec::RawVec<u32>) = const ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), undef_mask: UndefMask { blocks: [65535], len: Size { raw: 16 } }, size: Size { raw: 16 }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }: alloc::raw_vec::RawVec::<u32>;
|
||||||
// ((*_4).1: usize) = const 0usize;
|
// ((*_4).1: usize) = const 0usize;
|
||||||
// _1 = move _2;
|
// _1 = move _2;
|
||||||
// StorageDead(_2);
|
// StorageDead(_2);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// build-fail
|
// build-fail
|
||||||
|
//~^ ERROR cycle detected when normalizing `<() as Tr>::A`
|
||||||
|
|
||||||
// Cyclic assoc. const defaults don't error unless *used*
|
// Cyclic assoc. const defaults don't error unless *used*
|
||||||
trait Tr {
|
trait Tr {
|
||||||
const A: u8 = Self::B;
|
const A: u8 = Self::B;
|
||||||
//~^ ERROR cycle detected when const-evaluating + checking `Tr::A`
|
|
||||||
|
|
||||||
const B: u8 = Self::A;
|
const B: u8 = Self::A;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,42 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
|
error[E0391]: cycle detected when normalizing `<() as Tr>::A`
|
||||||
--> $DIR/defaults-cyclic-fail.rs:5:5
|
|
|
||||||
|
note: ...which requires const-evaluating + checking `Tr::A`...
|
||||||
|
--> $DIR/defaults-cyclic-fail.rs:6:5
|
||||||
|
|
|
|
||||||
LL | const A: u8 = Self::B;
|
LL | const A: u8 = Self::B;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
note: ...which requires const-evaluating + checking `Tr::A`...
|
||||||
note: ...which requires const-evaluating `Tr::A`...
|
--> $DIR/defaults-cyclic-fail.rs:6:5
|
||||||
--> $DIR/defaults-cyclic-fail.rs:5:19
|
|
||||||
|
|
|
|
||||||
LL | const A: u8 = Self::B;
|
LL | const A: u8 = Self::B;
|
||||||
| ^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires const-evaluating `Tr::A`...
|
||||||
|
--> $DIR/defaults-cyclic-fail.rs:6:5
|
||||||
|
|
|
||||||
|
LL | const A: u8 = Self::B;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
= note: ...which requires normalizing `<() as Tr>::B`...
|
||||||
|
note: ...which requires const-evaluating + checking `Tr::B`...
|
||||||
|
--> $DIR/defaults-cyclic-fail.rs:8:5
|
||||||
|
|
|
||||||
|
LL | const B: u8 = Self::A;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `Tr::B`...
|
note: ...which requires const-evaluating + checking `Tr::B`...
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:5
|
--> $DIR/defaults-cyclic-fail.rs:8:5
|
||||||
|
|
|
|
||||||
LL | const B: u8 = Self::A;
|
LL | const B: u8 = Self::A;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating `Tr::B`...
|
note: ...which requires const-evaluating `Tr::B`...
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:19
|
--> $DIR/defaults-cyclic-fail.rs:8:5
|
||||||
|
|
|
|
||||||
LL | const B: u8 = Self::A;
|
LL | const B: u8 = Self::A;
|
||||||
| ^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
|
= note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle
|
||||||
note: cycle used when const-evaluating `main`
|
note: cycle used when const-evaluating `main`
|
||||||
--> $DIR/defaults-cyclic-fail.rs:16:16
|
--> $DIR/defaults-cyclic-fail.rs:14:1
|
||||||
|
|
|
|
||||||
LL | assert_eq!(<() as Tr>::A, 0);
|
LL | fn main() {
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ note: ...which requires const-evaluating + checking `std::intrinsics::size_of`..
|
||||||
LL | pub fn size_of<T>() -> usize;
|
LL | pub fn size_of<T>() -> usize;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires computing layout of `Foo`...
|
= note: ...which requires computing layout of `Foo`...
|
||||||
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
|
= note: ...which requires normalizing `[u8; _]`...
|
||||||
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
|
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
|
||||||
note: cycle used when processing `Foo`
|
note: cycle used when processing `Foo`
|
||||||
--> $DIR/const-size_of-cycle.rs:7:1
|
--> $DIR/const-size_of-cycle.rs:7:1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue