Skip to content

Commit 9cc77d7

Browse files
committed
Auto merge of #41464 - frewsxcv:rollup, r=frewsxcv
Rollup of 3 pull requests - Successful merges: #41077, #41355, #41450 - Failed merges:
2 parents 6d841da + b37163c commit 9cc77d7

34 files changed

+579
-415
lines changed

src/doc/grammar.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -781,10 +781,11 @@ never_type : "!" ;
781781
### Type parameter bounds
782782

783783
```antlr
784+
bound-list := bound | bound '+' bound-list '+' ?
784785
bound := ty_bound | lt_bound
785786
lt_bound := lifetime
786-
ty_bound := [?] [ for<lt_param_defs> ] simple_path
787-
bound-list := bound | bound '+' bound-list '+' ?
787+
ty_bound := ty_bound_noparen | (ty_bound_noparen)
788+
ty_bound_noparen := [?] [ for<lt_param_defs> ] simple_path
788789
```
789790

790791
### Self types

src/librustc/dep_graph/dep_node.rs

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub enum DepNode<D: Clone + Debug> {
8888
// predicates for an item wind up in `ItemSignature`).
8989
AssociatedItems(D),
9090
ItemSignature(D),
91+
IsForeignItem(D),
9192
TypeParamPredicates((D, D)),
9293
SizedConstraint(D),
9394
AdtDestructor(D),
@@ -171,6 +172,7 @@ impl<D: Clone + Debug> DepNode<D> {
171172
TransCrateItem,
172173
AssociatedItems,
173174
ItemSignature,
175+
IsForeignItem,
174176
AssociatedItemDefIds,
175177
InherentImpls,
176178
TypeckTables,
@@ -221,6 +223,7 @@ impl<D: Clone + Debug> DepNode<D> {
221223
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
222224
AssociatedItems(ref d) => op(d).map(AssociatedItems),
223225
ItemSignature(ref d) => op(d).map(ItemSignature),
226+
IsForeignItem(ref d) => op(d).map(IsForeignItem),
224227
TypeParamPredicates((ref item, ref param)) => {
225228
Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
226229
}

src/librustc/middle/reachable.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use hir::map as hir_map;
1919
use hir::def::Def;
2020
use hir::def_id::{DefId, CrateNum};
21+
use std::rc::Rc;
2122
use ty::{self, TyCtxt};
2223
use ty::maps::Providers;
2324
use middle::privacy;
@@ -362,11 +363,11 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a,
362363
}
363364
}
364365

365-
pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
366+
pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Rc<NodeSet> {
366367
ty::queries::reachable_set::get(tcx, DUMMY_SP, LOCAL_CRATE)
367368
}
368369

369-
fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> NodeSet {
370+
fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> Rc<NodeSet> {
370371
debug_assert!(crate_num == LOCAL_CRATE);
371372

372373
let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
@@ -411,7 +412,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) ->
411412
reachable_context.propagate();
412413

413414
// Return the set of reachable symbols.
414-
reachable_context.reachable_symbols
415+
Rc::new(reachable_context.reachable_symbols)
415416
}
416417

417418
pub fn provide(providers: &mut Providers) {

src/librustc/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ mod object_safety;
5555
mod select;
5656
mod specialize;
5757
mod structural_impls;
58+
pub mod trans;
5859
mod util;
5960

6061
/// An `Obligation` represents some trait reference (e.g. `int:Eq`) for

src/librustc/traits/trans/mod.rs

+212
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This file contains various trait resolution methods used by trans.
12+
// They all assume regions can be erased and monomorphic types. It
13+
// seems likely that they should eventually be merged into more
14+
// general routines.
15+
16+
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
17+
use hir::def_id::DefId;
18+
use infer::TransNormalize;
19+
use std::cell::RefCell;
20+
use std::marker::PhantomData;
21+
use syntax::ast;
22+
use syntax_pos::Span;
23+
use traits::{FulfillmentContext, Obligation, ObligationCause, Reveal, SelectionContext, Vtable};
24+
use ty::{self, Ty, TyCtxt};
25+
use ty::subst::{Subst, Substs};
26+
use ty::fold::{TypeFoldable, TypeFolder};
27+
use util::common::MemoizationMap;
28+
29+
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
30+
/// Attempts to resolve an obligation to a vtable.. The result is
31+
/// a shallow vtable resolution -- meaning that we do not
32+
/// (necessarily) resolve all nested obligations on the impl. Note
33+
/// that type check should guarantee to us that all nested
34+
/// obligations *could be* resolved if we wanted to.
35+
pub fn trans_fulfill_obligation(self,
36+
span: Span,
37+
trait_ref: ty::PolyTraitRef<'tcx>)
38+
-> Vtable<'tcx, ()>
39+
{
40+
// Remove any references to regions; this helps improve caching.
41+
let trait_ref = self.erase_regions(&trait_ref);
42+
43+
self.trans_trait_caches.trait_cache.memoize(trait_ref, || {
44+
debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
45+
trait_ref, trait_ref.def_id());
46+
47+
// Do the initial selection for the obligation. This yields the
48+
// shallow result we are looking for -- that is, what specific impl.
49+
self.infer_ctxt((), Reveal::All).enter(|infcx| {
50+
let mut selcx = SelectionContext::new(&infcx);
51+
52+
let obligation_cause = ObligationCause::misc(span,
53+
ast::DUMMY_NODE_ID);
54+
let obligation = Obligation::new(obligation_cause,
55+
trait_ref.to_poly_trait_predicate());
56+
57+
let selection = match selcx.select(&obligation) {
58+
Ok(Some(selection)) => selection,
59+
Ok(None) => {
60+
// Ambiguity can happen when monomorphizing during trans
61+
// expands to some humongo type that never occurred
62+
// statically -- this humongo type can then overflow,
63+
// leading to an ambiguous result. So report this as an
64+
// overflow bug, since I believe this is the only case
65+
// where ambiguity can result.
66+
debug!("Encountered ambiguity selecting `{:?}` during trans, \
67+
presuming due to overflow",
68+
trait_ref);
69+
self.sess.span_fatal(span,
70+
"reached the recursion limit during monomorphization \
71+
(selection ambiguity)");
72+
}
73+
Err(e) => {
74+
span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
75+
e, trait_ref)
76+
}
77+
};
78+
79+
debug!("fulfill_obligation: selection={:?}", selection);
80+
81+
// Currently, we use a fulfillment context to completely resolve
82+
// all nested obligations. This is because they can inform the
83+
// inference of the impl's type parameters.
84+
let mut fulfill_cx = FulfillmentContext::new();
85+
let vtable = selection.map(|predicate| {
86+
debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
87+
fulfill_cx.register_predicate_obligation(&infcx, predicate);
88+
});
89+
let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
90+
91+
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
92+
vtable
93+
})
94+
})
95+
}
96+
97+
/// Monomorphizes a type from the AST by first applying the in-scope
98+
/// substitutions and then normalizing any associated types.
99+
pub fn trans_apply_param_substs<T>(self,
100+
param_substs: &Substs<'tcx>,
101+
value: &T)
102+
-> T
103+
where T: TransNormalize<'tcx>
104+
{
105+
debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
106+
let substituted = value.subst(self, param_substs);
107+
let substituted = self.erase_regions(&substituted);
108+
AssociatedTypeNormalizer::new(self).fold(&substituted)
109+
}
110+
}
111+
112+
struct AssociatedTypeNormalizer<'a, 'gcx: 'a> {
113+
tcx: TyCtxt<'a, 'gcx, 'gcx>,
114+
}
115+
116+
impl<'a, 'gcx> AssociatedTypeNormalizer<'a, 'gcx> {
117+
fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> Self {
118+
AssociatedTypeNormalizer { tcx }
119+
}
120+
121+
fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
122+
if !value.has_projection_types() {
123+
value.clone()
124+
} else {
125+
value.fold_with(self)
126+
}
127+
}
128+
}
129+
130+
impl<'a, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'gcx> {
131+
fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
132+
self.tcx
133+
}
134+
135+
fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
136+
if !ty.has_projection_types() {
137+
ty
138+
} else {
139+
self.tcx.trans_trait_caches.project_cache.memoize(ty, || {
140+
debug!("AssociatedTypeNormalizer: ty={:?}", ty);
141+
self.tcx.normalize_associated_type(&ty)
142+
})
143+
}
144+
}
145+
}
146+
147+
/// Specializes caches used in trans -- in particular, they assume all
148+
/// types are fully monomorphized and that free regions can be erased.
149+
pub struct TransTraitCaches<'tcx> {
150+
trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
151+
project_cache: RefCell<DepTrackingMap<ProjectionCache<'tcx>>>,
152+
}
153+
154+
impl<'tcx> TransTraitCaches<'tcx> {
155+
pub fn new(graph: DepGraph) -> Self {
156+
TransTraitCaches {
157+
trait_cache: RefCell::new(DepTrackingMap::new(graph.clone())),
158+
project_cache: RefCell::new(DepTrackingMap::new(graph)),
159+
}
160+
}
161+
}
162+
163+
// Implement DepTrackingMapConfig for `trait_cache`
164+
pub struct TraitSelectionCache<'tcx> {
165+
data: PhantomData<&'tcx ()>
166+
}
167+
168+
impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
169+
type Key = ty::PolyTraitRef<'tcx>;
170+
type Value = Vtable<'tcx, ()>;
171+
fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> {
172+
key.to_poly_trait_predicate().dep_node()
173+
}
174+
}
175+
176+
// # Global Cache
177+
178+
pub struct ProjectionCache<'gcx> {
179+
data: PhantomData<&'gcx ()>
180+
}
181+
182+
impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
183+
type Key = Ty<'gcx>;
184+
type Value = Ty<'gcx>;
185+
fn to_dep_node(key: &Self::Key) -> DepNode<DefId> {
186+
// Ideally, we'd just put `key` into the dep-node, but we
187+
// can't put full types in there. So just collect up all the
188+
// def-ids of structs/enums as well as any traits that we
189+
// project out of. It doesn't matter so much what we do here,
190+
// except that if we are too coarse, we'll create overly
191+
// coarse edges between impls and the trans. For example, if
192+
// we just used the def-id of things we are projecting out of,
193+
// then the key for `<Foo as SomeTrait>::T` and `<Bar as
194+
// SomeTrait>::T` would both share a dep-node
195+
// (`TraitSelect(SomeTrait)`), and hence the impls for both
196+
// `Foo` and `Bar` would be considered inputs. So a change to
197+
// `Bar` would affect things that just normalized `Foo`.
198+
// Anyway, this heuristic is not ideal, but better than
199+
// nothing.
200+
let def_ids: Vec<DefId> =
201+
key.walk()
202+
.filter_map(|t| match t.sty {
203+
ty::TyAdt(adt_def, _) => Some(adt_def.did),
204+
ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id),
205+
_ => None,
206+
})
207+
.collect();
208+
209+
DepNode::ProjectionCache { def_ids: def_ids }
210+
}
211+
}
212+

