Skip to content

resolve: Support imports of associated types and glob imports from traits #138712

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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: 5 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0253.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
#### Note: this error code is no longer emitted by the compiler.

Attempt was made to import an unimportable type. This can happen when trying
to import a type from a trait.

Erroneous code example:

```compile_fail,E0253
```
#![feature(import_trait_associated_functions)]

mod foo {
pub trait MyTrait {
type SomeType;
Expand Down
40 changes: 24 additions & 16 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1770,7 +1770,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
opt_self_ty: Option<Ty<'tcx>>,
item_def_id: DefId,
trait_segment: &hir::PathSegment<'tcx>,
trait_segment: Option<&hir::PathSegment<'tcx>>,
item_segment: &hir::PathSegment<'tcx>,
) -> Ty<'tcx> {
match self.lower_qpath_shared(
Expand All @@ -1795,7 +1795,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
opt_self_ty: Option<Ty<'tcx>>,
item_def_id: DefId,
trait_segment: &hir::PathSegment<'tcx>,
trait_segment: Option<&hir::PathSegment<'tcx>>,
item_segment: &hir::PathSegment<'tcx>,
) -> Const<'tcx> {
match self.lower_qpath_shared(
Expand All @@ -1820,7 +1820,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span: Span,
opt_self_ty: Option<Ty<'tcx>>,
item_def_id: DefId,
trait_segment: &hir::PathSegment<'tcx>,
trait_segment: Option<&hir::PathSegment<'tcx>>,
item_segment: &hir::PathSegment<'tcx>,
assoc_tag: ty::AssocTag,
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed> {
Expand All @@ -1840,7 +1840,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
debug!(?self_ty);

let trait_ref =
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment.unwrap(), false);
debug!(?trait_ref);

let item_args =
Expand Down Expand Up @@ -2196,16 +2196,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}
Res::Def(DefKind::AssocTy, def_id) => {
debug_assert!(path.segments.len() >= 2);
let _ = self.prohibit_generic_args(
path.segments[..path.segments.len() - 2].iter(),
GenericsArgsErrExtend::None,
);
let trait_segment = if path.segments.len() >= 2 {
let _ = self.prohibit_generic_args(
path.segments[..path.segments.len() - 2].iter(),
GenericsArgsErrExtend::None,
);
Some(&path.segments[path.segments.len() - 2])
} else {
None
};
self.lower_qpath_ty(
span,
opt_self_ty,
def_id,
&path.segments[path.segments.len() - 2],
trait_segment,
path.segments.last().unwrap(),
)
}
Expand Down Expand Up @@ -2413,16 +2417,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
}
Res::Def(DefKind::AssocConst, did) => {
debug_assert!(path.segments.len() >= 2);
let _ = self.prohibit_generic_args(
path.segments[..path.segments.len() - 2].iter(),
GenericsArgsErrExtend::None,
);
let trait_segment = if path.segments.len() >= 2 {
let _ = self.prohibit_generic_args(
path.segments[..path.segments.len() - 2].iter(),
GenericsArgsErrExtend::None,
);
Some(&path.segments[path.segments.len() - 2])
} else {
None
};
self.lower_qpath_const(
span,
opt_self_ty,
did,
&path.segments[path.segments.len() - 2],
trait_segment,
path.segments.last().unwrap(),
)
}
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_resolve/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -218,10 +218,6 @@ resolve_invalid_asm_sym =
.label = is a local variable
.help = `sym` operands must refer to either a function or a static

resolve_is_not_directly_importable =
`{$target}` is not directly importable
.label = cannot be imported directly

resolve_is_private =
{$ident_descr} `{$ident}` is private
.label = private {$ident_descr}
Expand All @@ -231,9 +227,6 @@ resolve_item_was_behind_feature =

resolve_item_was_cfg_out = the item is gated here

resolve_items_in_traits_are_not_importable =
items in traits are not importable

