Skip to content

Commit 28f1cf4

Browse files
committed
rustc_typeck: don't use Result for get_type_parameter_bounds and ensure_super_predicates.
1 parent 4649f73 commit 28f1cf4

16 files changed

+266
-295
lines changed

src/librustc/dep_graph/dep_node.rs

+4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub enum DepNode<D: Clone + Debug> {
109109
// predicates for an item wind up in `ItemSignature`).
110110
AssociatedItems(D),
111111
ItemSignature(D),
112+
TypeParamPredicates((D, D)),
112113
SizedConstraint(D),
113114
AssociatedItemDefIds(D),
114115
InherentImpls(D),
@@ -259,6 +260,9 @@ impl<D: Clone + Debug> DepNode<D> {
259260
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
260261
AssociatedItems(ref d) => op(d).map(AssociatedItems),
261262
ItemSignature(ref d) => op(d).map(ItemSignature),
263+
TypeParamPredicates((ref item, ref param)) => {
264+
Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
265+
}
262266
SizedConstraint(ref d) => op(d).map(SizedConstraint),
263267
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
264268
InherentImpls(ref d) => op(d).map(InherentImpls),

src/librustc/diagnostics.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,23 @@ error. To resolve it, add an `else` block having the same type as the `if`
13901390
block.
13911391
"##,
13921392

1393+
E0391: r##"
1394+
This error indicates that some types or traits depend on each other
1395+
and therefore cannot be constructed.
1396+
1397+
The following example contains a circular dependency between two traits:
1398+
1399+
```compile_fail,E0391
1400+
trait FirstTrait : SecondTrait {
1401+
1402+
}
1403+
1404+
trait SecondTrait : FirstTrait {
1405+
1406+
}
1407+
```
1408+
"##,
1409+
13931410
E0398: r##"
13941411
In Rust 1.3, the default object lifetime bounds are expected to change, as
13951412
described in RFC #1156 [1]. You are getting a warning because the compiler

src/librustc/hir/map/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,30 @@ impl<'hir> Map<'hir> {
437437
self.local_def_id(self.body_owner(id))
438438
}
439439

440+
pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
441+
match self.get(id) {
442+
NodeItem(&Item { node: ItemTrait(..), .. }) => id,
443+
NodeTyParam(_) => self.get_parent_node(id),
444+
_ => {
445+
bug!("ty_param_owner: {} not a type parameter",
446+
self.node_to_string(id))
447+
}
448+
}
449+
}
450+
451+
pub fn ty_param_name(&self, id: NodeId) -> Name {
452+
match self.get(id) {
453+
NodeItem(&Item { node: ItemTrait(..), .. }) => {
454+
keywords::SelfType.name()
455+
}
456+
NodeTyParam(tp) => tp.name,
457+
_ => {
458+
bug!("ty_param_name: {} not a type parameter",
459+
self.node_to_string(id))
460+
}
461+
}
462+
}
463+
440464
/// Get the attributes on the krate. This is preferable to
441465
/// invoking `krate.attrs` because it registers a tighter
442466
/// dep-graph access.

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#![feature(rustc_diagnostic_macros)]
4040
#![feature(rustc_private)]
4141
#![feature(slice_patterns)]
42+
#![feature(specialization)]
4243
#![feature(staged_api)]
4344
#![feature(unboxed_closures)]
4445

src/librustc/ty/maps.rs

+95-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_data_structures::indexed_vec::IndexVec;
2020
use std::cell::RefCell;
2121
use std::rc::Rc;
2222
use syntax::attr;
23+
use syntax_pos::Span;
2324

2425
trait Key {
2526
fn map_crate(&self) -> CrateNum;
@@ -31,13 +32,105 @@ impl Key for DefId {
3132
}
3233
}
3334

35+
impl Key for (DefId, DefId) {
36+
fn map_crate(&self) -> CrateNum {
37+
self.0.krate
38+
}
39+
}
40+
41+
trait Value<'tcx>: Sized {
42+
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
43+
}
44+
45+
impl<'tcx, T> Value<'tcx> for T {
46+
default fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> T {
47+
tcx.sess.abort_if_errors();
48+
bug!("Value::from_cycle_error called without errors");
49+
}
50+
}
51+
52+
impl<'tcx, T: Default> Value<'tcx> for T {
53+
default fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> T {
54+
T::default()
55+
}
56+
}
57+
58+
impl<'tcx> Value<'tcx> for Ty<'tcx> {
59+
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
60+
tcx.types.err
61+
}
62+
}
63+
64+
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
65+
fn report_cycle(self, span: Span, cycle: &[(Span, Query)]) {
66+
assert!(!cycle.is_empty());
67+
68+
let mut err = struct_span_err!(self.sess, span, E0391,
69+
"unsupported cyclic reference between types/traits detected");
70+
err.span_label(span, &format!("cyclic reference"));
71+
72+
err.span_note(cycle[0].0, &format!("the cycle begins when {}...",
73+
cycle[0].1.describe(self)));
74+
75+
for &(span, ref query) in &cycle[1..] {
76+
err.span_note(span, &format!("...which then requires {}...",
77+
query.describe(self)));
78+
}
79+
80+
err.note(&format!("...which then again requires {}, completing the cycle.",
81+
cycle[0].1.describe(self)));
82+
83+
err.emit();
84+
}
85+
86+
pub fn cycle_check<F, R>(self, span: Span, query: Query, compute: F) -> R
87+
where F: FnOnce() -> R
88+
{
89+
{
90+
let mut stack = self.maps.query_stack.borrow_mut();
91+
if let Some((i, _)) = stack.iter().enumerate().rev()
92+
.find(|&(_, &(_, ref q))| *q == query) {
93+
let cycle = &stack[i..];
94+
self.report_cycle(span, cycle);
95+
return R::from_cycle_error(self.global_tcx());
96+
}
97+
stack.push((span, query));
98+
}
99+
100+
let result = compute();
101+
102+
self.maps.query_stack.borrow_mut().pop();
103+
result
104+
}
105+
}
106+
107+
impl Query {
108+
fn describe(&self, tcx: TyCtxt) -> String {
109+
match *self {
110+
Query::ty(def_id) => {
111+
format!("processing `{}`", tcx.item_path_str(def_id))
112+
}
113+
Query::super_predicates(def_id) => {
114+
format!("computing the supertraits of `{}`",
115+
tcx.item_path_str(def_id))
116+
}
117+
Query::type_param_predicates((_, def_id)) => {
118+
let id = tcx.hir.as_local_node_id(def_id).unwrap();
119+
format!("computing the bounds for type parameter `{}`",
120+
tcx.hir.ty_param_name(id))
121+
}
122+
_ => bug!("unexpected `{:?}`", self)
123+
}
124+
}
125+
}
126+
34127
macro_rules! define_maps {
35128
(<$tcx:tt>
36129
$($(#[$attr:meta])*
37130
pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
38131
pub struct Maps<$tcx> {
39132
providers: IndexVec<CrateNum, Providers<$tcx>>,
40-
pub query_stack: RefCell<Vec<Query>>,
133+
pub query_stack: RefCell<Vec<(Span, Query)>>,
41134
$($(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
42135
}
43136

@@ -129,7 +222,7 @@ define_maps! { <'tcx>
129222

130223
/// To avoid cycles within the predicates of a single item we compute
131224
/// per-type-parameter predicates for resolving `T::AssocTy`.
132-
pub type_param_predicates: ItemSignature(DefId)
225+
pub type_param_predicates: TypeParamPredicates((DefId, DefId))
133226
-> ty::GenericPredicates<'tcx>,
134227

135228
pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ impl Generics {
669669
}
670670

671671
/// Bounds on generics.
672-
#[derive(Clone)]
672+
#[derive(Clone, Default)]
673673
pub struct GenericPredicates<'tcx> {
674674
pub parent: Option<DefId>,
675675
pub predicates: Vec<Predicate<'tcx>>,

src/librustc_typeck/astconv.rs

+20-36
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,12 @@ pub trait AstConv<'gcx, 'tcx> {
6464
/// Ensure that the super-predicates for the trait with the given
6565
/// id are available and also for the transitive set of
6666
/// super-predicates.
67-
fn ensure_super_predicates(&self, span: Span, id: DefId)
68-
-> Result<(), ErrorReported>;
67+
fn ensure_super_predicates(&self, span: Span, id: DefId);
6968

7069
/// Returns the set of bounds in scope for the type parameter with
7170
/// the given id.
72-
fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId)
73-
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>;
71+
fn get_type_parameter_bounds(&self, span: Span, def_id: DefId)
72+
-> Vec<ty::Predicate<'tcx>>;
7473

7574
/// Return an (optional) substitution to convert bound type parameters that
7675
/// are in scope into free ones. This function should only return Some
@@ -599,7 +598,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
599598

600599
// Otherwise, we have to walk through the supertraits to find
601600
// those that do.
602-
self.ensure_super_predicates(binding.span, trait_ref.def_id())?;
601+
self.ensure_super_predicates(binding.span, trait_ref.def_id());
603602

604603
let candidates =
605604
traits::supertraits(tcx, trait_ref.clone())
@@ -685,10 +684,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
685684
})
686685
});
687686

688-
// ensure the super predicates and stop if we encountered an error
689-
if self.ensure_super_predicates(span, principal.def_id()).is_err() {
690-
return tcx.types.err;
691-
}
687+
// ensure the super predicates
688+
self.ensure_super_predicates(span, principal.def_id());
692689

693690
// check that there are no gross object safety violations,
694691
// most importantly, that the supertraits don't contain Self,
@@ -774,29 +771,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
774771
}
775772

776773
// Search for a bound on a type parameter which includes the associated item
777-
// given by assoc_name. ty_param_node_id is the node id for the type parameter
778-
// (which might be `Self`, but only if it is the `Self` of a trait, not an
779-
// impl). This function will fail if there are no suitable bounds or there is
774+
// given by `assoc_name`. `ty_param_def_id` is the `DefId` for the type parameter
775+
// This function will fail if there are no suitable bounds or there is
780776
// any ambiguity.
781777
fn find_bound_for_assoc_item(&self,
782-
ty_param_node_id: ast::NodeId,
783-
ty_param_name: ast::Name,
778+
ty_param_def_id: DefId,
784779
assoc_name: ast::Name,
785780
span: Span)
786781
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
787782
{
788783
let tcx = self.tcx();
789784

790-
let bounds = match self.get_type_parameter_bounds(span, ty_param_node_id) {
791-
Ok(v) => v,
792-
Err(ErrorReported) => {
793-
return Err(ErrorReported);
794-
}
795-
};
785+
let bounds: Vec<_> = self.get_type_parameter_bounds(span, ty_param_def_id)
786+
.into_iter().filter_map(|p| p.to_opt_poly_trait_ref()).collect();
796787

797-
// Ensure the super predicates and stop if we encountered an error.
798-
if bounds.iter().any(|b| self.ensure_super_predicates(span, b.def_id()).is_err()) {
799-
return Err(ErrorReported);
788+
// Ensure the super predicates.
789+
for b in &bounds {
790+
self.ensure_super_predicates(span, b.def_id());
800791
}
801792

802793
// Check that there is exactly one way to find an associated type with the
@@ -805,8 +796,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
805796
traits::transitive_bounds(tcx, &bounds)
806797
.filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name));
807798

799+
let param_node_id = tcx.hir.as_local_node_id(ty_param_def_id).unwrap();
800+
let param_name = tcx.hir.ty_param_name(param_node_id);
808801
self.one_bound_for_assoc_type(suitable_bounds,
809-
&ty_param_name.as_str(),
802+
&param_name.as_str(),
810803
&assoc_name.as_str(),
811804
span)
812805
}
@@ -914,9 +907,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
914907
trait_ref
915908
};
916909

