-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Changes from 8 commits
c2d9b4e
513cc6d
77b7df3
8da2fe8
40a6734
742ebc1
d731b04
0a77a58
42051ce
08660af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -619,8 +619,6 @@ pub fn get_vtable_methods<'a, 'tcx>( | |
debug!("get_vtable_methods({:?})", trait_ref); | ||
|
||
supertraits(tcx, trait_ref).flat_map(move |trait_ref| { | ||
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); | ||
|
||
let trait_methods = tcx.associated_items(trait_ref.def_id()) | ||
.filter(|item| item.kind == ty::AssociatedKind::Method); | ||
|
||
|
@@ -782,3 +780,19 @@ impl<'tcx> TraitObligation<'tcx> { | |
ty::Binder(self.predicate.skip_binder().self_ty()) | ||
} | ||
} | ||
|
||
pub fn provide(providers: &mut ty::maps::Providers) { | ||
*providers = ty::maps::Providers { | ||
is_object_safe: object_safety::is_object_safe_provider, | ||
specialization_graph_of: specialize::specialization_graph_provider, | ||
..*providers | ||
}; | ||
} | ||
|
||
pub fn provide_extern(providers: &mut ty::maps::Providers) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since they're identical I'd use the same function twice. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You think so? It's just a coincidence that they are identical at the moment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes sense. |
||
*providers = ty::maps::Providers { | ||
is_object_safe: object_safety::is_object_safe_provider, | ||
specialization_graph_of: specialize::specialization_graph_provider, | ||
..*providers | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1317,26 +1317,30 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( | |
assoc_ty_name: ast::Name) | ||
-> Option<specialization_graph::NodeItem<ty::AssociatedItem>> | ||
{ | ||
let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id; | ||
let trait_def = selcx.tcx().trait_def(trait_def_id); | ||
|
||
if !trait_def.is_complete(selcx.tcx()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does this work? Do we produce cycle errors in more cases? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what you mean exactly. I don't see a potential cycle here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc @aturon We may be lacking tests here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It needs to be used in the specialization graph of the same trait. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, that makes sense. And I thought the following example might trigger the condition, but it doesn't #![feature(specialization)]
trait Assoc {
type Output;
}
impl<T> Assoc for T {
default type Output = u8;
}
impl Assoc for u32 {
type Output = u32;
}
impl Assoc for u64 {
// Shouldn't this cause a reentrant call?
type Output = <u32 as Assoc>::Output;
}
fn main() {
let _x: <u32 as Assoc>::Output = 0;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the impl header - only Self/params are checked by coherence/specialization. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, the following gives me the error #![feature(specialization)]
trait Assoc {
type Output;
}
impl Assoc for u32 {
type Output = u64;
}
impl Assoc for <u32 as Assoc>::Output {
type Output = u64;
}
fn main() {
let _x: <u64 as Assoc>::Output = 0;
} So that's not really what we are looking for, I guess? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I don't really expect you to be able to project #![feature(specialization)]
use std::vec;
trait Assoc {
type Output;
}
impl Assoc for u32 {
type Output = u64;
}
impl Assoc for <vec::IntoIter<u64> as Iterator>::Item {
type Output = u64;
}
fn main() {
} Interestingly, coherence rejects this example, presumably because of RFC 1214 concerns. I'm not sure that's right, but this example does work today: #![feature(specialization)]
use std::vec;
trait Assoc {
type Output;
}
impl Assoc for u32 {
type Output = u64;
}
impl Assoc for <u32 as Assoc2>::Output {
type Output = u64;
}
trait Assoc2 {
type Output;
}
impl Assoc2 for u32 {
type Output = u64;
}
fn main() {
} That said, I think that would also work in @michaelwoerister's branch, no? |
||
let impl_node = specialization_graph::Node::Impl(impl_def_id); | ||
for item in impl_node.items(selcx.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, | ||
}); | ||
} | ||
let tcx = selcx.tcx(); | ||
let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id; | ||
let trait_def = tcx.trait_def(trait_def_id); | ||
|
||
// 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 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(impl_def_id) | ||
.defs(selcx.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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why you converted this into a single dep-node, rather than keeping it per-trait. It seems like this is losing quite a bit of precision, no?
(That is, if any trait adds an impl, we will consider them all to have changed.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly for ease of implementation and symmetry with the situation in metadata.
DepNode::TraitImpls
has been re-purposed to represent local and remote impls and, with red-green, will take care of stopping invalidation short.Without red-green though you are right, it's losing precision. Want me to make it per-item?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not a big deal.