Skip to content

Commit 6c4b961

Browse files
committed
move projection mode into parameter environment
1 parent 4ed2eda commit 6c4b961

File tree

28 files changed

+110
-99
lines changed

28 files changed

+110
-99
lines changed

src/librustc/infer/mod.rs

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
174174
// avoid reporting the same error twice.
175175
pub reported_trait_errors: RefCell<FxHashSet<traits::TraitErrorKey<'tcx>>>,
176176

177-
// Sadly, the behavior of projection varies a bit depending on the
178-
// stage of compilation. The specifics are given in the
179-
// documentation for `Reveal`.
180-
projection_mode: Reveal,
181-
182177
// When an error occurs, we want to avoid reporting "derived"
183178
// errors that are due to this original failure. Normally, we
184179
// handle this with the `err_count_on_creation` count, which
@@ -406,54 +401,54 @@ pub trait InferEnv<'a, 'tcx> {
406401
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
407402
-> (Option<&'a ty::TypeckTables<'tcx>>,
408403
Option<ty::TypeckTables<'tcx>>,
409-
Option<ty::ParamEnv<'tcx>>);
404+
ty::ParamEnv<'tcx>);
410405
}
411406

412-
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
407+
impl<'a, 'tcx> InferEnv<'a, 'tcx> for Reveal {
413408
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
414409
-> (Option<&'a ty::TypeckTables<'tcx>>,
415410
Option<ty::TypeckTables<'tcx>>,
416-
Option<ty::ParamEnv<'tcx>>) {
417-
(None, None, None)
411+
ty::ParamEnv<'tcx>) {
412+
(None, None, ty::ParamEnv::empty(self))
418413
}
419414
}
420415

421416
impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParamEnv<'tcx> {
422417
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
423418
-> (Option<&'a ty::TypeckTables<'tcx>>,
424419
Option<ty::TypeckTables<'tcx>>,
425-
Option<ty::ParamEnv<'tcx>>) {
426-
(None, None, Some(self))
420+
ty::ParamEnv<'tcx>) {
421+
(None, None, self)
427422
}
428423
}
429424

430425
impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
431426
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
432427
-> (Option<&'a ty::TypeckTables<'tcx>>,
433428
Option<ty::TypeckTables<'tcx>>,
434-
Option<ty::ParamEnv<'tcx>>) {
435-
(Some(self.0), None, Some(self.1))
429+
ty::ParamEnv<'tcx>) {
430+
(Some(self.0), None, self.1)
436431
}
437432
}
438433

439434
impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
440435
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
441436
-> (Option<&'a ty::TypeckTables<'tcx>>,
442437
Option<ty::TypeckTables<'tcx>>,
443-
Option<ty::ParamEnv<'tcx>>) {
444-
(None, Some(self.0), Some(self.1))
438+
ty::ParamEnv<'tcx>) {
439+
(None, Some(self.0), self.1)
445440
}
446441
}
447442

448443
impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
449444
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
450445
-> (Option<&'a ty::TypeckTables<'tcx>>,
451446
Option<ty::TypeckTables<'tcx>>,
452-
Option<ty::ParamEnv<'tcx>>) {
447+
ty::ParamEnv<'tcx>) {
453448
let def_id = tcx.hir.body_owner_def_id(self);
454449
(Some(tcx.typeck_tables_of(def_id)),
455450
None,
456-
Some(tcx.param_env(def_id)))
451+
tcx.param_env(def_id))
457452
}
458453
}
459454

@@ -465,23 +460,18 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
465460
arena: DroplessArena,
466461
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
467462
tables: Option<&'a ty::TypeckTables<'gcx>>,
468-
param_env: Option<ty::ParamEnv<'gcx>>,
469-
projection_mode: Reveal,
463+
param_env: ty::ParamEnv<'gcx>,
470464
}
471465

472466
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
473-
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self,
474-
env: E,
475-
projection_mode: Reveal)
476-
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
467+
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
477468
let (tables, fresh_tables, param_env) = env.to_parts(self);
478469
InferCtxtBuilder {
479470
global_tcx: self,
480471
arena: DroplessArena::new(),
481472
fresh_tables: fresh_tables.map(RefCell::new),
482473
tables: tables,
483474
param_env: param_env,
484-
projection_mode: projection_mode,
485475
}
486476
}
487477

@@ -498,12 +488,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
498488
int_unification_table: RefCell::new(UnificationTable::new()),
499489
float_unification_table: RefCell::new(UnificationTable::new()),
500490
region_vars: RegionVarBindings::new(self),
501-
param_env: param_env.unwrap(),
491+
param_env: param_env,
502492
selection_cache: traits::SelectionCache::new(),
503493
evaluation_cache: traits::EvaluationCache::new(),
504494
projection_cache: RefCell::new(traits::ProjectionCache::new()),
505495
reported_trait_errors: RefCell::new(FxHashSet()),
506-
projection_mode: Reveal::UserFacing,
507496
tainted_by_errors_flag: Cell::new(false),
508497
err_count_on_creation: self.sess.err_count(),
509498
in_snapshot: Cell::new(false),
@@ -520,13 +509,11 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
520509
ref arena,
521510
ref fresh_tables,
522511
tables,
523-
ref mut param_env,
524-
projection_mode,
512+
param_env,
525513
} = *self;
526514
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
527515
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
528516
});
529-
let param_env = param_env.take().unwrap_or_else(|| ty::ParamEnv::empty());
530517
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
531518
tcx: tcx,
532519
tables: tables,
@@ -539,7 +526,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
539526
selection_cache: traits::SelectionCache::new(),
540527
evaluation_cache: traits::EvaluationCache::new(),
541528
reported_trait_errors: RefCell::new(FxHashSet()),
542-
projection_mode: projection_mode,
543529
tainted_by_errors_flag: Cell::new(false),
544530
err_count_on_creation: tcx.sess.err_count(),
545531
in_snapshot: Cell::new(false),
@@ -643,11 +629,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
643629
return value;
644630
}
645631

646-
self.infer_ctxt((), Reveal::All).enter(|infcx| {
632+
self.infer_ctxt(Reveal::All).enter(|infcx| {
647633
value.trans_normalize(&infcx)
648634
})
649635
}
650636

637+
/// Does a best-effort to normalize any associated types in
638+
/// `value`; this includes revealing specializable types, so this
639+
/// should be not be used during type-checking, but only during
640+
/// optimization and code generation.
651641
pub fn normalize_associated_type_in_env<T>(
652642
self, value: &T, env: ty::ParamEnv<'tcx>
653643
) -> T
@@ -661,7 +651,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
661651
return value;
662652
}
663653

664-
self.infer_ctxt(env, Reveal::All).enter(|infcx| {
654+
self.infer_ctxt(env.reveal_all()).enter(|infcx| {
665655
value.trans_normalize(&infcx)
666656
})
667657
}
@@ -728,10 +718,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
728718
}
729719
}
730720

731-
pub fn projection_mode(&self) -> Reveal {
732-
self.projection_mode
733-
}
734-
735721
pub fn is_in_snapshot(&self) -> bool {
736722
self.in_snapshot.get()
737723
}

src/librustc/middle/intrinsicck.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use hir::def::Def;
1212
use hir::def_id::DefId;
1313
use infer::InferCtxt;
14-
use traits::Reveal;
1514
use ty::{self, Ty, TyCtxt};
1615
use ty::layout::{LayoutError, Pointer, SizeSkeleton};
1716

@@ -140,7 +139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> {
140139

141140
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
142141
let body = self.tcx.hir.body(body_id);
143-
self.tcx.infer_ctxt(body_id, Reveal::All).enter(|infcx| {
142+
self.tcx.infer_ctxt(body_id).enter(|infcx| {
144143
let mut visitor = ExprVisitor {
145144
infcx: &infcx
146145
};

src/librustc/traits/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,9 +477,10 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
477477
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
478478
predicates);
479479

480-
let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
480+
let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
481+
unnormalized_env.reveal);
481482

482-
tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
483+
tcx.infer_ctxt(elaborated_env).enter(|infcx| {
483484
let predicates = match fully_normalize(
484485
&infcx, cause,
485486
// You would really want to pass infcx.param_env.caller_bounds here,
@@ -528,7 +529,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
528529
debug!("normalize_param_env_or_error: resolved predicates={:?}",
529530
predicates);
530531

531-
ty::ParamEnv::new(tcx.intern_predicates(&predicates))
532+
ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal)
532533
})
533534
}
534535

@@ -590,7 +591,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
590591
debug!("normalize_and_test_predicates(predicates={:?})",
591592
predicates);
592593

593-
tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
594+
tcx.infer_ctxt(Reveal::All).enter(|infcx| {
594595
let mut selcx = SelectionContext::new(&infcx);
595596
let mut fulfill_cx = FulfillmentContext::new();
596597
let cause = ObligationCause::dummy();

src/librustc/traits/project.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use util::common::FN_OUTPUT_NAME;
3636

3737
/// Depending on the stage of compilation, we want projection to be
3838
/// more or less conservative.
39-
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
39+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
4040
pub enum Reveal {
4141
/// At type-checking time, we refuse to project any associated
4242
/// type that is marked `default`. Non-`default` ("final") types
@@ -278,12 +278,14 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
278278
match ty.sty {
279279
ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
280280
// Only normalize `impl Trait` after type-checking, usually in trans.
281-
if self.selcx.projection_mode() == Reveal::All {
282-
let generic_ty = self.tcx().type_of(def_id);
283-
let concrete_ty = generic_ty.subst(self.tcx(), substs);
284-
self.fold_ty(concrete_ty)
285-
} else {
286-
ty
281+
match self.param_env.reveal {
282+
Reveal::UserFacing => ty,
283+
284+
Reveal::All => {
285+
let generic_ty = self.tcx().type_of(def_id);
286+
let concrete_ty = generic_ty.subst(self.tcx(), substs);
287+
self.fold_ty(concrete_ty)
288+
}
287289
}
288290
}
289291

src/librustc/traits/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
324324
}
325325

326326
pub fn projection_mode(&self) -> Reveal {
327-
self.infcx.projection_mode()
327+
self.param_env().reveal
328328
}
329329

330330
/// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection

src/librustc/traits/specialize/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ pub fn find_associated_item<'a, 'tcx>(
122122
let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id);
123123
match ancestors.defs(tcx, item.name, item.kind).next() {
124124
Some(node_item) => {
125-
let substs = tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
125+
let substs = tcx.infer_ctxt(Reveal::All).enter(|infcx| {
126126
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
127127
let substs = translate_substs(&infcx, impl_data.impl_def_id,
128128
substs, node_item.node);
@@ -184,7 +184,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
184184
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
185185

186186
// Create a infcx, taking the predicates of impl1 as assumptions:
187-
let result = tcx.infer_ctxt(penv, Reveal::UserFacing).enter(|infcx| {
187+
let result = tcx.infer_ctxt(penv).enter(|infcx| {
188188
// Normalize the trait reference. The WF rules ought to ensure
189189
// that this always succeeds.
190190
let impl1_trait_ref =

src/librustc/traits/specialize/specialization_graph.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'a, 'gcx, 'tcx> Children {
109109
let possible_sibling = *slot;
110110

111111
let tcx = tcx.global_tcx();
112-
let (le, ge) = tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
112+
let (le, ge) = tcx.infer_ctxt(Reveal::UserFacing).enter(|infcx| {
113113
let overlap = traits::overlapping_impls(&infcx,
114114
possible_sibling,
115115
impl_def_id);

src/librustc/traits/trans/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
4646

4747
// Do the initial selection for the obligation. This yields the
4848
// shallow result we are looking for -- that is, what specific impl.
49-
self.infer_ctxt((), Reveal::All).enter(|infcx| {
49+
self.infer_ctxt(Reveal::All).enter(|infcx| {
5050
let mut selcx = SelectionContext::new(&infcx);
5151

5252
let obligation_cause = ObligationCause::misc(span,

src/librustc/ty/maps.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,12 @@ define_maps! { <'tcx>
906906
[] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
907907
[] is_object_safe: ObjectSafety(DefId) -> bool,
908908

909+
// Get the ParameterEnvironment for a given item; this environment
910+
// will be in "user-facing" mode, meaning that it is suitabe for
911+
// type-checking etc, and it does not normalize specializable
912+
// associated types. This is almost always what you want,
913+
// unless you are doing MIR optimizations, in which case you
914+
// might want to use `reveal_all()` method to change modes.
909915
[] param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,
910916

911917
// Trait selection queries. These are best used by invoking `ty.moves_by_default()`,

src/librustc/ty/mod.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,11 @@ pub struct ParamEnv<'tcx> {
11911191
/// the set of bounds on the in-scope type parameters, translated
11921192
/// into Obligations, and elaborated and normalized.
11931193
pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
1194+
1195+
/// Typically, this is `Reveal::UserFacing`, but during trans we
1196+
/// want `Reveal::All` -- note that this is always paired with an
1197+
/// empty environment. To get that, use `ParamEnv::reveal()`.
1198+
pub reveal: traits::Reveal,
11941199
}
11951200

11961201
impl<'tcx> ParamEnv<'tcx> {
@@ -1218,7 +1223,7 @@ impl<'tcx> ParamEnv<'tcx> {
12181223
}
12191224
} else {
12201225
ParamEnvAnd {
1221-
param_env: ParamEnv::empty(),
1226+
param_env: ParamEnv::empty(self.reveal),
12221227
value: value,
12231228
}
12241229
}
@@ -2467,8 +2472,8 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
24672472

24682473
/// See `ParamEnv` struct def'n for details.
24692474
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2470-
def_id: DefId)
2471-
-> ParamEnv<'tcx> {
2475+
def_id: DefId)
2476+
-> ParamEnv<'tcx> {
24722477
// Compute the bounds on Self and the type parameters.
24732478

24742479
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
@@ -2486,7 +2491,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
24862491
// are any errors at that point, so after type checking you can be
24872492
// sure that this will succeed without errors anyway.
24882493

2489-
let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
2494+
let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
2495+
traits::Reveal::UserFacing);
24902496

24912497
let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
24922498
tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)

0 commit comments

Comments
 (0)