Skip to content

Commit 3ef8935

Browse files
committed
Make synthetic RPITIT assoc ty name handling more rigorous.
Currently it relies on special treatment of `kw::Empty`, which is really easy to get wrong. This commit makes the special case clearer in the type system by using `Option`. It's a bit clumsy, but the synthetic name handling itself is a bit clumsy; better to make it explicit than sneak it in. Fixes #133426.
1 parent 5dd8614 commit 3ef8935

File tree

9 files changed

+84
-36
lines changed

9 files changed

+84
-36
lines changed

compiler/rustc_hir/src/def.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ impl DefKind {
254254
}
255255

256256
// Some `DefKind`s require a name, some don't. Panics if one is needed but
257-
// not provided.
257+
// not provided. (`AssocTy` is an exception, see below.)
258258
pub fn def_path_data(self, name: Option<Symbol>) -> DefPathData {
259259
match self {
260260
DefKind::Mod
@@ -266,9 +266,13 @@ impl DefKind {
266266
| DefKind::TyAlias
267267
| DefKind::ForeignTy
268268
| DefKind::TraitAlias
269-
| DefKind::AssocTy
270269
| DefKind::TyParam
271-
| DefKind::ExternCrate => DefPathData::TypeNs(name.unwrap()),
270+
| DefKind::ExternCrate => DefPathData::TypeNs(Some(name.unwrap())),
271+
272+
// An associated type names will be missing for an RPITIT. It will
273+
// later be given a name with `synthetic` in it, if necessary.
274+
DefKind::AssocTy => DefPathData::TypeNs(name),
275+
272276
// It's not exactly an anon const, but wrt DefPathData, there
273277
// is no difference.
274278
DefKind::Static { nested: true, .. } => DefPathData::AnonConst,

compiler/rustc_hir/src/definitions.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,9 @@ pub enum DefPathData {
271271
Use,
272272
/// A global asm item.
273273
GlobalAsm,
274-
/// Something in the type namespace.
275-
TypeNs(Symbol),
274+
/// Something in the type namespace. Will be empty for RPITIT associated
275+
/// types, which are given a synthetic name later, if necessary.
276+
TypeNs(Option<Symbol>),
276277
/// Something in the value namespace.
277278
ValueNs(Symbol),
278279
/// Something in the macro namespace.
@@ -410,8 +411,9 @@ impl DefPathData {
410411
pub fn get_opt_name(&self) -> Option<Symbol> {
411412
use self::DefPathData::*;
412413
match *self {
413-
TypeNs(name) if name == kw::Empty => None,
414-
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
414+
TypeNs(name) => name,
415+
416+
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
415417

416418
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
417419
| OpaqueTy => None,
@@ -421,12 +423,14 @@ impl DefPathData {
421423
pub fn name(&self) -> DefPathDataName {
422424
use self::DefPathData::*;
423425
match *self {
424-
TypeNs(name) if name == kw::Empty => {
425-
DefPathDataName::Anon { namespace: sym::synthetic }
426-
}
427-
TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => {
428-
DefPathDataName::Named(name)
426+
TypeNs(name) => {
427+
if let Some(name) = name {
428+
DefPathDataName::Named(name)
429+
} else {
430+
DefPathDataName::Anon { namespace: sym::synthetic }
431+
}
429432
}
433+
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => DefPathDataName::Named(name),
430434
// Note that this does not show up in user print-outs.
431435
CrateRoot => DefPathDataName::Anon { namespace: kw::Crate },
432436
Impl => DefPathDataName::Anon { namespace: kw::Impl },

compiler/rustc_middle/src/ty/print/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
554554
// the children of the visible parent (as was done when computing
555555
// `visible_parent_map`), looking for the specific child we currently have and then
556556
// have access to the re-exported name.
557-
DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => {
557+
DefPathData::TypeNs(Some(ref mut name)) if Some(visible_parent) != actual_parent => {
558558
// Item might be re-exported several times, but filter for the one
559559
// that's public and whose identifier isn't `_`.
560560
let reexport = self
@@ -575,7 +575,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
575575
}
576576
// Re-exported `extern crate` (#43189).
577577
DefPathData::CrateRoot => {
578-
data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate));
578+
data = DefPathData::TypeNs(Some(self.tcx().crate_name(def_id.krate)));
579579
}
580580
_ => {}
581581
}

compiler/rustc_middle/src/ty/significant_drop_order.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ fn true_significant_drop_ty<'tcx>(
2323

2424
match key.disambiguated_data.data {
2525
rustc_hir::definitions::DefPathData::CrateRoot => {
26-
name_rev.push(tcx.crate_name(did.krate))
26+
name_rev.push(tcx.crate_name(did.krate));
27+
}
28+
rustc_hir::definitions::DefPathData::TypeNs(symbol) => {
29+
name_rev.push(symbol.unwrap());
2730
}
28-
rustc_hir::definitions::DefPathData::TypeNs(symbol) => name_rev.push(symbol),
2931
_ => return None,
3032
}
3133
if let Some(parent) = key.parent {

compiler/rustc_ty_utils/src/assoc.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ fn associated_type_for_impl_trait_in_trait(
252252
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
253253

254254
let span = tcx.def_span(opaque_ty_def_id);
255-
// FIXME: `kw::Empty` gets special treatment by `DefPathData`'s methods.
256-
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, Some(kw::Empty), DefKind::AssocTy);
255+
// No name because this is a synthetic associated type.
256+
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, None, DefKind::AssocTy);
257257

258258
let local_def_id = trait_assoc_ty.def_id();
259259
let def_id = local_def_id.to_def_id();
@@ -305,9 +305,8 @@ fn associated_type_for_impl_trait_in_impl(
305305
hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
306306
hir::FnRetTy::Return(ty) => ty.span,
307307
};
308-
// FIXME: `kw::Empty` gets special treatment by `DefPathData`'s methods.
309-
let impl_assoc_ty =
310-
tcx.at(span).create_def(impl_local_def_id, Some(kw::Empty), DefKind::AssocTy);
308+
// No name because this is a synthetic associated type.
309+
let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, None, DefKind::AssocTy);
311310

312311
let local_def_id = impl_assoc_ty.def_id();
313312
let def_id = local_def_id.to_def_id();

src/tools/clippy/clippy_utils/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3489,7 +3489,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
34893489
// a::b::c ::d::sym refers to
34903490
// e::f::sym:: ::
34913491
// result should be super::super::super::super::e::f
3492-
if let DefPathData::TypeNs(s) = l {
3492+
if let DefPathData::TypeNs(Some(s)) = l {
34933493
path.push(s.to_string());
34943494
}
34953495
if let DefPathData::TypeNs(_) = r {
@@ -3500,7 +3500,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
35003500
// a::b::sym:: :: refers to
35013501
// c::d::e ::f::sym
35023502
// when looking at `f`
3503-
Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()),
3503+
Left(DefPathData::TypeNs(Some(sym))) => path.push(sym.to_string()),
35043504
// consider:
35053505
// a::b::c ::d::sym refers to
35063506
// e::f::sym:: ::
@@ -3514,7 +3514,7 @@ fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> St
35143514
// `super` chain would be too long, just use the absolute path instead
35153515
once(String::from("crate"))
35163516
.chain(to.data.iter().filter_map(|el| {
3517-
if let DefPathData::TypeNs(sym) = el.data {
3517+
if let DefPathData::TypeNs(Some(sym)) = el.data {
35183518
Some(sym.to_string())
35193519
} else {
35203520
None

tests/crashes/133426.rs

-12
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! Test for the crash in #133426, caused by an empty symbol being used for a
2+
//! type name.
3+
4+
#![allow(incomplete_features)]
5+
#![feature(never_patterns)]
6+
7+
fn a(
8+
_: impl Iterator<
9+
Item = [(); {
10+
match *todo!() { ! }; //~ ERROR type `!` cannot be dereferenced
11+
}],
12+
>,
13+
) {
14+
}
15+
16+
fn b(_: impl Iterator<Item = { match 0 { ! } }>) {}
17+
//~^ ERROR associated const equality is incomplete
18+
//~| ERROR expected type, found constant
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0658]: associated const equality is incomplete
2+
--> $DIR/no-name-for-DefPath-issue-133426.rs:16:23
3+
|
4+
LL | fn b(_: impl Iterator<Item = { match 0 { ! } }>) {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
8+
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
11+
error[E0614]: type `!` cannot be dereferenced
12+
--> $DIR/no-name-for-DefPath-issue-133426.rs:10:19
13+
|
14+
LL | match *todo!() { ! };
15+
| ^^^^^^^^ can't be dereferenced
16+
17+
error: expected type, found constant
18+
--> $DIR/no-name-for-DefPath-issue-133426.rs:16:30
19+
|
20+
LL | fn b(_: impl Iterator<Item = { match 0 { ! } }>) {}
21+
| ---- ^^^^^^^^^^^^^^^^^ unexpected constant
22+
| |
23+
| expected a type because of this associated type
24+
|
25+
note: the associated type is defined here
26+
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
27+
28+
error: aborting due to 3 previous errors
29+
30+
Some errors have detailed explanations: E0614, E0658.
31+
For more information about an error, try `rustc --explain E0614`.

0 commit comments

Comments
 (0)