Skip to content

Commit 5c0a3b5

Browse files
committed
move projection mode into parameter environment
1 parent e1fe1a8 commit 5c0a3b5

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),
@@ -642,11 +628,15 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
642628
return value;
643629
}
644630

645-
self.infer_ctxt((), Reveal::All).enter(|infcx| {
631+
self.infer_ctxt(Reveal::All).enter(|infcx| {
646632
value.trans_normalize(&infcx)
647633
})
648634
}
649635

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

663-
self.infer_ctxt(env, Reveal::All).enter(|infcx| {
653+
self.infer_ctxt(env.reveal_all()).enter(|infcx| {
664654
value.trans_normalize(&infcx)
665655
})
666656
}
@@ -727,10 +717,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
727717
}
728718
}
729719

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

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
@@ -1237,6 +1237,11 @@ pub struct ParamEnv<'tcx> {
12371237
/// the set of bounds on the in-scope type parameters, translated
12381238
/// into Obligations, and elaborated and normalized.
12391239
pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
1240+
1241+
/// Typically, this is `Reveal::UserFacing`, but during trans we
1242+
/// want `Reveal::All` -- note that this is always paired with an
1243+
/// empty environment. To get that, use `ParamEnv::reveal()`.
1244+
pub reveal: traits::Reveal,
12401245
}
12411246

12421247
impl<'tcx> ParamEnv<'tcx> {
@@ -1264,7 +1269,7 @@ impl<'tcx> ParamEnv<'tcx> {
12641269
}
12651270
} else {
12661271
ParamEnvAnd {
1267-
param_env: ParamEnv::empty(),
1272+
param_env: ParamEnv::empty(self.reveal),
12681273
value: value,
12691274
}
12701275
}
@@ -2526,8 +2531,8 @@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option
25262531

25272532
/// See `ParamEnv` struct def'n for details.
25282533
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
2529-
def_id: DefId)
2530-
-> ParamEnv<'tcx> {
2534+
def_id: DefId)
2535+
-> ParamEnv<'tcx> {
25312536
// Compute the bounds on Self and the type parameters.
25322537

25332538
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
@@ -2545,7 +2550,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
25452550
// are any errors at that point, so after type checking you can be
25462551
// sure that this will succeed without errors anyway.
25472552

2548-
let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
2553+
let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
2554+
traits::Reveal::UserFacing);
25492555

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

0 commit comments

Comments
 (0)