Skip to content

Commit

Permalink
Delegation: fix ICE on duplicated associative items
Browse files Browse the repository at this point in the history
  • Loading branch information
Bryanskiy committed Mar 15, 2024
1 parent 6639672 commit 8409bbc
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 13 deletions.
28 changes: 15 additions & 13 deletions compiler/rustc_ast_lowering/src/item.rs
Expand Up @@ -373,9 +373,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
(trait_ref, lowered_ty)
});

let new_impl_items = self
.arena
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
let new_impl_items = self.with_trait_impl(trait_ref.is_some(), |this| {
this.arena.alloc_from_iter(
impl_items.iter().map(|item| this.lower_impl_item_ref(item)),
)
});

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

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

match ctxt {
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
AssocCtxt::Impl => self.with_trait_impl(is_in_trait_impl, |this| {
hir::OwnerNode::ImplItem(this.lower_impl_item(item))
}),
}
}

Expand Down Expand Up @@ -978,13 +983,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
}

fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
let trait_item_def_id = self
.resolver
.get_partial_res(i.id)
.map(|r| r.expect_full_res().opt_def_id())
.unwrap_or(None);
self.is_in_trait_impl = trait_item_def_id.is_some();

hir::ImplItemRef {
id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
Expand All @@ -1000,7 +998,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
},
AssocItemKind::MacCall(..) => unimplemented!(),
},
trait_item_def_id,
trait_item_def_id: self
.resolver
.get_partial_res(i.id)
.map(|r| r.expect_full_res().opt_def_id())
.unwrap_or(None),
}
}

Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_ast_lowering/src/lib.rs
Expand Up @@ -882,6 +882,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
result
}

fn with_trait_impl<T>(&mut self, is_trait_impl: bool, f: impl FnOnce(&mut Self) -> T) -> T {
let was_in_trait_impl = self.is_in_trait_impl;
self.is_in_trait_impl = is_trait_impl;

let result = f(self);

self.is_in_trait_impl = was_in_trait_impl;

result
}

fn with_new_scopes<T>(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T {
let current_item = self.current_item;
self.current_item = Some(scope_span);
Expand Down
23 changes: 23 additions & 0 deletions tests/ui/delegation/duplicate-definition-inside-trait-impl.rs
@@ -0,0 +1,23 @@
#![feature(fn_delegation)]
//~^ WARN the feature `fn_delegation` is incomplete

trait Trait {
fn foo(&self) -> u32 { 0 }
}

struct F;
struct S;

mod to_reuse {
use crate::S;

pub fn foo(_: &S) -> u32 { 0 }
}

impl Trait for S {
reuse to_reuse::foo { self }
reuse Trait::foo;
//~^ ERROR duplicate definitions with name `foo`
}

fn main() {}
23 changes: 23 additions & 0 deletions tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr
@@ -0,0 +1,23 @@
error[E0201]: duplicate definitions with name `foo`:
--> $DIR/duplicate-definition-inside-trait-impl.rs:19:5
|
LL | fn foo(&self) -> u32 { 0 }
| -------------------------- item in trait
...
LL | reuse to_reuse::foo { self }
| ---------------------------- previous definition here
LL | reuse Trait::foo;
| ^^^^^^^^^^^^^^^^^ duplicate definition

warning: the feature `fn_delegation` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/duplicate-definition-inside-trait-impl.rs:1:12
|
LL | #![feature(fn_delegation)]
| ^^^^^^^^^^^^^
|
= note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information
= note: `#[warn(incomplete_features)]` on by default

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0201`.

0 comments on commit 8409bbc

Please sign in to comment.