Skip to content

Commit dc2bdee

Browse files
committed
Implement use associated items of traits
1 parent 32c8a9f commit dc2bdee

File tree

9 files changed

+212
-20
lines changed

9 files changed

+212
-20
lines changed

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@ declare_features! (
519519
(unstable, impl_trait_in_bindings, "1.64.0", Some(63065)),
520520
/// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
521521
(unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
522+
/// Allows `use` associated functions from traits.
523+
(unstable, import_trait_associated_functions, "CURRENT_RUSTC_VERSION", Some(134691)),
522524
/// Allows associated types in inherent impls.
523525
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
524526
/// Allow anonymous constants from an inline `const` block in pattern position

compiler/rustc_resolve/messages.ftl

-4
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,6 @@ resolve_invalid_asm_sym =
221221
.label = is a local variable
222222
.help = `sym` operands must refer to either a function or a static
223223
224-
resolve_is_not_directly_importable =
225-
`{$target}` is not directly importable
226-
.label = cannot be imported directly
227-
228224
resolve_is_private =
229225
{$ident_descr} `{$ident}` is private
230226
.label = private {$ident_descr}

compiler/rustc_resolve/src/errors.rs

-9
Original file line numberDiff line numberDiff line change
@@ -785,15 +785,6 @@ pub(crate) struct ItemsInTraitsAreNotImportable {
785785
pub(crate) span: Span,
786786
}
787787

788-
#[derive(Diagnostic)]
789-
#[diag(resolve_is_not_directly_importable, code = E0253)]
790-
pub(crate) struct IsNotDirectlyImportable {
791-
#[primary_span]
792-
#[label]
793-
pub(crate) span: Span,
794-
pub(crate) target: Ident,
795-
}
796-
797788
#[derive(Subdiagnostic)]
798789
#[suggestion(
799790
resolve_unexpected_res_change_ty_to_const_param_sugg,

compiler/rustc_resolve/src/ident.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15491549
ignore_import,
15501550
)
15511551
.map_err(|(determinacy, _)| determinacy)
1552+
.or_else(|err| {
1553+
// HACK: try to resolve as a trait or type if it's the first segment in a `use` item.
1554+
if ns == TypeNS
1555+
&& ribs.is_none()
1556+
&& segment_idx == 1
1557+
&& let ModuleOrUniformRoot::Module(module) = module
1558+
&& let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
1559+
ident,
1560+
ScopeSet::Late(ns, module, finalize.map(|f| f.node_id)),
1561+
parent_scope,
1562+
finalize,
1563+
finalize.is_some(),
1564+
ignore_binding,
1565+
ignore_import,
1566+
)
1567+
{
1568+
return Ok(binding);
1569+
}
1570+
Err(err)
1571+
})
15521572
} else if let Some(ribs) = ribs
15531573
&& let Some(TypeNS | ValueNS) = opt_ns
15541574
{

compiler/rustc_resolve/src/imports.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ use rustc_session::lint::builtin::{
1717
AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
1818
REDUNDANT_IMPORTS, UNUSED_IMPORTS,
1919
};
20+
use rustc_session::parse::feature_err;
2021
use rustc_span::edit_distance::find_best_match_for_name;
2122
use rustc_span::hygiene::LocalExpnId;
22-
use rustc_span::{Ident, Span, Symbol, kw};
23+
use rustc_span::{Ident, Span, Symbol, kw, sym};
2324
use smallvec::SmallVec;
2425
use tracing::debug;
2526

@@ -29,8 +30,7 @@ use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
2930
use crate::errors::{
3031
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
3132
CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
32-
ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
33-
ItemsInTraitsAreNotImportable,
33+
ConsiderAddingMacroExport, ConsiderMarkingAsPub, ItemsInTraitsAreNotImportable,
3434
};
3535
use crate::{
3636
AmbiguityError, AmbiguityKind, BindingKey, Finalize, ImportSuggestion, Module,
@@ -828,16 +828,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
828828
Err(Undetermined) => indeterminate_count += 1,
829829
// Don't update the resolution, because it was never added.
830830
Err(Determined) if target.name == kw::Underscore => {}
831-
Ok(binding) if binding.is_importable() => {
831+
Ok(binding)
832+
if binding.is_importable()
833+
|| this.tcx.features().import_trait_associated_functions() =>
834+
{
832835
let imported_binding = this.import(binding, import);
833836
target_bindings[ns].set(Some(imported_binding));
834837
this.define(parent, target, ns, imported_binding);
835838
}
836839
source_binding @ (Ok(..) | Err(Determined)) => {
837840
if source_binding.is_ok() {
838-
this.dcx()
839-
.create_err(IsNotDirectlyImportable { span: import.span, target })
840-
.emit();
841+
feature_err(
842+
this.tcx.sess,
843+
sym::import_trait_associated_functions,
844+
import.span,
845+
"`use` associated items of traits is unstable",
846+
)
847+
.emit();
841848
}
842849
let key = BindingKey::new(target, ns);
843850
this.update_resolution(parent, key, false, |_, resolution| {

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,7 @@ symbols! {
10921092
import,
10931093
import_name_type,
10941094
import_shadowing,
1095+
import_trait_associated_functions,
10951096
imported_main,
10961097
in_band_lifetimes,
10971098
include,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use std::collections::HashMap;
2+
3+
use A::{DEFAULT, new};
4+
//~^ ERROR `use` associated items of traits is unstable [E0658]
5+
//~| ERROR `use` associated items of traits is unstable [E0658]
6+
use Default::default;
7+
//~^ ERROR `use` associated items of traits is unstable [E0658]
8+
9+
struct S {
10+
a: HashMap<i32, i32>,
11+
}
12+
13+
impl S {
14+
fn new() -> S {
15+
S { a: default() }
16+
}
17+
}
18+
19+
trait A: Sized {
20+
const DEFAULT: Option<Self> = None;
21+
fn new() -> Self;
22+
fn do_something(&self);
23+
}
24+
25+
mod b {
26+
use super::A::{self, DEFAULT, new};
27+
//~^ ERROR `use` associated items of traits is unstable [E0658]
28+
//~| ERROR `use` associated items of traits is unstable [E0658]
29+
30+
struct B();
31+
32+
impl A for B {
33+
const DEFAULT: Option<Self> = Some(B());
34+
fn new() -> Self {
35+
B()
36+
}
37+
38+
fn do_something(&self) {}
39+
}
40+
41+
fn f() {
42+
let b: B = new();
43+
b.do_something();
44+
let c: B = DEFAULT.unwrap();
45+
}
46+
}
47+
48+
impl A for S {
49+
fn new() -> Self {
50+
S::new()
51+
}
52+
53+
fn do_something(&self) {}
54+
}
55+
56+
fn f() {
57+
let s: S = new();
58+
s.do_something();
59+
let t: Option<S> = DEFAULT;
60+
}
61+
62+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
error[E0658]: `use` associated items of traits is unstable
2+
--> $DIR/feature-gate-import-trait-associated-functions.rs:3:9
3+
|
4+
LL | use A::{DEFAULT, new};
5+
| ^^^^^^^
6+
|
7+
= note: see issue #134691 <https://github.com/rust-lang/rust/issues/134691> for more information
8+
= help: add `#![feature(import_trait_associated_functions)]` 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[E0658]: `use` associated items of traits is unstable
12+
--> $DIR/feature-gate-import-trait-associated-functions.rs:3:18
13+
|
14+
LL | use A::{DEFAULT, new};
15+
| ^^^
16+
|
17+
= note: see issue #134691 <https://github.com/rust-lang/rust/issues/134691> for more information
18+
= help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable
19+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
20+
21+
error[E0658]: `use` associated items of traits is unstable
22+
--> $DIR/feature-gate-import-trait-associated-functions.rs:6:5
23+
|
24+
LL | use Default::default;
25+
| ^^^^^^^^^^^^^^^^
26+
|
27+
= note: see issue #134691 <https://github.com/rust-lang/rust/issues/134691> for more information
28+
= help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable
29+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
30+
31+
error[E0658]: `use` associated items of traits is unstable
32+
--> $DIR/feature-gate-import-trait-associated-functions.rs:26:26
33+
|
34+
LL | use super::A::{self, DEFAULT, new};
35+
| ^^^^^^^
36+
|
37+
= note: see issue #134691 <https://github.com/rust-lang/rust/issues/134691> for more information
38+
= help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable
39+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
40+
41+
error[E0658]: `use` associated items of traits is unstable
42+
--> $DIR/feature-gate-import-trait-associated-functions.rs:26:35
43+
|
44+
LL | use super::A::{self, DEFAULT, new};
45+
| ^^^
46+
|
47+
= note: see issue #134691 <https://github.com/rust-lang/rust/issues/134691> for more information
48+
= help: add `#![feature(import_trait_associated_functions)]` to the crate attributes to enable
49+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
50+
51+
error: aborting due to 5 previous errors
52+
53+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//@ check-pass
2+
#![feature(import_trait_associated_functions)]
3+
4+
use std::collections::HashMap;
5+
6+
use A::{DEFAULT, new};
7+
use Default::default;
8+
9+
struct S {
10+
a: HashMap<i32, i32>,
11+
}
12+
13+
impl S {
14+
fn new() -> S {
15+
S { a: default() }
16+
}
17+
}
18+
19+
trait A: Sized {
20+
const DEFAULT: Option<Self> = None;
21+
fn new() -> Self;
22+
fn do_something(&self);
23+
}
24+
25+
mod b {
26+
use super::A::{self, DEFAULT, new};
27+
28+
struct B();
29+
30+
impl A for B {
31+
const DEFAULT: Option<Self> = Some(B());
32+
fn new() -> Self {
33+
B()
34+
}
35+
36+
fn do_something(&self) {}
37+
}
38+
39+
fn f() {
40+
let b: B = new();
41+
b.do_something();
42+
let c: B = DEFAULT.unwrap();
43+
}
44+
}
45+
46+
impl A for S {
47+
fn new() -> Self {
48+
S::new()
49+
}
50+
51+
fn do_something(&self) {}
52+
}
53+
54+
fn f() {
55+
let s: S = new();
56+
s.do_something();
57+
let t: Option<S> = DEFAULT;
58+
}
59+
60+
fn main() {}

0 commit comments

Comments
 (0)