Skip to content

Commit

Permalink
rustc_typeck: don't use Result for get_type_parameter_bounds and ensu…
Browse files Browse the repository at this point in the history
…re_super_predicates.
  • Loading branch information
eddyb committed Feb 25, 2017
1 parent 4649f73 commit 28f1cf4
Show file tree
Hide file tree
Showing 16 changed files with 266 additions and 295 deletions.
4 changes: 4 additions & 0 deletions src/librustc/dep_graph/dep_node.rs
Expand Up @@ -109,6 +109,7 @@ pub enum DepNode<D: Clone + Debug> {
// predicates for an item wind up in `ItemSignature`).
AssociatedItems(D),
ItemSignature(D),
TypeParamPredicates((D, D)),
SizedConstraint(D),
AssociatedItemDefIds(D),
InherentImpls(D),
Expand Down Expand Up @@ -259,6 +260,9 @@ impl<D: Clone + Debug> DepNode<D> {
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
AssociatedItems(ref d) => op(d).map(AssociatedItems),
ItemSignature(ref d) => op(d).map(ItemSignature),
TypeParamPredicates((ref item, ref param)) => {
Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
}
SizedConstraint(ref d) => op(d).map(SizedConstraint),
AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds),
InherentImpls(ref d) => op(d).map(InherentImpls),
Expand Down
17 changes: 17 additions & 0 deletions src/librustc/diagnostics.rs
Expand Up @@ -1390,6 +1390,23 @@ error. To resolve it, add an `else` block having the same type as the `if`
block.
"##,

E0391: r##"
This error indicates that some types or traits depend on each other
and therefore cannot be constructed.
The following example contains a circular dependency between two traits:
```compile_fail,E0391
trait FirstTrait : SecondTrait {
}
trait SecondTrait : FirstTrait {
}
```
"##,

E0398: r##"
In Rust 1.3, the default object lifetime bounds are expected to change, as
described in RFC #1156 [1]. You are getting a warning because the compiler
Expand Down
24 changes: 24 additions & 0 deletions src/librustc/hir/map/mod.rs
Expand Up @@ -437,6 +437,30 @@ impl<'hir> Map<'hir> {
self.local_def_id(self.body_owner(id))
}

pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
match self.get(id) {
NodeItem(&Item { node: ItemTrait(..), .. }) => id,
NodeTyParam(_) => self.get_parent_node(id),
_ => {
bug!("ty_param_owner: {} not a type parameter",
self.node_to_string(id))
}
}
}

pub fn ty_param_name(&self, id: NodeId) -> Name {
match self.get(id) {
NodeItem(&Item { node: ItemTrait(..), .. }) => {
keywords::SelfType.name()
}
NodeTyParam(tp) => tp.name,
_ => {
bug!("ty_param_name: {} not a type parameter",
self.node_to_string(id))
}
}
}

/// Get the attributes on the krate. This is preferable to
/// invoking `krate.attrs` because it registers a tighter
/// dep-graph access.
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Expand Up @@ -39,6 +39,7 @@
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(unboxed_closures)]

Expand Down
97 changes: 95 additions & 2 deletions src/librustc/ty/maps.rs
Expand Up @@ -20,6 +20,7 @@ use rustc_data_structures::indexed_vec::IndexVec;
use std::cell::RefCell;
use std::rc::Rc;
use syntax::attr;
use syntax_pos::Span;

trait Key {
fn map_crate(&self) -> CrateNum;
Expand All @@ -31,13 +32,105 @@ impl Key for DefId {
}
}

impl Key for (DefId, DefId) {
fn map_crate(&self) -> CrateNum {
self.0.krate
}
}

trait Value<'tcx>: Sized {
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
}

impl<'tcx, T> Value<'tcx> for T {
default fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> T {
tcx.sess.abort_if_errors();
bug!("Value::from_cycle_error called without errors");
}
}

impl<'tcx, T: Default> Value<'tcx> for T {
default fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> T {
T::default()
}
}

impl<'tcx> Value<'tcx> for Ty<'tcx> {
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
tcx.types.err
}
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
fn report_cycle(self, span: Span, cycle: &[(Span, Query)]) {
assert!(!cycle.is_empty());

let mut err = struct_span_err!(self.sess, span, E0391,
"unsupported cyclic reference between types/traits detected");
err.span_label(span, &format!("cyclic reference"));

err.span_note(cycle[0].0, &format!("the cycle begins when {}...",
cycle[0].1.describe(self)));

for &(span, ref query) in &cycle[1..] {
err.span_note(span, &format!("...which then requires {}...",
query.describe(self)));
}

err.note(&format!("...which then again requires {}, completing the cycle.",
cycle[0].1.describe(self)));

err.emit();
}

pub fn cycle_check<F, R>(self, span: Span, query: Query, compute: F) -> R
where F: FnOnce() -> R
{
{
let mut stack = self.maps.query_stack.borrow_mut();
if let Some((i, _)) = stack.iter().enumerate().rev()
.find(|&(_, &(_, ref q))| *q == query) {
let cycle = &stack[i..];
self.report_cycle(span, cycle);
return R::from_cycle_error(self.global_tcx());
}
stack.push((span, query));
}

let result = compute();

self.maps.query_stack.borrow_mut().pop();
result
}
}

impl Query {
fn describe(&self, tcx: TyCtxt) -> String {
match *self {
Query::ty(def_id) => {
format!("processing `{}`", tcx.item_path_str(def_id))
}
Query::super_predicates(def_id) => {
format!("computing the supertraits of `{}`",
tcx.item_path_str(def_id))
}
Query::type_param_predicates((_, def_id)) => {
let id = tcx.hir.as_local_node_id(def_id).unwrap();
format!("computing the bounds for type parameter `{}`",
tcx.hir.ty_param_name(id))
}
_ => bug!("unexpected `{:?}`", self)
}
}
}

macro_rules! define_maps {
(<$tcx:tt>
$($(#[$attr:meta])*
pub $name:ident: $node:ident($K:ty) -> $V:ty),*) => {
pub struct Maps<$tcx> {
providers: IndexVec<CrateNum, Providers<$tcx>>,
pub query_stack: RefCell<Vec<Query>>,
pub query_stack: RefCell<Vec<(Span, Query)>>,
$($(#[$attr])* pub $name: RefCell<DepTrackingMap<queries::$name<$tcx>>>),*
}

Expand Down Expand Up @@ -129,7 +222,7 @@ define_maps! { <'tcx>

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

pub trait_def: ItemSignature(DefId) -> &'tcx ty::TraitDef,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/mod.rs
Expand Up @@ -669,7 +669,7 @@ impl Generics {
}

/// Bounds on generics.
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>,
pub predicates: Vec<Predicate<'tcx>>,
Expand Down
56 changes: 20 additions & 36 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -64,13 +64,12 @@ pub trait AstConv<'gcx, 'tcx> {
/// Ensure that the super-predicates for the trait with the given
/// id are available and also for the transitive set of
/// super-predicates.
fn ensure_super_predicates(&self, span: Span, id: DefId)
-> Result<(), ErrorReported>;
fn ensure_super_predicates(&self, span: Span, id: DefId);

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

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

// Otherwise, we have to walk through the supertraits to find
// those that do.
self.ensure_super_predicates(binding.span, trait_ref.def_id())?;
self.ensure_super_predicates(binding.span, trait_ref.def_id());

let candidates =
traits::supertraits(tcx, trait_ref.clone())
Expand Down Expand Up @@ -685,10 +684,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
})
});

// ensure the super predicates and stop if we encountered an error
if self.ensure_super_predicates(span, principal.def_id()).is_err() {
return tcx.types.err;
}
// ensure the super predicates
self.ensure_super_predicates(span, principal.def_id());

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

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

let bounds = match self.get_type_parameter_bounds(span, ty_param_node_id) {
Ok(v) => v,
Err(ErrorReported) => {
return Err(ErrorReported);
}
};
let bounds: Vec<_> = self.get_type_parameter_bounds(span, ty_param_def_id)
.into_iter().filter_map(|p| p.to_opt_poly_trait_ref()).collect();

// Ensure the super predicates and stop if we encountered an error.
if bounds.iter().any(|b| self.ensure_super_predicates(span, b.def_id()).is_err()) {
return Err(ErrorReported);
// Ensure the super predicates.
for b in &bounds {
self.ensure_super_predicates(span, b.def_id());
}

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

let param_node_id = tcx.hir.as_local_node_id(ty_param_def_id).unwrap();
let param_name = tcx.hir.ty_param_name(param_node_id);
self.one_bound_for_assoc_type(suitable_bounds,
&ty_param_name.as_str(),
&param_name.as_str(),
&assoc_name.as_str(),
span)
}
Expand Down Expand Up @@ -914,9 +907,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
trait_ref
};

if self.ensure_super_predicates(span, trait_ref.def_id).is_err() {
return (tcx.types.err, Def::Err);
}
self.ensure_super_predicates(span, trait_ref.def_id);

let candidates =
traits::supertraits(tcx, ty::Binder(trait_ref))
Expand All @@ -933,12 +924,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
(&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) |
(&ty::TyParam(_), Def::TyParam(param_did)) => {
let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap();
let param_name = ::ty_param_name(tcx, param_node_id);
match self.find_bound_for_assoc_item(param_node_id,
param_name,
assoc_name,
span) {
match self.find_bound_for_assoc_item(param_did, assoc_name, span) {
Ok(bound) => bound,
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
Expand Down Expand Up @@ -1375,9 +1361,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
existential_predicates);

if let Some(principal) = existential_predicates.principal() {
if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) {
return Some(tcx.mk_region(ty::ReStatic));
}
self.ensure_super_predicates(span, principal.def_id());
}

// No explicit region bound specified. Therefore, examine trait
Expand Down

0 comments on commit 28f1cf4

Please sign in to comment.