Skip to content

Commit 80423d6

Browse files
committed
update TypeFlags to deal with missing ct substs
1 parent 2e13be1 commit 80423d6

File tree

45 files changed

+307
-167
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+307
-167
lines changed

compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
499499
ty::Adt(def, ..) if !def.is_box() => {
500500
// Again, only create type information if full debuginfo is enabled
501501
if cx.sess().opts.debuginfo == DebugInfo::Full
502-
&& !impl_self_ty.needs_subst()
502+
&& !impl_self_ty.needs_subst(cx.tcx)
503503
{
504504
Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
505505
} else {

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1391,7 +1391,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13911391
LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
13921392
LocalRef::Operand(None) => {
13931393
let dst_layout = bx.layout_of(self.monomorphized_place_ty(dst.as_ref()));
1394-
assert!(!dst_layout.ty.has_erasable_regions());
1394+
assert!(!dst_layout.ty.has_erasable_regions(self.cx.tcx()));
13951395
let place = PlaceRef::alloca(bx, dst_layout);
13961396
place.storage_live(bx);
13971397
self.codegen_transmute_into(bx, src, place);

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
216216
let mut allocate_local = |local| {
217217
let decl = &mir.local_decls[local];
218218
let layout = bx.layout_of(fx.monomorphize(decl.ty));
219-
assert!(!layout.ty.has_erasable_regions());
219+
assert!(!layout.ty.has_erasable_regions(cx.tcx()));
220220

221221
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
222222
debug!("alloc: {:?} (return place) -> place", local);

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
479479
{
480480
let needs_canonical_flags = if canonicalize_region_mode.any() {
481481
TypeFlags::NEEDS_INFER |
482-
TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
482+
TypeFlags::HAS_POTENTIAL_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_xxx_FREE_REGIONS`
483483
TypeFlags::HAS_TY_PLACEHOLDER |
484484
TypeFlags::HAS_CT_PLACEHOLDER
485485
} else {

compiler/rustc_infer/src/infer/freshen.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
138138
}
139139

140140
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
141-
if !t.needs_infer() && !t.has_erasable_regions() {
141+
if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
142142
return t;
143143
}
144144

compiler/rustc_lint/src/builtin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
16141614
ConstEquate(..) |
16151615
TypeWellFormedFromEnv(..) => continue,
16161616
};
1617-
if predicate.is_global() {
1617+
if predicate.is_global(cx.tcx) {
16181618
cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
16191619
lint.build(&format!(
16201620
"{} bound {} does not depend on any type \

compiler/rustc_lint/src/noop_method_call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
6262
_ => return,
6363
};
6464
let substs = cx.typeck_results().node_substs(expr.hir_id);
65-
if substs.needs_subst() {
65+
if substs.needs_subst(cx.tcx) {
6666
// We can't resolve on types that require monomorphization, so we don't handle them if
6767
// we need to perfom substitution.
6868
return;

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ pub struct Body<'tcx> {
242242

243243
impl<'tcx> Body<'tcx> {
244244
pub fn new(
245+
tcx: TyCtxt<'tcx>,
245246
source: MirSource<'tcx>,
246247
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
247248
source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
@@ -284,7 +285,7 @@ impl<'tcx> Body<'tcx> {
284285
predecessor_cache: PredecessorCache::new(),
285286
is_cyclic: GraphIsCyclicCache::new(),
286287
};
287-
body.is_polymorphic = body.has_param_types_or_consts();
288+
body.is_polymorphic = body.has_param_types_or_consts(tcx);
288289
body
289290
}
290291

@@ -293,7 +294,10 @@ impl<'tcx> Body<'tcx> {
293294
/// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
294295
/// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
295296
/// crate.
296-
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
297+
pub fn new_cfg_only(
298+
tcx: TyCtxt<'tcx>,
299+
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
300+
) -> Self {
297301
let mut body = Body {
298302
phase: MirPhase::Build,
299303
source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
@@ -311,7 +315,7 @@ impl<'tcx> Body<'tcx> {
311315
predecessor_cache: PredecessorCache::new(),
312316
is_cyclic: GraphIsCyclicCache::new(),
313317
};
314-
body.is_polymorphic = body.has_param_types_or_consts();
318+
body.is_polymorphic = body.has_param_types_or_consts(tcx);
315319
body
316320
}
317321

compiler/rustc_middle/src/ty/consts/kind.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ use rustc_target::abi::Size;
1212

1313
use super::ScalarInt;
1414
/// An unevaluated, potentially generic, constant.
15+
///
16+
/// If `substs_` is `None` it means that this anon const
17+
/// still has its default substs.
18+
///
19+
/// We check for all possible substs in `fn default_anon_const_substs`,
20+
/// so refer to that check for more info.
1521
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
1622
#[derive(Hash, HashStable)]
1723
pub struct Unevaluated<'tcx> {

compiler/rustc_middle/src/ty/erase_regions.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ impl<'tcx> TyCtxt<'tcx> {
2121
T: TypeFoldable<'tcx>,
2222
{
2323
// If there's nothing to erase avoid performing the query at all
24-
if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
24+
if !value
25+
.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_POTENTIAL_FREE_REGIONS)
26+
{
2527
return value;
2628
}
2729
debug!("erase_regions({:?})", value);

compiler/rustc_middle/src/ty/flags.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ impl FlagComputation {
3434
result.flags
3535
}
3636

37+
pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
38+
let mut result = FlagComputation::new();
39+
result.add_unevaluated_const(uv);
40+
result.flags
41+
}
42+
3743
fn add_flags(&mut self, flags: TypeFlags) {
3844
self.flags = self.flags | flags;
3945
}
@@ -91,7 +97,7 @@ impl FlagComputation {
9197
&ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
9298

9399
&ty::Param(_) => {
94-
self.add_flags(TypeFlags::HAS_TY_PARAM);
100+
self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM);
95101
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
96102
}
97103

@@ -288,7 +294,7 @@ impl FlagComputation {
288294
self.add_bound_var(debruijn);
289295
}
290296
ty::ConstKind::Param(_) => {
291-
self.add_flags(TypeFlags::HAS_CT_PARAM);
297+
self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM);
292298
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
293299
}
294300
ty::ConstKind::Placeholder(_) => {
@@ -301,8 +307,12 @@ impl FlagComputation {
301307
}
302308

303309
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
304-
// TODO
305-
self.add_substs(ct.substs_.unwrap());
310+
if let Some(substs) = ct.substs_ {
311+
self.add_substs(substs);
312+
} else {
313+
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
314+
self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS);
315+
}
306316
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
307317
}
308318

compiler/rustc_middle/src/ty/fold.rs

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
7474
self.has_vars_bound_at_or_above(ty::INNERMOST)
7575
}
7676

77+
fn definitely_has_type_flags(&self, tcx: TyCtxt<'tcx>, flags: TypeFlags) -> bool {
78+
self.visit_with(&mut HasTypeFlagsVisitor { tcx: Some(tcx), flags }).break_value()
79+
== Some(FoundFlags)
80+
}
81+
7782
fn has_type_flags(&self, flags: TypeFlags) -> bool {
78-
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
83+
self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value()
84+
== Some(FoundFlags)
7985
}
8086
fn has_projections(&self) -> bool {
8187
self.has_type_flags(TypeFlags::HAS_PROJECTION)
@@ -86,8 +92,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
8692
fn references_error(&self) -> bool {
8793
self.has_type_flags(TypeFlags::HAS_ERROR)
8894
}
89-
fn has_param_types_or_consts(&self) -> bool {
90-
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
95+
fn has_potential_param_types_or_consts(&self) -> bool {
96+
self.has_type_flags(
97+
TypeFlags::HAS_KNOWN_TY_PARAM
98+
| TypeFlags::HAS_KNOWN_CT_PARAM
99+
| TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
100+
)
101+
}
102+
fn has_param_types_or_consts(&self, tcx: TyCtxt<'tcx>) -> bool {
103+
self.definitely_has_type_flags(
104+
tcx,
105+
TypeFlags::HAS_KNOWN_TY_PARAM | TypeFlags::HAS_KNOWN_CT_PARAM,
106+
)
91107
}
92108
fn has_infer_regions(&self) -> bool {
93109
self.has_type_flags(TypeFlags::HAS_RE_INFER)
@@ -108,29 +124,44 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
108124
| TypeFlags::HAS_CT_PLACEHOLDER,
109125
)
110126
}
111-
fn needs_subst(&self) -> bool {
112-
self.has_type_flags(TypeFlags::NEEDS_SUBST)
127+
fn potentially_needs_subst(&self) -> bool {
128+
self.has_type_flags(
129+
TypeFlags::KNOWN_NEEDS_SUBST | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
130+
)
131+
}
132+
fn needs_subst(&self, tcx: TyCtxt<'tcx>) -> bool {
133+
self.definitely_has_type_flags(tcx, TypeFlags::KNOWN_NEEDS_SUBST)
113134
}
114135
/// "Free" regions in this context means that it has any region
115136
/// that is not (a) erased or (b) late-bound.
116-
fn has_free_regions(&self) -> bool {
117-
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
137+
fn has_free_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
138+
self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
118139
}
119140

120141
fn has_erased_regions(&self) -> bool {
121142
self.has_type_flags(TypeFlags::HAS_RE_ERASED)
122143
}
123144

124145
/// True if there are any un-erased free regions.
125-
fn has_erasable_regions(&self) -> bool {
126-
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
146+
fn has_erasable_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
147+
self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
148+
}
149+
150+
/// Indicates whether this value definitely references only 'global'
151+
/// generic parameters that are the same regardless of what fn we are
152+
/// in. This is used for caching.
153+
///
154+
/// Note that this function is pessimistic and may incorrectly return
155+
/// `false`.
156+
fn is_known_global(&self) -> bool {
157+
!self.has_type_flags(TypeFlags::HAS_POTENTIAL_FREE_LOCAL_NAMES)
127158
}
128159

129160
/// Indicates whether this value references only 'global'
130161
/// generic parameters that are the same regardless of what fn we are
131162
/// in. This is used for caching.
132-
fn is_global(&self) -> bool {
133-
!self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
163+
fn is_global(&self, tcx: TyCtxt<'tcx>) -> bool {
164+
!self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES)
134165
}
135166

136167
/// True if there are any late-bound regions
@@ -217,6 +248,10 @@ pub trait TypeVisitor<'tcx>: Sized {
217248
c.super_visit_with(self)
218249
}
219250

251+
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
252+
uv.super_visit_with(self)
253+
}
254+
220255
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
221256
p.super_visit_with(self)
222257
}
@@ -369,7 +404,7 @@ impl<'tcx> TyCtxt<'tcx> {
369404

370405
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
371406
// We're only interested in types involving regions
372-
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
407+
if ty.flags().intersects(TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
373408
ty.super_visit_with(self)
374409
} else {
375410
ControlFlow::CONTINUE
@@ -1078,23 +1113,19 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
10781113
struct FoundFlags;
10791114

10801115
// FIXME: Optimize for checking for infer flags
1081-
struct HasTypeFlagsVisitor {
1116+
struct HasTypeFlagsVisitor<'tcx> {
1117+
tcx: Option<TyCtxt<'tcx>>,
10821118
flags: ty::TypeFlags,
10831119
}
10841120

1085-
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
1121+
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> {
10861122
type BreakTy = FoundFlags;
10871123
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
1088-
// TypeFlagsVisitor must not look into the default anon const substs
1089-
// as that would cause cycle errors, but we do care about them for
1090-
// some flags.
1091-
//
1092-
// We therefore have to be very careful here.
1093-
None
1124+
self.tcx
10941125
}
10951126

10961127
#[inline]
1097-
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
1128+
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
10981129
debug!(
10991130
"HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
11001131
t,
@@ -1103,6 +1134,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
11031134
);
11041135
if t.flags().intersects(self.flags) {
11051136
ControlFlow::Break(FoundFlags)
1137+
} else if self.tcx.is_some()
1138+
&& t.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
1139+
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
1140+
{
1141+
t.super_visit_with(self)
11061142
} else {
11071143
ControlFlow::CONTINUE
11081144
}
@@ -1125,6 +1161,26 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
11251161
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
11261162
if flags.intersects(self.flags) {
11271163
ControlFlow::Break(FoundFlags)
1164+
} else if self.tcx.is_some()
1165+
&& flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
1166+
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
1167+
{
1168+
c.super_visit_with(self)
1169+
} else {
1170+
ControlFlow::CONTINUE
1171+
}
1172+
}
1173+
1174+
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
1175+
let flags = FlagComputation::for_unevaluated_const(uv);
1176+
debug!("HasTypeFlagsVisitor: uv={:?} uv.flags={:?} self.flags={:?}", uv, flags, self.flags);
1177+
if flags.intersects(self.flags) {
1178+
ControlFlow::Break(FoundFlags)
1179+
} else if self.tcx.is_some()
1180+
&& flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
1181+
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
1182+
{
1183+
uv.super_visit_with(self)
11281184
} else {
11291185
ControlFlow::CONTINUE
11301186
}
@@ -1138,6 +1194,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
11381194
);
11391195
if predicate.inner.flags.intersects(self.flags) {
11401196
ControlFlow::Break(FoundFlags)
1197+
} else if self.tcx.is_some()
1198+
&& predicate.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
1199+
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
1200+
{
1201+
predicate.super_visit_with(self)
11411202
} else {
11421203
ControlFlow::CONTINUE
11431204
}

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1727,7 +1727,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
17271727
// Ignore layouts that are done with non-empty environments or
17281728
// non-monomorphic layouts, as the user only wants to see the stuff
17291729
// resulting from the final codegen session.
1730-
if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() {
1730+
if layout.ty.has_param_types_or_consts(self.tcx)
1731+
|| !self.param_env.caller_bounds().is_empty()
1732+
{
17311733
return;
17321734
}
17331735

@@ -1894,7 +1896,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
18941896
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
18951897
match tail.kind() {
18961898
ty::Param(_) | ty::Projection(_) => {
1897-
debug_assert!(tail.has_param_types_or_consts());
1899+
debug_assert!(tail.has_param_types_or_consts(tcx));
18981900
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
18991901
}
19001902
_ => bug!(

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ impl<'tcx> ParamEnv<'tcx> {
12511251
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
12521252

12531253
Reveal::All => {
1254-
if value.is_global() {
1254+
if value.is_known_global() {
12551255
ParamEnvAnd { param_env: self.without_caller_bounds(), value }
12561256
} else {
12571257
ParamEnvAnd { param_env: self, value }

0 commit comments

Comments
 (0)