Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove interior mutability from TraitDef by turning fields into queries #41911

Merged
merged 10 commits into from
May 18, 2017
Merged
41 changes: 16 additions & 25 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use infer::type_variable::TypeVariableOrigin;
use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
use syntax::ast;
use syntax::symbol::Symbol;
use syntax_pos::DUMMY_SP;
use ty::subst::Subst;
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
Expand Down Expand Up @@ -1324,32 +1323,24 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(

// This function may be called while we are still building the
// specialization graph that is queried below (via TraidDef::ancestors()),
// so, in order to avoid infinite recursion, we detect this case by
// seeing if a query of the specialization graph fails with a cycle error.
// If we are in cycle, and thus still building the graph, we perform a
// reduced version of the associated item lookup that does not need the
// specialization graph.
let specialization_graph_complete =
ty::queries::specialization_graph_of::try_get(tcx,
DUMMY_SP,
trait_def_id).is_ok();
if !specialization_graph_complete {
let impl_node = specialization_graph::Node::Impl(impl_def_id);
for item in impl_node.items(tcx) {
if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
return Some(specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
item: item,
});
}
// so, in order to avoid unnecessary infinite recursion, we manually look
// for the associated item at the given impl.
// If there is no such item in that impl, this function will fail with a
// cycle error if the specialization graph is currently being built.
let impl_node = specialization_graph::Node::Impl(impl_def_id);
for item in impl_node.items(tcx) {
if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name {
return Some(specialization_graph::NodeItem {
node: specialization_graph::Node::Impl(impl_def_id),
item: item,
});
}
None
} else {
trait_def
.ancestors(tcx, impl_def_id)
.defs(tcx, assoc_ty_name, ty::AssociatedKind::Type)
.next()
}

trait_def
.ancestors(tcx, impl_def_id)
.defs(tcx, assoc_ty_name, ty::AssociatedKind::Type)
.next()
}

// # Cache
Expand Down
34 changes: 34 additions & 0 deletions src/test/compile-fail/coherence-inherited-assoc-ty-cycle-err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Formerly this ICEd with the following message:
// Tried to project an inherited associated type during coherence checking,
// which is currently not supported.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is that message in the source? Could that codepath be removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It here:

span_bug!(obligation.cause.span,

But it has this nice, long comment which made me reluctant to remove it. I could move the comment to assoc_ty_def(), make its return value non-optional, and then remove the branch though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, moving the comment should be fine.

//
// No we expect to run into a more user-friendly cycle error instead.

#![feature(specialization)]

trait Trait<T> { type Assoc; }
//~^ unsupported cyclic reference between types/traits detected [E0391]

impl<T> Trait<T> for Vec<T> {
type Assoc = ();
}

impl Trait<u8> for Vec<u8> {}

impl<T> Trait<T> for String {
type Assoc = ();
}

impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {}

fn main() {}
33 changes: 33 additions & 0 deletions src/test/run-pass/specialization/assoc-ty-graph-cycle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Make sure we don't crash with a cycle error during coherence.

#![feature(specialization)]

trait Trait<T> {
type Assoc;
}

impl<T> Trait<T> for Vec<T> {
default type Assoc = ();
}

impl Trait<u8> for Vec<u8> {
type Assoc = u8;
}

impl<T> Trait<T> for String {
type Assoc = ();
}

impl Trait<<Vec<u8> as Trait<u8>>::Assoc> for String {}

fn main() {}