resolve_label_with_similar_name_reachable =
a label with a similar name is reachable

Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1181,11 +1181,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
} {
let in_module_is_extern = !in_module.def_id().is_local();
in_module.for_each_child(self, |this, ident, ns, name_binding| {
// avoid non-importable candidates
if !name_binding.is_importable()
// FIXME(import_trait_associated_functions): remove this when `import_trait_associated_functions` is stable
|| name_binding.is_assoc_const_or_fn()
&& !this.tcx.features().import_trait_associated_functions()
// Avoid non-importable candidates.
if name_binding.is_assoc_item()
&& !this.tcx.features().import_trait_associated_functions()
{
return;
}
Expand Down
16 changes: 0 additions & 16 deletions compiler/rustc_resolve/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,22 +781,6 @@ pub(crate) struct CannotGlobImportAllCrates {
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(resolve_items_in_traits_are_not_importable)]
pub(crate) struct ItemsInTraitsAreNotImportable {
#[primary_span]
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(resolve_is_not_directly_importable, code = E0253)]
pub(crate) struct IsNotDirectlyImportable {
#[primary_span]
#[label]
pub(crate) span: Span,
pub(crate) target: Ident,
}

#[derive(Subdiagnostic)]
#[suggestion(
resolve_unexpected_res_change_ty_to_const_param_sugg,
Expand Down
43 changes: 23 additions & 20 deletions compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
use crate::errors::{
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
ItemsInTraitsAreNotImportable,
ConsiderAddingMacroExport, ConsiderMarkingAsPub,
};
use crate::{
AmbiguityError, AmbiguityKind, BindingKey, Finalize, ImportSuggestion, Module,
Expand Down Expand Up @@ -835,11 +834,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

let parent = import.parent_scope.module;
match source_bindings[ns].get() {
Err(Undetermined) => indeterminate_count += 1,
// Don't update the resolution, because it was never added.
Err(Determined) if target.name == kw::Underscore => {}
Ok(binding) if binding.is_importable() => {
if binding.is_assoc_const_or_fn()
Ok(binding) => {
if binding.is_assoc_item()
&& !this.tcx.features().import_trait_associated_functions()
{
feature_err(
Expand All @@ -850,21 +846,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
)
.emit();
}

let imported_binding = this.import(binding, import);
target_bindings[ns].set(Some(imported_binding));
this.define(parent, target, ns, imported_binding);
}
source_binding @ (Ok(..) | Err(Determined)) => {
if source_binding.is_ok() {
this.dcx()
.create_err(IsNotDirectlyImportable { span: import.span, target })
.emit();
Err(Determined) => {
// Don't update the resolution for underscores, because it was never added.
if target.name != kw::Underscore {
let key = BindingKey::new(target, ns);
this.update_resolution(parent, key, false, |_, resolution| {
resolution.single_imports.swap_remove(&import);
});
}
let key = BindingKey::new(target, ns);
this.update_resolution(parent, key, false, |_, resolution| {
resolution.single_imports.swap_remove(&import);
});
}
Err(Undetermined) => indeterminate_count += 1,
}
}
});
Expand Down Expand Up @@ -1428,10 +1424,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return;
};

if module.is_trait() {
self.dcx().emit_err(ItemsInTraitsAreNotImportable { span: import.span });
return;
} else if module == import.parent_scope.module {
if module.is_trait() && !self.tcx.features().import_trait_associated_functions() {
feature_err(
self.tcx.sess,
sym::import_trait_associated_functions,
import.span,
"`use` associated items of traits is unstable",
)
.emit();
}

if module == import.parent_scope.module {
return;
} else if is_prelude {
self.prelude = Some(module);
Expand Down
10 changes: 2 additions & 8 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,14 +948,8 @@ impl<'ra> NameBindingData<'ra> {
}
}

fn is_importable(&self) -> bool {
!matches!(self.res(), Res::Def(DefKind::AssocTy, _))
}

// FIXME(import_trait_associated_functions): associate `const` or `fn` are not importable unless
// the feature `import_trait_associated_functions` is enable
fn is_assoc_const_or_fn(&self) -> bool {
matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn, _))
fn is_assoc_item(&self) -> bool {
matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _))
}

fn macro_kind(&self) -> Option<MacroKind> {
Expand Down
10 changes: 0 additions & 10 deletions tests/ui/error-codes/E0253.rs

This file was deleted.

9 changes: 0 additions & 9 deletions tests/ui/error-codes/E0253.stderr

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,7 @@ fn f() {
let t: Option<S> = DEFAULT;
}

trait Glob {}
use Glob::*; //~ ERROR `use` associated items of traits is unstable

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

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

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0658`.
3 changes: 0 additions & 3 deletions tests/ui/imports/issue-30560.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,4 @@ use Alias::*; //~ ERROR unresolved import `Alias` [E0432]

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

trait T {}
use T::*; //~ ERROR items in traits are not importable

fn main() {}
8 changes: 1 addition & 7 deletions tests/ui/imports/issue-30560.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
error: items in traits are not importable
--> $DIR/issue-30560.rs:7:5
|
LL | use T::*;
| ^^^^

error[E0432]: unresolved import `Alias`
--> $DIR/issue-30560.rs:2:5
|
Expand All @@ -16,6 +10,6 @@ error[E0432]: unresolved import `std::io::Result`
LL | use std::io::Result::*;
| ^^^^^^ `Result` is a type alias, not a module

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0432`.
18 changes: 18 additions & 0 deletions tests/ui/use/import_trait_associated_item_bad.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![feature(import_trait_associated_functions)]
#![feature(min_generic_const_args)]
#![allow(incomplete_features)]

trait Trait {
type AssocTy;
const CONST: usize;
}

use Trait::AssocTy;
type Alias1 = AssocTy; //~ ERROR ambiguous associated type
type Alias2 = self::AssocTy; //~ ERROR ambiguous associated type

use Trait::CONST;
type Alias3 = [u8; CONST]; //~ ERROR ambiguous associated constant
type Alias4 = [u8; self::CONST]; //~ ERROR ambiguous associated constant

fn main() {}
49 changes: 49 additions & 0 deletions tests/ui/use/import_trait_associated_item_bad.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
error[E0223]: ambiguous associated type
--> $DIR/import_trait_associated_item_bad.rs:11:15
|
LL | type Alias1 = AssocTy;
| ^^^^^^^
|
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
|
LL | type Alias1 = <Example as Trait>::AssocTy;
| ++++++++++++++++++++

error[E0223]: ambiguous associated type
--> $DIR/import_trait_associated_item_bad.rs:12:15
|
LL | type Alias2 = self::AssocTy;
| ^^^^^^^^^^^^^
|
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
|
LL - type Alias2 = self::AssocTy;
LL + type Alias2 = <Example as Trait>::AssocTy;
|

error[E0223]: ambiguous associated constant
--> $DIR/import_trait_associated_item_bad.rs:15:20
|
LL | type Alias3 = [u8; CONST];
| ^^^^^
|
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
|
LL | type Alias3 = [u8; <Example as Trait>::CONST];
| ++++++++++++++++++++

error[E0223]: ambiguous associated constant
--> $DIR/import_trait_associated_item_bad.rs:16:20
|
LL | type Alias4 = [u8; self::CONST];
| ^^^^^^^^^^^
|
help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
|
LL - type Alias4 = [u8; self::CONST];
LL + type Alias4 = [u8; <Example as Trait>::CONST];
|

error: aborting due to 4 previous errors

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