917-
if self.ensure_super_predicates(span, trait_ref.def_id).is_err() {
918-
return (tcx.types.err, Def::Err);
919-
}
910+
self.ensure_super_predicates(span, trait_ref.def_id);
920911

921912
let candidates =
922913
traits::supertraits(tcx, ty::Binder(trait_ref))
@@ -933,12 +924,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
933924
}
934925
(&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) |
935926
(&ty::TyParam(_), Def::TyParam(param_did)) => {
936-
let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap();
937-
let param_name = ::ty_param_name(tcx, param_node_id);
938-
match self.find_bound_for_assoc_item(param_node_id,
939-
param_name,
940-
assoc_name,
941-
span) {
927+
match self.find_bound_for_assoc_item(param_did, assoc_name, span) {
942928
Ok(bound) => bound,
943929
Err(ErrorReported) => return (tcx.types.err, Def::Err),
944930
}
@@ -1375,9 +1361,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
13751361
existential_predicates);
13761362

13771363
if let Some(principal) = existential_predicates.principal() {
1378-
if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) {
1379-
return Some(tcx.mk_region(ty::ReStatic));
1380-
}
1364+
self.ensure_super_predicates(span, principal.def_id());
13811365
}
13821366

13831367
// No explicit region bound specified. Therefore, examine trait

0 commit comments

Comments
 (0)