resolve: Support imports of associated types and glob imports from traits
This commit is contained in:
parent
db074a06fe
commit
3eee3dad5c
20 changed files with 168 additions and 113 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
@ -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(
|
||||
|
|
@ -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> {
|
||||
|
|
@ -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 =
|
||||
|
|
@ -2196,16 +2196,17 @@ 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 let [modules @ .., trait_, _item] = path.segments {
|
||||
let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None);
|
||||
Some(trait_)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.lower_qpath_ty(
|
||||
span,
|
||||
opt_self_ty,
|
||||
def_id,
|
||||
&path.segments[path.segments.len() - 2],
|
||||
trait_segment,
|
||||
path.segments.last().unwrap(),
|
||||
)
|
||||
}
|
||||
|
|
@ -2413,16 +2414,17 @@ 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 let [modules @ .., trait_, _item] = path.segments {
|
||||
let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None);
|
||||
Some(trait_)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.lower_qpath_const(
|
||||
span,
|
||||
opt_self_ty,
|
||||
did,
|
||||
&path.segments[path.segments.len() - 2],
|
||||
trait_segment,
|
||||
path.segments.last().unwrap(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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(
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -949,14 +949,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> {
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
mod foo {
|
||||
pub trait MyTrait {
|
||||
type SomeType;
|
||||
}
|
||||
}
|
||||
|
||||
use foo::MyTrait::SomeType;
|
||||
//~^ ERROR E0253
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
error[E0253]: `SomeType` is not directly importable
|
||||
--> $DIR/E0253.rs:7:5
|
||||
|
|
||||
LL | use foo::MyTrait::SomeType;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0253`.
|
||||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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,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() {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
@ -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
tests/ui/use/import_trait_associated_item_bad.rs
Normal file
18
tests/ui/use/import_trait_associated_item_bad.rs
Normal file
|
|
@ -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
tests/ui/use/import_trait_associated_item_bad.stderr
Normal file
49
tests/ui/use/import_trait_associated_item_bad.stderr
Normal file
|
|
@ -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`.
|
||||
17
tests/ui/use/import_trait_associated_item_glob.rs
Normal file
17
tests/ui/use/import_trait_associated_item_glob.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
//@ check-pass
|
||||
|
||||
#![feature(import_trait_associated_functions)]
|
||||
|
||||
trait Trait: Default {
|
||||
fn f() -> Self { Default::default() }
|
||||
fn g() -> Self { Default::default() }
|
||||
}
|
||||
|
||||
impl Trait for u8 {}
|
||||
|
||||
use Trait::*;
|
||||
|
||||
fn main() {
|
||||
let _: u8 = f();
|
||||
let _: u8 = g();
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ use use_from_trait_xc::Trait::foo;
|
|||
//~^ ERROR `use` associated items of traits is unstable [E0658]
|
||||
|
||||
use use_from_trait_xc::Trait::Assoc;
|
||||
//~^ ERROR `Assoc` is not directly importable
|
||||
//~^ ERROR `use` associated items of traits is unstable [E0658]
|
||||
|
||||
use use_from_trait_xc::Trait::CONST;
|
||||
//~^ ERROR `use` associated items of traits is unstable [E0658]
|
||||
|
|
|
|||
|
|
@ -8,11 +8,15 @@ LL | use use_from_trait_xc::Trait::foo;
|
|||
= 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[E0253]: `Assoc` is not directly importable
|
||||
error[E0658]: `use` associated items of traits is unstable
|
||||
--> $DIR/use-from-trait-xc.rs:8:5
|
||||
|
|
||||
LL | use use_from_trait_xc::Trait::Assoc;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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[E0658]: `use` associated items of traits is unstable
|
||||
--> $DIR/use-from-trait-xc.rs:11:5
|
||||
|
|
@ -74,5 +78,5 @@ LL | struct Foo;
|
|||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0253, E0432, E0603, E0658.
|
||||
For more information about an error, try `rustc --explain E0253`.
|
||||
Some errors have detailed explanations: E0432, E0603, E0658.
|
||||
For more information about an error, try `rustc --explain E0432`.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use Trait::foo; //~ ERROR `use` associated items of traits is unstable [E0658]
|
||||
use Trait::Assoc; //~ ERROR `Assoc` is not directly importable
|
||||
use Trait::Assoc; //~ ERROR `use` associated items of traits is unstable [E0658]
|
||||
use Trait::C; //~ ERROR `use` associated items of traits is unstable [E0658]
|
||||
|
||||
use Foo::new; //~ ERROR unresolved import `Foo` [E0432]
|
||||
|
|
|
|||
|
|
@ -8,11 +8,15 @@ LL | use Trait::foo;
|
|||
= 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[E0253]: `Assoc` is not directly importable
|
||||
error[E0658]: `use` associated items of traits is unstable
|
||||
--> $DIR/use-from-trait.rs:2:5
|
||||
|
|
||||
LL | use Trait::Assoc;
|
||||
| ^^^^^^^^^^^^ cannot be imported directly
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= 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[E0658]: `use` associated items of traits is unstable
|
||||
--> $DIR/use-from-trait.rs:3:5
|
||||
|
|
@ -38,5 +42,5 @@ LL | use Foo::C2;
|
|||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0253, E0432, E0658.
|
||||
For more information about an error, try `rustc --explain E0253`.
|
||||
Some errors have detailed explanations: E0432, E0658.
|
||||
For more information about an error, try `rustc --explain E0432`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue