Skip to content

Commit 8e84aa9

Browse files
committed
Add constness to ParamEnv
This now causes a lot of queries to be executed twice, as reveal_all forces NotConst
1 parent b966d1c commit 8e84aa9

File tree

8 files changed

+126
-41
lines changed

8 files changed

+126
-41
lines changed

compiler/rustc_middle/src/hir/map/mod.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -446,18 +446,30 @@ impl<'hir> Map<'hir> {
446446
///
447447
/// Panics if `LocalDefId` does not have an associated body.
448448
pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind {
449+
match self.opt_body_owner_kind(id) {
450+
Ok(kind) => kind,
451+
Err(node) => bug!("{:#?} is not a body node", node),
452+
}
453+
}
454+
455+
/// Returns the `BodyOwnerKind` of this `LocalDefId`.
456+
///
457+
/// Returns the `Node` if `LocalDefId` does not have an associated body.
458+
pub fn opt_body_owner_kind(&self, id: HirId) -> Result<BodyOwnerKind, Node<'_>> {
449459
match self.get(id) {
450460
Node::Item(&Item { kind: ItemKind::Const(..), .. })
451461
| Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. })
452462
| Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. })
453-
| Node::AnonConst(_) => BodyOwnerKind::Const,
463+
| Node::AnonConst(_) => Ok(BodyOwnerKind::Const),
454464
Node::Ctor(..)
455465
| Node::Item(&Item { kind: ItemKind::Fn(..), .. })
456466
| Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. })
457-
| Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => BodyOwnerKind::Fn,
458-
Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m),
459-
Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure,
460-
node => bug!("{:#?} is not a body node", node),
467+
| Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => Ok(BodyOwnerKind::Fn),
468+
Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => {
469+
Ok(BodyOwnerKind::Static(m))
470+
}
471+
Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => Ok(BodyOwnerKind::Closure),
472+
node => Err(node),
461473
}
462474
}
463475

@@ -466,7 +478,8 @@ impl<'hir> Map<'hir> {
466478
/// Panics if `LocalDefId` does not have an associated body.
467479
///
468480
/// This should only be used for determining the context of a body, a return
469-
/// value of `Some` does not always suggest that the owner of the body is `const`.
481+
/// value of `Some` does not always suggest that the owner of the body is `const`,
482+
/// just that it has to be checked as if it were.
470483
pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> {
471484
let hir_id = self.local_def_id_to_hir_id(did);
472485
let ccx = match self.body_owner_kind(hir_id) {

compiler/rustc_middle/src/ty/mod.rs

+38-13
Original file line numberDiff line numberDiff line change
@@ -1222,22 +1222,27 @@ pub struct ParamEnv<'tcx> {
12221222
#[derive(Copy, Clone)]
12231223
struct ParamTag {
12241224
reveal: traits::Reveal,
1225+
constness: hir::Constness,
12251226
}
12261227

12271228
unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
1228-
const BITS: usize = 1;
1229+
const BITS: usize = 2;
12291230
#[inline]
12301231
fn into_usize(self) -> usize {
12311232
match self {
1232-
Self { reveal: traits::Reveal::UserFacing } => 0,
1233-
Self { reveal: traits::Reveal::All } => 1,
1233+
Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0,
1234+
Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1,
1235+
Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2,
1236+
Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3,
12341237
}
12351238
}
12361239
#[inline]
12371240
unsafe fn from_usize(ptr: usize) -> Self {
12381241
match ptr {
1239-
0 => Self { reveal: traits::Reveal::UserFacing },
1240-
1 => Self { reveal: traits::Reveal::All },
1242+
0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
1243+
1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst },
1244+
2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const },
1245+
3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const },
12411246
_ => std::hint::unreachable_unchecked(),
12421247
}
12431248
}
@@ -1248,6 +1253,7 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> {
12481253
f.debug_struct("ParamEnv")
12491254
.field("caller_bounds", &self.caller_bounds())
12501255
.field("reveal", &self.reveal())
1256+
.field("constness", &self.constness())
12511257
.finish()
12521258
}
12531259
}
@@ -1256,17 +1262,23 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ParamEnv<'tcx> {
12561262
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
12571263
self.caller_bounds().hash_stable(hcx, hasher);
12581264
self.reveal().hash_stable(hcx, hasher);
1265+
self.constness().hash_stable(hcx, hasher);
12591266
}
12601267
}
12611268

12621269
impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
12631270
fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
1264-
ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder))
1271+
ParamEnv::new(
1272+
self.caller_bounds().fold_with(folder),
1273+
self.reveal().fold_with(folder),
1274+
self.constness().fold_with(folder),
1275+
)
12651276
}
12661277