src/librustc/ty/context.rs

+3
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ pub struct GlobalCtxt<'tcx> {
407407

408408
pub specializes_cache: RefCell<traits::SpecializesCache>,
409409

410+
pub trans_trait_caches: traits::trans::TransTraitCaches<'tcx>,
411+
410412
pub dep_graph: DepGraph,
411413

412414
/// Common types, pre-interned for your convenience.
@@ -689,6 +691,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
689691
providers[LOCAL_CRATE] = local_providers;
690692
tls::enter_global(GlobalCtxt {
691693
sess: s,
694+
trans_trait_caches: traits::trans::TransTraitCaches::new(dep_graph.clone()),
692695
specializes_cache: RefCell::new(traits::SpecializesCache::new()),
693696
global_arenas: arenas,
694697
global_interners: interners,

src/librustc/ty/maps.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,9 @@ define_maps! { <'tcx>
380380
pub adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
381381
pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>,
382382

383+
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
384+
pub is_foreign_item: IsForeignItem(DefId) -> bool,
385+
383386
/// Maps from def-id of a type or region parameter to its
384387
/// (inferred) variance.
385388
pub variances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>>,
@@ -448,7 +451,7 @@ define_maps! { <'tcx>
448451
/// Performs the privacy check and computes "access levels".
449452
pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
450453

451-
pub reachable_set: reachability_dep_node(CrateNum) -> NodeSet,
454+
pub reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
452455

453456
pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
454457
}

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ mod sty;
115115
#[derive(Clone)]
116116
pub struct CrateAnalysis {
117117
pub access_levels: Rc<AccessLevels>,
118-
pub reachable: NodeSet,
118+
pub reachable: Rc<NodeSet>,
119119
pub name: String,
120120
pub glob_map: Option<hir::GlobMap>,
121121
}

src/librustc_driver/driver.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
810810
defs: resolver.definitions,
811811
analysis: ty::CrateAnalysis {
812812
access_levels: Rc::new(AccessLevels::default()),
813-
reachable: NodeSet(),
813+
reachable: Rc::new(NodeSet()),
814814
name: crate_name.to_string(),
815815
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
816816
},
@@ -889,9 +889,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
889889
let index = stability::Index::new(&hir_map);
890890

891891
let mut local_providers = ty::maps::Providers::default();
892+
borrowck::provide(&mut local_providers);
892893
mir::provide(&mut local_providers);
894+
reachable::provide(&mut local_providers);
893895
rustc_privacy::provide(&mut local_providers);
894-
borrowck::provide(&mut local_providers);
895896
typeck::provide(&mut local_providers);
896897
ty::provide(&mut local_providers);
897898
reachable::provide(&mut local_providers);

src/librustc_metadata/cstore_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ provide! { <'tcx> tcx, def_id, cdata
111111
closure_kind => { cdata.closure_kind(def_id.index) }
112112
closure_type => { cdata.closure_ty(def_id.index, tcx) }
113113
inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
114+
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
114115
}
115116

116117
impl CrateStore for cstore::CStore {

0 commit comments

Comments
 (0)