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

Give return-position impl traits in trait a (synthetic) name to avoid name collisions with new lowering strategy #109499

Merged
merged 3 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions compiler/rustc_hir/src/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,8 @@ impl DefPathData {
match *self {
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),

// We use this name when collecting `ModChild`s.
// FIXME this could probably be removed with some refactoring to the name resolver.
ImplTraitAssocTy => Some(kw::Empty),

Impl | ForeignMod | CrateRoot | Use | GlobalAsm | ClosureExpr | Ctor | AnonConst
| ImplTrait => None,
| ImplTrait | ImplTraitAssocTy => None,
}
}

Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
} else {
// Iterate over all children.
for child_index in self.root.tables.children.get(self, id).unwrap().decode(self) {
yield self.get_mod_child(child_index, sess);
if self.root.tables.opt_rpitit_info.get(self, child_index).is_none() {
yield self.get_mod_child(child_index, sess);
}
}

if let Some(reexports) = self.root.tables.module_reexports.get(self, id) {
Expand Down Expand Up @@ -1067,8 +1069,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}

fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
let name = self.item_name(id);

let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
kw::Empty
} else {
self.item_name(id)
};
let (kind, has_self) = match self.def_kind(id) {
DefKind::AssocConst => (ty::AssocKind::Const, false),
DefKind::AssocFn => (ty::AssocKind::Fn, self.get_fn_has_self_parameter(id, sess)),
Expand Down
35 changes: 19 additions & 16 deletions compiler/rustc_ty_utils/src/assoc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
Expand Down Expand Up @@ -196,20 +197,26 @@ fn associated_types_for_impl_traits_in_associated_fn(

match tcx.def_kind(parent_def_id) {
DefKind::Trait => {
struct RPITVisitor {
rpits: Vec<LocalDefId>,
struct RPITVisitor<'tcx> {
rpits: FxIndexSet<LocalDefId>,
tcx: TyCtxt<'tcx>,
}

impl<'v> Visitor<'v> for RPITVisitor {
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind {
self.rpits.push(item_id.owner_id.def_id)
impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind
&& self.rpits.insert(item_id.owner_id.def_id)
{
let opaque_item = self.tcx.hir().expect_item(item_id.owner_id.def_id).expect_opaque_ty();
for bound in opaque_item.bounds {
intravisit::walk_param_bound(self, bound);
}
}
intravisit::walk_ty(self, ty)
}
}

let mut visitor = RPITVisitor { rpits: Vec::new() };
let mut visitor = RPITVisitor { tcx, rpits: FxIndexSet::default() };

if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
visitor.visit_fn_ret_ty(output);
Expand All @@ -227,13 +234,9 @@ fn associated_types_for_impl_traits_in_associated_fn(

tcx.arena.alloc_from_iter(
tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
move |trait_assoc_def_id| {
associated_type_for_impl_trait_in_impl(
tcx,
trait_assoc_def_id.expect_local(),
fn_def_id,
)
.to_def_id()
move |&trait_assoc_def_id| {
associated_type_for_impl_trait_in_impl(tcx, trait_assoc_def_id, fn_def_id)
.to_def_id()
},
),
)
Expand Down Expand Up @@ -355,7 +358,7 @@ fn associated_type_for_impl_trait_in_trait(
/// that inherits properties that we infer from the method and the associated type.
fn associated_type_for_impl_trait_in_impl(
tcx: TyCtxt<'_>,
trait_assoc_def_id: LocalDefId,
trait_assoc_def_id: DefId,
impl_fn_def_id: LocalDefId,
) -> LocalDefId {
let impl_local_def_id = tcx.local_parent(impl_fn_def_id);
Expand All @@ -380,7 +383,7 @@ fn associated_type_for_impl_trait_in_impl(
name: kw::Empty,
kind: ty::AssocKind::Type,
def_id,
trait_item_def_id: Some(trait_assoc_def_id.to_def_id()),
trait_item_def_id: Some(trait_assoc_def_id),
container: ty::ImplContainer,
fn_has_self_parameter: false,
opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
Expand Down
7 changes: 4 additions & 3 deletions tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

#![feature(return_position_impl_trait_in_trait)]

use std::ops::Deref;

pub trait Foo {
fn bar() -> impl Sized;
fn bar() -> impl Deref<Target = impl Sized>;
}

pub struct Foreign;

impl Foo for Foreign {
fn bar() {}
fn bar() -> &'static () { &() }
}
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/in-trait/doesnt-satisfy.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ note: required by a bound in `Foo::{opaque#0}`
--> $DIR/doesnt-satisfy.rs:8:22
|
LL | fn bar() -> impl std::fmt::Display;
| ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::`
| ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`

error: aborting due to previous error

Expand Down
14 changes: 12 additions & 2 deletions tests/ui/impl-trait/in-trait/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,17 @@

extern crate rpitit;

use std::sync::Arc;

// Implement an RPITIT from another crate.
struct Local;
impl rpitit::Foo for Local {
fn bar() -> Arc<String> { Arc::new(String::new()) }
}

fn main() {
// Witness an RPITIT from another crate
let () = <rpitit::Foreign as rpitit::Foo>::bar();
// Witness an RPITIT from another crate.
let &() = <rpitit::Foreign as rpitit::Foo>::bar();

let x: Arc<String> = <Local as rpitit::Foo>::bar();
}
2 changes: 2 additions & 0 deletions tests/ui/impl-trait/in-trait/nested-rpitit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// check-pass
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
// revisions: current next

#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error[E0277]: the trait bound `Something: Termination` is not satisfied
--> $DIR/issue-103052-2.rs:12:22
--> $DIR/issue-103052-2.rs:15:22
|
LL | fn main() -> Something {
| ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
|
note: required by a bound in `Main::main::{opaque#0}`
--> $DIR/issue-103052-2.rs:6:27
--> $DIR/issue-103052-2.rs:9:27
|
LL | fn main() -> impl std::process::Termination;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}`
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/rfc-1937-termination-trait/issue-103052-2.next.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0277]: the trait bound `Something: Termination` is not satisfied
--> $DIR/issue-103052-2.rs:15:22
|
LL | fn main() -> Something {
| ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
|
note: required by a bound in `Main::{opaque#0}`
--> $DIR/issue-103052-2.rs:9:27
|
LL | fn main() -> impl std::process::Termination;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
6 changes: 5 additions & 1 deletion tests/ui/rfc-1937-termination-trait/issue-103052-2.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
// revisions: current next

#![feature(return_position_impl_trait_in_trait)]
#![allow(incomplete_features)]

Expand All @@ -9,7 +12,8 @@ mod child {
struct Something;

impl Main for () {
fn main() -> Something { //~ ERROR the trait bound `Something: Termination` is not satisfied
fn main() -> Something {
//~^ ERROR the trait bound `Something: Termination` is not satisfied
Something
}
}
Expand Down