Reattach all grandchildren when constructing specialization graph.
This commit fixes the issue #50452.
This commit is contained in:
parent
96734ae0d4
commit
3a8e0afdbc
3 changed files with 80 additions and 8 deletions
|
@ -73,8 +73,8 @@ enum Inserted {
|
|||
/// The impl was inserted as a new child in this group of children.
|
||||
BecameNewSibling(Option<OverlapError>),
|
||||
|
||||
/// The impl should replace an existing impl X, because the impl specializes X.
|
||||
ReplaceChild(DefId),
|
||||
/// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
|
||||
ReplaceChildren(Vec<DefId>),
|
||||
|
||||
/// The impl is a specialization of an existing child.
|
||||
ShouldRecurseOn(DefId),
|
||||
|
@ -124,6 +124,7 @@ impl<'a, 'gcx, 'tcx> Children {
|
|||
-> Result<Inserted, OverlapError>
|
||||
{
|
||||
let mut last_lint = None;
|
||||
let mut replace_children = Vec::new();
|
||||
|
||||
debug!(
|
||||
"insert(impl_def_id={:?}, simplified_self={:?})",
|
||||
|
@ -194,7 +195,7 @@ impl<'a, 'gcx, 'tcx> Children {
|
|||
debug!("placing as parent of TraitRef {:?}",
|
||||
tcx.impl_trait_ref(possible_sibling).unwrap());
|
||||
|
||||
return Ok(Inserted::ReplaceChild(possible_sibling));
|
||||
replace_children.push(possible_sibling);
|
||||
} else {
|
||||
if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
|
||||
traits::overlapping_impls(
|
||||
|
@ -211,6 +212,10 @@ impl<'a, 'gcx, 'tcx> Children {
|
|||
}
|
||||
}
|
||||
|
||||
if !replace_children.is_empty() {
|
||||
return Ok(Inserted::ReplaceChildren(replace_children));
|
||||
}
|
||||
|
||||
// no overlap with any potential siblings, so add as a new sibling
|
||||
debug!("placing as new sibling");
|
||||
self.insert_blindly(tcx, impl_def_id);
|
||||
|
@ -282,7 +287,7 @@ impl<'a, 'gcx, 'tcx> Graph {
|
|||
last_lint = opt_lint;
|
||||
break;
|
||||
}
|
||||
ReplaceChild(grand_child_to_be) => {
|
||||
ReplaceChildren(grand_children_to_be) => {
|
||||
// We currently have
|
||||
//
|
||||
// P
|
||||
|
@ -302,17 +307,23 @@ impl<'a, 'gcx, 'tcx> Graph {
|
|||
let siblings = self.children
|
||||
.get_mut(&parent)
|
||||
.unwrap();
|
||||
siblings.remove_existing(tcx, grand_child_to_be);
|
||||
for &grand_child_to_be in &grand_children_to_be {
|
||||
siblings.remove_existing(tcx, grand_child_to_be);
|
||||
}
|
||||
siblings.insert_blindly(tcx, impl_def_id);
|
||||
}
|
||||
|
||||
// Set G's parent to N and N's parent to P
|
||||
self.parent.insert(grand_child_to_be, impl_def_id);
|
||||
for &grand_child_to_be in &grand_children_to_be {
|
||||
self.parent.insert(grand_child_to_be, impl_def_id);
|
||||
}
|
||||
self.parent.insert(impl_def_id, parent);
|
||||
|
||||
// Add G as N's child.
|
||||
self.children.entry(impl_def_id).or_default()
|
||||
.insert_blindly(tcx, grand_child_to_be);
|
||||
for &grand_child_to_be in &grand_children_to_be {
|
||||
self.children.entry(impl_def_id).or_default()
|
||||
.insert_blindly(tcx, grand_child_to_be);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ShouldRecurseOn(new_parent) => {
|
||||
|
|
32
src/test/compile-fail/specialization/issue-50452.rs
Normal file
32
src/test/compile-fail/specialization/issue-50452.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// compile-fail
|
||||
|
||||
#![feature(specialization)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
impl Foo for i32 {}
|
||||
impl Foo for i64 {
|
||||
fn foo() {}
|
||||
//~^ERROR `foo` specializes an item from a parent `impl`
|
||||
}
|
||||
impl<T> Foo for T {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
i32::foo();
|
||||
i64::foo();
|
||||
u8::foo();
|
||||
}
|
29
src/test/run-pass/specialization/issue-50452.rs
Normal file
29
src/test/run-pass/specialization/issue-50452.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// run-pass
|
||||
|
||||
#![feature(specialization)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
impl Foo for i32 {}
|
||||
impl Foo for i64 {}
|
||||
impl<T> Foo for T {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
i32::foo();
|
||||
i64::foo();
|
||||
u8::foo();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue