Skip to content

Commit 56a2a71

Browse files
committed
resolve: Support imports of associated types and glob imports from traits
1 parent 5ae50d3 commit 56a2a71

20 files changed

+174
-113
lines changed

compiler/rustc_error_codes/src/error_codes/E0253.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
Attempt was made to import an unimportable type. This can happen when trying
24
to import a type from a trait.
35

46
Erroneous code example:
57

6-
```compile_fail,E0253
8+
```
9+
#![feature(import_trait_associated_functions)]
10+
711
mod foo {
812
pub trait MyTrait {
913
type SomeType;

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+24-16
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17701770
span: Span,
17711771
opt_self_ty: Option<Ty<'tcx>>,
17721772
item_def_id: DefId,
1773-
trait_segment: &hir::PathSegment<'tcx>,
1773+
trait_segment: Option<&hir::PathSegment<'tcx>>,
17741774
item_segment: &hir::PathSegment<'tcx>,
17751775
) -> Ty<'tcx> {
17761776
match self.lower_qpath_shared(
@@ -1795,7 +1795,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17951795
span: Span,
17961796
opt_self_ty: Option<Ty<'tcx>>,
17971797
item_def_id: DefId,
1798-
trait_segment: &hir::PathSegment<'tcx>,
1798+
trait_segment: Option<&hir::PathSegment<'tcx>>,
17991799
item_segment: &hir::PathSegment<'tcx>,
18001800
) -> Const<'tcx> {
18011801
match self.lower_qpath_shared(
@@ -1820,7 +1820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
18201820
span: Span,
18211821
opt_self_ty: Option<Ty<'tcx>>,
18221822
item_def_id: DefId,
1823-
trait_segment: &hir::PathSegment<'tcx>,
1823+
trait_segment: Option<&hir::PathSegment<'tcx>>,
18241824
item_segment: &hir::PathSegment<'tcx>,
18251825
assoc_tag: ty::AssocTag,
18261826
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {
@@ -1840,7 +1840,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
18401840
debug!(?self_ty);
18411841

18421842
let trait_ref =
1843-
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
1843+
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment.unwrap(), false);
18441844
debug!(?trait_ref);
18451845

18461846
let item_args =
@@ -2196,16 +2196,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21962196
}
21972197
}
21982198
Res::Def(DefKind::AssocTy, def_id) => {
2199-
debug_assert!(path.segments.len() >= 2);
2200-
let _ = self.prohibit_generic_args(
2201-
path.segments[..path.segments.len() - 2].iter(),
2202-
GenericsArgsErrExtend::None,
2203-
);
2199+
let trait_segment = if path.segments.len() >= 2 {
2200+
let _ = self.prohibit_generic_args(
2201+
path.segments[..path.segments.len() - 2].iter(),
2202+
GenericsArgsErrExtend::None,
2203+
);
2204+
Some(&path.segments[path.segments.len() - 2])
2205+
} else {
2206+
None
2207+
};
22042208
self.lower_qpath_ty(
22052209
span,
22062210
opt_self_ty,
22072211
def_id,
2208-
&path.segments[path.segments.len() - 2],
2212+
trait_segment,
22092213
path.segments.last().unwrap(),
22102214
)
22112215
}
@@ -2413,16 +2417,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24132417
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
24142418
}
24152419
Res::Def(DefKind::AssocConst, did) => {
2416-
debug_assert!(path.segments.len() >= 2);
2417-
let _ = self.prohibit_generic_args(
2418-
path.segments[..path.segments.len() - 2].iter(),
2419-
GenericsArgsErrExtend::None,
2420-
);
2420+
let trait_segment = if path.segments.len() >= 2 {
2421+
let _ = self.prohibit_generic_args(
2422+
path.segments[..path.segments.len() - 2].iter(),
2423+
GenericsArgsErrExtend::None,
2424+
);
2425+
Some(&path.segments[path.segments.len() - 2])
2426+
} else {
2427+
None
2428+
};
24212429
self.lower_qpath_const(
24222430
span,
24232431
opt_self_ty,
24242432
did,
2425-
&path.segments[path.segments.len() - 2],
2433+
trait_segment,
24262434
path.segments.last().unwrap(),
24272435
)
24282436
}

compiler/rustc_resolve/messages.ftl

-7
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,6 @@ resolve_invalid_asm_sym =
218218
.label = is a local variable
219219
.help = `sym` operands must refer to either a function or a static
220220
221-
resolve_is_not_directly_importable =
222-
`{$target}` is not directly importable
223-
.label = cannot be imported directly
224-
225221
resolve_is_private =
226222
{$ident_descr} `{$ident}` is private
227223
.label = private {$ident_descr}
@@ -231,9 +227,6 @@ resolve_item_was_behind_feature =
231227
232228
resolve_item_was_cfg_out = the item is gated here
233229
234-
resolve_items_in_traits_are_not_importable =
235-
items in traits are not importable
236-
237230
resolve_label_with_similar_name_reachable =
238231
a label with a similar name is reachable
239232