12671278
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
12681279
self.caller_bounds().visit_with(visitor)?;
1269-
self.reveal().visit_with(visitor)
1280+
self.reveal().visit_with(visitor)?;
1281+
self.constness().visit_with(visitor)
12701282
}
12711283
}
12721284

@@ -1277,7 +1289,7 @@ impl<'tcx> ParamEnv<'tcx> {
12771289
/// type-checking.
12781290
#[inline]
12791291
pub fn empty() -> Self {
1280-
Self::new(List::empty(), Reveal::UserFacing)
1292+
Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst)
12811293
}
12821294

12831295
#[inline]
@@ -1290,6 +1302,11 @@ impl<'tcx> ParamEnv<'tcx> {
12901302
self.packed.tag().reveal
12911303
}
12921304

1305+
#[inline]
1306+
pub fn constness(self) -> hir::Constness {
1307+
self.packed.tag().constness
1308+
}
1309+
12931310
/// Construct a trait environment with no where-clauses in scope
12941311
/// where the values of all `impl Trait` and other hidden types
12951312
/// are revealed. This is suitable for monomorphized, post-typeck
@@ -1299,13 +1316,17 @@ impl<'tcx> ParamEnv<'tcx> {
12991316
/// or invoke `param_env.with_reveal_all()`.
13001317
#[inline]
13011318
pub fn reveal_all() -> Self {
1302-
Self::new(List::empty(), Reveal::All)
1319+
Self::new(List::empty(), Reveal::All, hir::Constness::NotConst)
13031320
}
13041321

13051322
/// Construct a trait environment with the given set of predicates.
13061323
#[inline]
1307-
pub fn new(caller_bounds: &'tcx List<Predicate<'tcx>>, reveal: Reveal) -> Self {
1308-
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) }
1324+
pub fn new(
1325+
caller_bounds: &'tcx List<Predicate<'tcx>>,
1326+
reveal: Reveal,
1327+
constness: hir::Constness,
1328+
) -> Self {
1329+
ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) }
13091330
}
13101331

13111332
pub fn with_user_facing(mut self) -> Self {
@@ -1327,13 +1348,17 @@ impl<'tcx> ParamEnv<'tcx> {
13271348
return self;
13281349
}
13291350

1330-
ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All)
1351+
ParamEnv::new(
1352+
tcx.normalize_opaque_types(self.caller_bounds()),
1353+
Reveal::All,
1354+
self.constness(),
1355+
)
13311356
}
13321357

13331358
/// Returns this same environment but with no caller bounds.
13341359
#[inline]
13351360
pub fn without_caller_bounds(self) -> Self {
1336-
Self::new(List::empty(), self.reveal())
1361+
Self::new(List::empty(), self.reveal(), self.constness())
13371362
}
13381363

13391364
/// Creates a suitable environment in which to perform trait

compiler/rustc_middle/src/ty/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
480480
type Lifted = ty::ParamEnv<'tcx>;
481481
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
482482
tcx.lift(self.caller_bounds())
483-
.map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal()))
483+
.map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.constness()))
484484
}
485485
}
486486

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,17 @@ impl AutoTraitFinder<'tcx> {
368368
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
369369
)
370370
.map(|o| o.predicate);
371-
new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal());
371+
new_env = ty::ParamEnv::new(
372+
tcx.mk_predicates(normalized_preds),
373+
param_env.reveal(),
374+
param_env.constness(),
375+
);
372376
}
373377

374378
let final_user_env = ty::ParamEnv::new(
375379
tcx.mk_predicates(user_computed_preds.into_iter()),
376380
user_env.reveal(),
381+
user_env.constness(),
377382
);
378383
debug!(
379384
"evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \

compiler/rustc_trait_selection/src/traits/mod.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,11 @@ pub fn normalize_param_env_or_error<'tcx>(
310310

311311
debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
312312

313-
let elaborated_env =
314-
ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal());
313+
let elaborated_env = ty::ParamEnv::new(
314+
tcx.intern_predicates(&predicates),
315+
unnormalized_env.reveal(),
316+
unnormalized_env.constness(),
317+
);
315318

316319
// HACK: we are trying to normalize the param-env inside *itself*. The problem is that
317320
// normalization expects its param-env to be already normalized, which means we have
@@ -363,8 +366,11 @@ pub fn normalize_param_env_or_error<'tcx>(
363366
// predicates here anyway. Keeping them here anyway because it seems safer.
364367
let outlives_env: Vec<_> =
365368
non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect();
366-
let outlives_env =
367-
ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal());
369+
let outlives_env = ty::ParamEnv::new(
370+
tcx.intern_predicates(&outlives_env),
371+
unnormalized_env.reveal(),
372+
unnormalized_env.constness(),
373+
);
368374
let outlives_predicates = match do_normalize_predicates(
369375
tcx,
370376
region_context,
@@ -384,7 +390,11 @@ pub fn normalize_param_env_or_error<'tcx>(
384390
let mut predicates = non_outlives_predicates;
385391
predicates.extend(outlives_predicates);
386392
debug!("normalize_param_env_or_error: final predicates={:?}", predicates);
387-
ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal())
393+
ty::ParamEnv::new(
394+
tcx.intern_predicates(&predicates),
395+
unnormalized_env.reveal(),
396+
unnormalized_env.constness(),
397+
)
388398
}
389399

390400
pub fn fully_normalize<'a, 'tcx, T>(

compiler/rustc_trait_selection/src/traits/object_safety.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,11 @@ fn receiver_is_dispatchable<'tcx>(
698698
.chain(array::IntoIter::new([unsize_predicate, trait_predicate]))
699699
.collect();
700700

701-
ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal())
701+
ty::ParamEnv::new(
702+
tcx.intern_predicates(&caller_bounds),
703+
param_env.reveal(),
704+
param_env.constness(),
705+
)
702706
};
703707

704708
// Receiver: DispatchFromDyn<Receiver[Self => U]>

compiler/rustc_ty_utils/src/ty.rs

+27-9
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,33 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
274274
predicates.extend(environment);
275275
}
276276

277-
let unnormalized_env =
278-
ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing);
279-
280-
let body_id = def_id
281-
.as_local()
282-
.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
283-
.map_or(hir::CRATE_HIR_ID, |id| {
284-
tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
285-
});
277+
let local_did = def_id.as_local();
278+
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
279+
280+
let constness = match hir_id {
281+
Some(hir_id) => match tcx.hir().opt_body_owner_kind(hir_id) {
282+
Err(hir::Node::Item(&hir::Item {
283+
kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
284+
..
285+
})) => constness,
286+
Err(_) => hir::Constness::NotConst,
287+
Ok(_) => match tcx.hir().body_const_context(local_did.unwrap()) {
288+
Some(_) => hir::Constness::Const,
289+
None => hir::Constness::NotConst,
290+
},
291+
},
292+
None => hir::Constness::NotConst,
293+
};
294+
295+
let unnormalized_env = ty::ParamEnv::new(
296+
tcx.intern_predicates(&predicates),
297+
traits::Reveal::UserFacing,
298+
constness,
299+
);
300+
301+
let body_id = hir_id.map_or(hir::CRATE_HIR_ID, |id| {
302+
tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
303+
});
286304
let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
287305
traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
288306
}

compiler/rustc_typeck/src/check/compare_method.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,11 @@ fn compare_predicate_entailment<'tcx>(
209209
// The key step here is to update the caller_bounds's predicates to be
210210
// the new hybrid bounds we computed.
211211
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id);
212-
let param_env =
213-
ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing);
212+
let param_env = ty::ParamEnv::new(
213+
tcx.intern_predicates(&hybrid_preds.predicates),
214+
Reveal::UserFacing,
215+
hir::Constness::NotConst,
216+
);
214217
let param_env = traits::normalize_param_env_or_error(
215218
tcx,
216219
impl_m.def_id,
@@ -1183,8 +1186,11 @@ fn compare_type_predicate_entailment<'tcx>(
11831186
debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds);
11841187

11851188
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
1186-
let param_env =
1187-
ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing);
1189+
let param_env = ty::ParamEnv::new(
1190+
tcx.intern_predicates(&hybrid_preds.predicates),
1191+
Reveal::UserFacing,
1192+
hir::Constness::NotConst,
1193+
);
11881194
let param_env = traits::normalize_param_env_or_error(
11891195
tcx,
11901196
impl_ty.def_id,
@@ -1368,7 +1374,11 @@ pub fn check_type_bounds<'tcx>(
13681374
.to_predicate(tcx),
13691375
),
13701376
};
1371-
ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
1377+
ty::ParamEnv::new(
1378+
tcx.intern_predicates(&predicates),
1379+
Reveal::UserFacing,
1380+
param_env.constness(),
1381+
)
13721382
};
13731383
debug!(?normalize_param_env);
13741384

0 commit comments

Comments
 (0)