Skip to content

Commit 8409bbc

Browse files
committed
Delegation: fix ICE on duplicated associative items
1 parent 6639672 commit 8409bbc

File tree

4 files changed

+72
-13
lines changed

4 files changed

+72
-13
lines changed

compiler/rustc_ast_lowering/src/item.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
373373
(trait_ref, lowered_ty)
374374
});
375375

376-
let new_impl_items = self
377-
.arena
378-
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
376+
let new_impl_items = self.with_trait_impl(trait_ref.is_some(), |this| {
377+
this.arena.alloc_from_iter(
378+
impl_items.iter().map(|item| this.lower_impl_item_ref(item)),
379+
)
380+
});
379381

380382
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
381383
// to not cause an assertion failure inside the `lower_defaultness` function.
@@ -606,9 +608,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
606608
// This is used to track which lifetimes have already been defined,
607609
// and which need to be replicated when lowering an async fn.
608610

611+
let mut is_in_trait_impl = false;
609612
let generics = match parent_hir.node().expect_item().kind {
610613
hir::ItemKind::Impl(impl_) => {
611-
self.is_in_trait_impl = impl_.of_trait.is_some();
614+
is_in_trait_impl = impl_.of_trait.is_some();
612615
&impl_.generics
613616
}
614617
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
@@ -629,7 +632,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
629632

630633
match ctxt {
631634
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
632-
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
635+
AssocCtxt::Impl => self.with_trait_impl(is_in_trait_impl, |this| {
636+
hir::OwnerNode::ImplItem(this.lower_impl_item(item))
637+
}),
633638
}
634639
}
635640

@@ -978,13 +983,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
978983
}
979984

980985
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
981-
let trait_item_def_id = self
982-
.resolver
983-
.get_partial_res(i.id)
984-
.map(|r| r.expect_full_res().opt_def_id())
985-
.unwrap_or(None);
986-
self.is_in_trait_impl = trait_item_def_id.is_some();
987-
988986
hir::ImplItemRef {
989987
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
990988
ident: self.lower_ident(i.ident),
@@ -1000,7 +998,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
1000998
},
1001999
AssocItemKind::MacCall(..) => unimplemented!(),
10021000
},
1003-
trait_item_def_id,
1001+
trait_item_def_id: self
1002+
.resolver
1003+
.get_partial_res(i.id)
1004+
.map(|r| r.expect_full_res().opt_def_id())
1005+
.unwrap_or(None),
10041006
}
10051007
}
10061008

compiler/rustc_ast_lowering/src/lib.rs

+11
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
882882
result
883883
}
884884

885+
fn with_trait_impl<T>(&mut self, is_trait_impl: bool, f: impl FnOnce(&mut Self) -> T) -> T {
886+
let was_in_trait_impl = self.is_in_trait_impl;
887+
self.is_in_trait_impl = is_trait_impl;
888+
889+
let result = f(self);
890+
891+
self.is_in_trait_impl = was_in_trait_impl;
892+
893+
result
894+
}
895+
885896
fn with_new_scopes<T>(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T {
886897
let current_item = self.current_item;
887898
self.current_item = Some(scope_span);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![feature(fn_delegation)]
2+
//~^ WARN the feature `fn_delegation` is incomplete
3+
4+
trait Trait {
5+
fn foo(&self) -> u32 { 0 }
6+
}
7+
8+
struct F;
9+
struct S;
10+
11+
mod to_reuse {
12+
use crate::S;
13+
14+
pub fn foo(_: &S) -> u32 { 0 }
15+
}
16+
17+
impl Trait for S {
18+
reuse to_reuse::foo { self }
19+
reuse Trait::foo;
20+
//~^ ERROR duplicate definitions with name `foo`
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0201]: duplicate definitions with name `foo`:
2+
--> $DIR/duplicate-definition-inside-trait-impl.rs:19:5
3+
|
4+
LL | fn foo(&self) -> u32 { 0 }
5+
| -------------------------- item in trait
6+
...
7+
LL | reuse to_reuse::foo { self }
8+
| ---------------------------- previous definition here
9+
LL | reuse Trait::foo;
10+
| ^^^^^^^^^^^^^^^^^ duplicate definition
11+
12+
warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
13+
--> $DIR/duplicate-definition-inside-trait-impl.rs:1:12
14+
|
15+
LL | #![feature(fn_delegation)]
16+
| ^^^^^^^^^^^^^
17+
|
18+
= note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
19+
= note: `#[warn(incomplete_features)]` on by default
20+
21+
error: aborting due to 1 previous error; 1 warning emitted
22+
23+
For more information about this error, try `rustc --explain E0201`.

0 commit comments

Comments
 (0)