compiler/rustc_resolve/src/diagnostics.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -1181,11 +1181,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
11811181
} {
11821182
let in_module_is_extern = !in_module.def_id().is_local();
11831183
in_module.for_each_child(self, |this, ident, ns, name_binding| {
1184-
// avoid non-importable candidates
1185-
if !name_binding.is_importable()
1186-
// FIXME(import_trait_associated_functions): remove this when `import_trait_associated_functions` is stable
1187-
|| name_binding.is_assoc_const_or_fn()
1188-
&& !this.tcx.features().import_trait_associated_functions()
1184+
// Avoid non-importable candidates.
1185+
if name_binding.is_assoc_item()
1186+
&& !this.tcx.features().import_trait_associated_functions()
11891187
{
11901188
return;
11911189
}

compiler/rustc_resolve/src/errors.rs

-16
Original file line numberDiff line numberDiff line change
@@ -781,22 +781,6 @@ pub(crate) struct CannotGlobImportAllCrates {
781781
pub(crate) span: Span,
782782
}
783783

784-
#[derive(Diagnostic)]
785-
#[diag(resolve_items_in_traits_are_not_importable)]
786-
pub(crate) struct ItemsInTraitsAreNotImportable {
787-
#[primary_span]
788-
pub(crate) span: Span,
789-
}
790-
791-
#[derive(Diagnostic)]
792-
#[diag(resolve_is_not_directly_importable, code = E0253)]
793-
pub(crate) struct IsNotDirectlyImportable {
794-
#[primary_span]
795-
#[label]
796-
pub(crate) span: Span,
797-
pub(crate) target: Ident,
798-
}
799-
800784
#[derive(Subdiagnostic)]
801785
#[suggestion(
802786
resolve_unexpected_res_change_ty_to_const_param_sugg,

compiler/rustc_resolve/src/imports.rs

+23-20
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
3030
use crate::errors::{
3131
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
3232
CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
33-
ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
34-
ItemsInTraitsAreNotImportable,
33+
ConsiderAddingMacroExport, ConsiderMarkingAsPub,
3534
};
3635
use crate::{
3736
AmbiguityError, AmbiguityKind, BindingKey, Finalize, ImportSuggestion, Module,
@@ -835,11 +834,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
835834

836835
let parent = import.parent_scope.module;
837836
match source_bindings[ns].get() {
838-
Err(Undetermined) => indeterminate_count += 1,
839-
// Don't update the resolution, because it was never added.
840-
Err(Determined) if target.name == kw::Underscore => {}
841-
Ok(binding) if binding.is_importable() => {
842-
if binding.is_assoc_const_or_fn()
837+
Ok(binding) => {
838+
if binding.is_assoc_item()
843839
&& !this.tcx.features().import_trait_associated_functions()
844840
{
845841
feature_err(
@@ -850,21 +846,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
850846
)
851847
.emit();
852848
}
849+
853850
let imported_binding = this.import(binding, import);
854851
target_bindings[ns].set(Some(imported_binding));
855852
this.define(parent, target, ns, imported_binding);
856853
}
857-
source_binding @ (Ok(..) | Err(Determined)) => {
858-
if source_binding.is_ok() {
859-
this.dcx()
860-
.create_err(IsNotDirectlyImportable { span: import.span, target })
861-
.emit();
854+
Err(Determined) => {
855+
// Don't update the resolution for underscores, because it was never added.
856+
if target.name != kw::Underscore {
857+
let key = BindingKey::new(target, ns);
858+
this.update_resolution(parent, key, false, |_, resolution| {
859+
resolution.single_imports.swap_remove(&import);
860+
});
862861
}
863-
let key = BindingKey::new(target, ns);
864-
this.update_resolution(parent, key, false, |_, resolution| {
865-
resolution.single_imports.swap_remove(&import);
866-
});
867862
}
863+
Err(Undetermined) => indeterminate_count += 1,
868864
}
869865
}
870866
});
@@ -1428,10 +1424,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
14281424
return;
14291425
};
14301426

1431-
if module.is_trait() {
1432-
self.dcx().emit_err(ItemsInTraitsAreNotImportable { span: import.span });
1433-
return;
1434-
} else if module == import.parent_scope.module {
1427+
if module.is_trait() && !self.tcx.features().import_trait_associated_functions() {
1428+
feature_err(
1429+
self.tcx.sess,
1430+
sym::import_trait_associated_functions,
1431+
import.span,
1432+
"`use` associated items of traits is unstable",
1433+
)
1434+
.emit();
1435+
}
1436+
1437+
if module == import.parent_scope.module {
14351438
return;
14361439
} else if is_prelude {
14371440
self.prelude = Some(module);

compiler/rustc_resolve/src/lib.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -948,14 +948,8 @@ impl<'ra> NameBindingData<'ra> {
948948
}
949949
}
950950

951-
fn is_importable(&self) -> bool {
952-
!matches!(self.res(), Res::Def(DefKind::AssocTy, _))
953-
}
954-
955-
// FIXME(import_trait_associated_functions): associate `const` or `fn` are not importable unless
956-
// the feature `import_trait_associated_functions` is enable
957-
fn is_assoc_const_or_fn(&self) -> bool {
958-
matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn, _))
951+
fn is_assoc_item(&self) -> bool {
952+
matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _))
959953
}
960954

961955
fn macro_kind(&self) -> Option<MacroKind> {

tests/ui/error-codes/E0253.rs

-10
This file was deleted.

tests/ui/error-codes/E0253.stderr

-9
This file was deleted.

tests/ui/feature-gates/feature-gate-import-trait-associated-functions.rs

+3
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,7 @@ fn f() {
6060
let t: Option<S> = DEFAULT;
6161
}
6262

63+
trait Glob {}
64+
use Glob::*; //~ ERROR `use` associated items of traits is unstable
65+
6366
fn main() {}

tests/ui/feature-gates/feature-gate-import-trait-associated-functions.stderr

+11-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ LL | use super::A::{self, DEFAULT, new};
4848
= help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable
4949
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
5050

51-
error: aborting due to 5 previous errors
51+
error[E0658]: `use` associated items of traits is unstable
52+
--> $DIR/feature-gate-import-trait-associated-functions.rs:64:5
53+
|
54+
LL | use Glob::*;
55+
| ^^^^^^^
56+
|
57+
= note: see issue #134691 <https://github.com./rust-lang/rust/issues/134691> for more information
58+
= help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable
59+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
60+
61+
error: aborting due to 6 previous errors
5262

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

tests/ui/imports/issue-30560.rs

-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,4 @@ use Alias::*; //~ ERROR unresolved import `Alias` [E0432]
33

44
use std::io::Result::*; //~ ERROR unresolved import `std::io::Result` [E0432]
55

6-
trait T {}
7-
use T::*; //~ ERROR items in traits are not importable
8-
96
fn main() {}

tests/ui/imports/issue-30560.stderr

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
error: items in traits are not importable
2-
--> $DIR/issue-30560.rs:7:5
3-
|
4-
LL | use T::*;
5-
| ^^^^
6-
71
error[E0432]: unresolved import `Alias`
82
--> $DIR/issue-30560.rs:2:5
93
|
@@ -16,6 +10,6 @@ error[E0432]: unresolved import `std::io::Result`
1610
LL | use std::io::Result::*;
1711
| ^^^^^^ `Result` is a type alias, not a module
1812

19-
error: aborting due to 3 previous errors
13+
error: aborting due to 2 previous errors
2014

2115
For more information about this error, try `rustc --explain E0432`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(import_trait_associated_functions)]
2+
#![feature(min_generic_const_args)]
3+
#![allow(incomplete_features)]
4+
5+
trait Trait {
6+
type AssocTy;
7+
const CONST: usize;
8+
}
9+
10+
use Trait::AssocTy;
11+
type Alias1 = AssocTy; //~ ERROR ambiguous associated type
12+
type Alias2 = self::AssocTy; //~ ERROR ambiguous associated type
13+
14+
use Trait::CONST;
15+
type Alias3 = [u8; CONST]; //~ ERROR ambiguous associated constant
16+
type Alias4 = [u8; self::CONST]; //~ ERROR ambiguous associated constant
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
error[E0223]: ambiguous associated type
2+
--> $DIR/import_trait_associated_item_bad.rs:11:15
3+
|
4+
LL | type Alias1 = AssocTy;
5+
| ^^^^^^^
6+
|
7+
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
8+
|
9+
LL | type Alias1 = <Example as Trait>::AssocTy;
10+
| ++++++++++++++++++++
11+
12+
error[E0223]: ambiguous associated type
13+
--> $DIR/import_trait_associated_item_bad.rs:12:15
14+
|
15+
LL | type Alias2 = self::AssocTy;
16+
| ^^^^^^^^^^^^^
17+
|
18+
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
19+
|
20+
LL - type Alias2 = self::AssocTy;
21+
LL + type Alias2 = <Example as Trait>::AssocTy;
22+
|
23+
24+
error[E0223]: ambiguous associated constant
25+
--> $DIR/import_trait_associated_item_bad.rs:15:20
26+
|
27+
LL | type Alias3 = [u8; CONST];
28+
| ^^^^^
29+
|
30+
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
31+
|
32+
LL | type Alias3 = [u8; <Example as Trait>::CONST];
33+
| ++++++++++++++++++++
34+
35+
error[E0223]: ambiguous associated constant
36+
--> $DIR/import_trait_associated_item_bad.rs:16:20
37+
|
38+
LL | type Alias4 = [u8; self::CONST];
39+
| ^^^^^^^^^^^
40+
|
41+
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
42+
|
43+
LL - type Alias4 = [u8; self::CONST];
44+
LL + type Alias4 = [u8; <Example as Trait>::CONST];
45+
|
46+
47+
error: aborting due to 4 previous errors
48+
49+
For more information about this error, try `rustc --explain E0223`.

0 commit comments

Comments
 (0)