rustc_typeck: don't use Result for get_type_parameter_bounds and ensure_super_predicates.

This commit is contained in:
Eduard-Mihai Burtescu 2017-02-11 19:26:13 +02:00
parent 4649f7387e
commit 28f1cf4262
16 changed files with 265 additions and 294 deletions

View File

@ -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),
@ -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),

View File

@ -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

View File

@ -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.

View File

@ -39,6 +39,7 @@
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(specialization)]
#![feature(staged_api)]
#![feature(unboxed_closures)]

View File

@ -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;
@ -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>>>),*
}
@ -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,

View File

@ -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>>,

View File

@ -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
@ -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())
@ -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,
@ -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
@ -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)
}
@ -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))
@ -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),
}
@ -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

View File

@ -91,7 +91,7 @@ use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
use rustc::ty::{ParamTy, ParameterEnvironment};
use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPolyTraitRef};
use rustc::ty::{self, Ty, TyCtxt, Visibility};
use rustc::ty::{MethodCall, MethodCallee};
use rustc::ty::adjustment;
use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
@ -1366,44 +1366,31 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
self.tcx().lookup_trait_def(id)
}
fn ensure_super_predicates(&self, _: Span, _: DefId) -> Result<(), ErrorReported> {
fn ensure_super_predicates(&self, _: Span, _: DefId) {
// all super predicates are ensured during collect pass
Ok(())
}
fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
Some(&self.parameter_environment.free_substs)
}
fn get_type_parameter_bounds(&self,
_: Span,
node_id: ast::NodeId)
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId)
-> Vec<ty::Predicate<'tcx>>
{
let tcx = self.tcx;
let item_id = ::ty_param_owner(tcx, node_id);
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
let item_id = tcx.hir.ty_param_owner(node_id);
let item_def_id = tcx.hir.local_def_id(item_id);
let generics = tcx.item_generics(item_def_id);
let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index];
let r = self.parameter_environment
.caller_bounds
.iter()
.filter_map(|predicate| {
match *predicate {
ty::Predicate::Trait(ref data) => {
if data.0.self_ty().is_param(index) {
Some(data.to_poly_trait_ref())
} else {
None
}
}
_ => {
None
}
}
})
.collect();
Ok(r)
let index = generics.type_param_to_index[&def_id.index];
self.parameter_environment.caller_bounds.iter().filter(|predicate| {
match **predicate {
ty::Predicate::Trait(ref data) => {
data.0.self_ty().is_param(index)
}
_ => false
}
}).cloned().collect()
}
fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)

View File

@ -70,7 +70,7 @@ use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContai
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::util::IntTypeExt;
use rustc::dep_graph::DepNode;
use util::common::{ErrorReported, MemoizationMap};
use util::common::MemoizationMap;
use util::nodemap::{NodeMap, FxHashMap};
use rustc_const_math::ConstInt;
@ -80,7 +80,7 @@ use std::collections::BTreeMap;
use syntax::{abi, ast, attr};
use syntax::symbol::{Symbol, keywords};
use syntax_pos::Span;
use syntax_pos::{Span, DUMMY_SP};
use rustc::hir::{self, map as hir_map};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@ -231,91 +231,6 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
}
}
fn cycle_check<F,R>(tcx: TyCtxt,
span: Span,
query: ty::maps::Query,
code: F)
-> Result<R,ErrorReported>
where F: FnOnce() -> Result<R,ErrorReported>
{
{
let mut stack = tcx.maps.query_stack.borrow_mut();
if let Some((i, _)) = stack.iter().enumerate().rev().find(|&(_, q)| *q == query) {
let cycle = &stack[i..];
report_cycle(tcx, span, cycle);
return Err(ErrorReported);
}
stack.push(query);
}
let result = code();
tcx.maps.query_stack.borrow_mut().pop();
result
}
fn report_cycle(tcx: TyCtxt,
span: Span,
cycle: &[ty::maps::Query])
{
assert!(!cycle.is_empty());
let mut err = struct_span_err!(tcx.sess, span, E0391,
"unsupported cyclic reference between types/traits detected");
err.span_label(span, &format!("cyclic reference"));
let describe = |query: ty::maps::Query| {
match query {
ty::maps::Query::ty(def_id) => {
format!("processing `{}`", tcx.item_path_str(def_id))
}
ty::maps::Query::super_predicates(def_id) => {
format!("computing the supertraits of `{}`",
tcx.item_path_str(def_id))
}
ty::maps::Query::type_param_predicates(def_id) => {
let id = tcx.hir.as_local_node_id(def_id).unwrap();
format!("the cycle begins when computing the bounds \
for type parameter `{}`",
::ty_param_name(tcx, id))
}
query => span_bug!(span, "unexpected `{:?}`", query)
}
};
err.note(&format!("the cycle begins when {}...",
describe(cycle[0])));
for &query in &cycle[1..] {
err.note(&format!("...which then requires {}...",
describe(query)));
}
err.note(&format!("...which then again requires {}, completing the cycle.",
describe(cycle[0])));
err.emit();
}
/// Ensure that the (transitive) super predicates for
/// `trait_def_id` are available. This will report a cycle error
/// if a trait `X` (transitively) extends itself in some form.
fn ensure_super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
span: Span,
trait_def_id: DefId)
-> Result<(), ErrorReported>
{
cycle_check(tcx, span, ty::maps::Query::super_predicates(trait_def_id), || {
let def_ids = ensure_super_predicates_step(tcx, trait_def_id);
for def_id in def_ids {
ensure_super_predicates(tcx, span, def_id)?;
}
Ok(())
})
}
impl<'a,'tcx> ItemCtxt<'a,'tcx> {
fn to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
AstConv::ast_ty_to_ty(self, ast_ty)
@ -334,9 +249,9 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
}
fn get_item_type(&self, span: Span, id: DefId) -> Ty<'tcx> {
cycle_check(self.tcx, span, ty::maps::Query::ty(id), || {
Ok(type_of_def_id(self.tcx, id))
}).unwrap_or(self.tcx.types.err)
self.tcx.cycle_check(span, ty::maps::Query::ty(id), || {
type_of_def_id(self.tcx, id)
})
}
fn get_trait_def(&self, def_id: DefId) -> &'tcx ty::TraitDef {
@ -349,30 +264,36 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
}
}
/// Ensure that the (transitive) super predicates for
/// `trait_def_id` are available. This will report a cycle error
/// if a trait `X` (transitively) extends itself in some form.
fn ensure_super_predicates(&self,
span: Span,
trait_def_id: DefId)
-> Result<(), ErrorReported>
{
debug!("ensure_super_predicates(trait_def_id={:?})",
trait_def_id);
trait_def_id: DefId) {
if !trait_def_id.is_local() {
// If this trait comes from an external crate, then all of the
// supertraits it may depend on also must come from external
// crates, and hence all of them already have their
// super-predicates "converted" (and available from crate
// meta-data), so there is no need to transitively test them.
return;
}
ensure_super_predicates(self.tcx, span, trait_def_id)
self.tcx.maps.super_predicates.memoize(trait_def_id, || {
self.tcx.cycle_check(span, ty::maps::Query::super_predicates(trait_def_id), || {
super_predicates(self.tcx, trait_def_id)
})
});
}
fn get_type_parameter_bounds(&self,
span: Span,
node_id: ast::NodeId)
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
def_id: DefId)
-> Vec<ty::Predicate<'tcx>>
{
let def_id = self.tcx.hir.local_def_id(node_id);
cycle_check(self.tcx, span, ty::maps::Query::type_param_predicates(def_id), || {
let v = get_type_parameter_bounds(self.tcx, self.item_def_id, node_id)
.into_iter()
.filter_map(|p| p.to_opt_poly_trait_ref())
.collect();
Ok(v)
})
self.tcx.cycle_check(span,
ty::maps::Query::type_param_predicates((self.item_def_id, def_id)),
|| get_type_parameter_bounds(self.tcx, self.item_def_id, def_id))
}
fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
@ -428,7 +349,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
fn get_type_parameter_bounds<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
item_def_id: DefId,
param_id: ast::NodeId)
def_id: DefId)
-> Vec<ty::Predicate<'tcx>>
{
use rustc::hir::map::*;
@ -438,10 +359,12 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
// written inline like `<T:Foo>` or in a where clause like
// `where T:Foo`.
let param_owner_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, param_id));
let param_id = tcx.hir.as_local_node_id(def_id).unwrap();
let param_owner = tcx.hir.ty_param_owner(param_id);
let param_owner_def_id = tcx.hir.local_def_id(param_owner);
let generics = generics_of_def_id(tcx, param_owner_def_id);
let index = generics.type_param_to_index[&tcx.hir.local_def_id(param_id).index];
let ty = tcx.mk_param(index, ::ty_param_name(tcx, param_id));
let index = generics.type_param_to_index[&def_id.index];
let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id));
// Don't look for bounds where the type parameter isn't in scope.
let parent = if item_def_id == param_owner_def_id {
@ -450,8 +373,9 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
generics_of_def_id(tcx, item_def_id).parent
};
let mut results = parent.map_or(vec![], |def_id| {
get_type_parameter_bounds(tcx, def_id, param_id)
let mut results = parent.map_or(vec![], |parent| {
let icx = ItemCtxt::new(tcx, parent);
icx.get_type_parameter_bounds(DUMMY_SP, def_id)
});
let item_node_id = tcx.hir.as_local_node_id(item_def_id).unwrap();
@ -706,8 +630,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) {
hir::ItemTrait(..) => {
generics_of_def_id(tcx, def_id);
trait_def_of_item(tcx, it);
let _: Result<(), ErrorReported> = // any error is already reported, can ignore
ensure_super_predicates(tcx, it.span, def_id);
icx.ensure_super_predicates(it.span, def_id);
predicates_of_item(tcx, it);
},
hir::ItemStruct(ref struct_def, _) |
@ -1025,82 +948,54 @@ fn convert_enum_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
/// Ensures that the super-predicates of the trait with def-id
/// trait_def_id are converted and stored. This does NOT ensure that
/// the transitive super-predicates are converted; that is the job of
/// the `ensure_super_predicates()` method in the `AstConv` impl
/// above. Returns a list of trait def-ids that must be ensured as
/// well to guarantee that the transitive superpredicates are
/// converted.
fn ensure_super_predicates_step<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trait_def_id: DefId)
-> Vec<DefId>
{
debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id);
/// trait_def_id are converted and stored. This also ensures that
/// the transitive super-predicates are converted;
fn super_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
trait_def_id: DefId)
-> ty::GenericPredicates<'tcx> {
debug!("super_predicates(trait_def_id={:?})", trait_def_id);
let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap();
let trait_node_id = if let Some(n) = tcx.hir.as_local_node_id(trait_def_id) {
n
} else {
// If this trait comes from an external crate, then all of the
// supertraits it may depend on also must come from external
// crates, and hence all of them already have their
// super-predicates "converted" (and available from crate
// meta-data), so there is no need to transitively test them.
return Vec::new();
let item = match tcx.hir.get(trait_node_id) {
hir_map::NodeItem(item) => item,
_ => bug!("trait_node_id {} is not an item", trait_node_id)
};
let superpredicates = tcx.maps.super_predicates.borrow().get(&trait_def_id).cloned();
let superpredicates = superpredicates.unwrap_or_else(|| {
let item = match tcx.hir.get(trait_node_id) {
hir_map::NodeItem(item) => item,
_ => bug!("trait_node_id {} is not an item", trait_node_id)
};
let (generics, bounds) = match item.node {
hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
_ => span_bug!(item.span,
"super_predicates invoked on non-trait"),
};
let (generics, bounds) = match item.node {
hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
_ => span_bug!(item.span,
"ensure_super_predicates_step invoked on non-trait"),
};
let icx = ItemCtxt::new(tcx, trait_def_id);
let icx = ItemCtxt::new(tcx, trait_def_id);
// Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
let self_param_ty = tcx.mk_self_type();
let superbounds1 = compute_bounds(&icx,
self_param_ty,
bounds,
SizedByDefault::No,
item.span);
// Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
let self_param_ty = tcx.mk_self_type();
let superbounds1 = compute_bounds(&icx,
self_param_ty,
bounds,
SizedByDefault::No,
item.span);
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
// Convert any explicit superbounds in the where clause,
// e.g. `trait Foo where Self : Bar`:
let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty);
// Convert any explicit superbounds in the where clause,
// e.g. `trait Foo where Self : Bar`:
let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty);
// Combine the two lists to form the complete set of superbounds:
let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect();
// Combine the two lists to form the complete set of superbounds:
let superbounds = superbounds1.into_iter().chain(superbounds2).collect();
let superpredicates = ty::GenericPredicates {
parent: None,
predicates: superbounds
};
debug!("superpredicates for trait {:?} = {:?}",
tcx.hir.local_def_id(item.id),
superpredicates);
// Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits.
for bound in superbounds.iter().filter_map(|p| p.to_opt_poly_trait_ref()) {
icx.ensure_super_predicates(item.span, bound.def_id());
}
tcx.maps.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
superpredicates
});
let def_ids: Vec<_> = superpredicates.predicates
.iter()
.filter_map(|p| p.to_opt_poly_trait_ref())
.map(|tr| tr.def_id())
.collect();
debug!("ensure_super_predicates_step: def_ids={:?}", def_ids);
def_ids
ty::GenericPredicates {
parent: None,
predicates: superbounds
}
}
fn trait_def_of_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) -> &'tcx ty::TraitDef {

View File

@ -3417,23 +3417,6 @@ impl Bar for *mut Foo {
```
"##,
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 {
}
```
"##,
E0392: r##"
This error indicates that a type or lifetime parameter has been declared
but not actually used. Here is an example that demonstrates the error:

View File

@ -116,7 +116,6 @@ use util::common::time;
use syntax::ast;
use syntax::abi::Abi;
use syntax::symbol::keywords;
use syntax_pos::Span;
use std::iter;
@ -170,30 +169,6 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
})
}
fn ty_param_owner(tcx: TyCtxt, id: ast::NodeId) -> ast::NodeId {
match tcx.hir.get(id) {
hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => id,
hir::map::NodeTyParam(_) => tcx.hir.get_parent_node(id),
_ => {
bug!("ty_param_owner: {} not a type parameter",
tcx.hir.node_to_string(id))
}
}
}
fn ty_param_name(tcx: TyCtxt, id: ast::NodeId) -> ast::Name {
match tcx.hir.get(id) {
hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => {
keywords::SelfType.name()
}
hir::map::NodeTyParam(tp) => tp.name,
_ => {
bug!("ty_param_name: {} not a type parameter",
tcx.hir.node_to_string(id))
}
}
}
fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
main_id: ast::NodeId,
main_span: Span) {

View File

@ -26,6 +26,7 @@ struct A<T>
where T : Trait,
T : Add<T::Item>
//~^ ERROR unsupported cyclic reference between types/traits detected
//~| ERROR associated type `Item` not found for `T`
{
data: T
}

View File

@ -12,14 +12,16 @@
// a direct participant in the cycle.
trait A: B {
//~^ ERROR unsupported cyclic reference
//~^ NOTE the cycle begins when computing the supertraits of `B`...
}
trait B: C {
//~^ ERROR unsupported cyclic reference
//~^ NOTE ...which then requires computing the supertraits of `C`...
}
trait C: B { }
//~^ ERROR unsupported cyclic reference
//~| cyclic reference
//~| NOTE ...which then again requires computing the supertraits of `B`, completing the cycle
fn main() { }

View File

@ -9,11 +9,14 @@
// except according to those terms.
trait t1 : t2 {
//~^ ERROR: unsupported cyclic reference between types/traits detected
//~^ NOTE the cycle begins when computing the supertraits of `t1`...
//~| NOTE ...which then requires computing the supertraits of `t2`...
}
trait t2 : t1 {
//~^ ERROR: unsupported cyclic reference between types/traits detected
//~^ ERROR unsupported cyclic reference between types/traits detected
//~| cyclic reference
//~| NOTE ...which then again requires computing the supertraits of `t1`, completing the cycle
}
fn main() { }

View File

@ -10,6 +10,7 @@
trait T : Iterator<Item=Self::Item>
//~^ ERROR unsupported cyclic reference between types/traits detected
//~| ERROR associated type `Item` not found for `Self`
{}
fn main() {}

View File

@ -14,6 +14,7 @@ trait Trait {
}
fn foo<T: Trait<A = T::B>>() { }
//~^ ERROR: unsupported cyclic reference between types/traits detected
//~^ ERROR unsupported cyclic reference between types/traits detected
//~| ERROR associated type `B` not found for `T`
fn main() { }