Skip to content
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

Implement use associated items of traits #134754

Merged
Merged
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
12 changes: 6 additions & 6 deletions compiler/rustc_error_codes/src/error_codes/E0253.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
Attempt was made to import an unimportable value. This can happen when trying
to import a method from a trait.
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
mod foo {
pub trait MyTrait {
fn do_something();
type SomeType;
}
}

use foo::MyTrait::do_something;
// error: `do_something` is not directly importable
use foo::MyTrait::SomeType;
// error: `SomeType` is not directly importable

fn main() {}
```

It's invalid to directly import methods belonging to a trait or concrete type.
It's invalid to directly import types belonging to a trait.
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ declare_features! (
(unstable, impl_trait_in_bindings, "1.64.0", Some(63065)),
/// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
(unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
/// Allows `use` associated functions from traits.
(unstable, import_trait_associated_functions, "CURRENT_RUSTC_VERSION", Some(134691)),
/// Allows associated types in inherent impls.
(incomplete, inherent_associated_types, "1.52.0", Some(8995)),
/// Allow anonymous constants from an inline `const` block in pattern position
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,11 @@ 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() {
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()
{
return;
}

Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_resolve/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ use rustc_session::lint::builtin::{
AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
REDUNDANT_IMPORTS, UNUSED_IMPORTS,
};
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::hygiene::LocalExpnId;
use rustc_span::{Ident, Span, Symbol, kw};
use rustc_span::{Ident, Span, Symbol, kw, sym};
use smallvec::SmallVec;
use tracing::debug;

Expand Down Expand Up @@ -829,6 +830,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// 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()
&& !this.tcx.features().import_trait_associated_functions()
{
feature_err(
this.tcx.sess,
sym::import_trait_associated_functions,
import.span,
"`use` associated items of traits is unstable",
)
.emit();
}
let imported_binding = this.import(binding, import);
target_bindings[ns].set(Some(imported_binding));
this.define(parent, target, ns, imported_binding);
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -920,10 +920,13 @@ impl<'ra> NameBindingData<'ra> {
}

fn is_importable(&self) -> bool {
!matches!(
self.res(),
Res::Def(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _)
)
!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 macro_kind(&self) -> Option<MacroKind> {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,7 @@ symbols! {
import,
import_name_type,
import_shadowing,
import_trait_associated_functions,
imported_main,
in_band_lifetimes,
include,
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/error-codes/E0253.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
mod foo {
pub trait MyTrait {
fn do_something();
type SomeType;
}
}

use foo::MyTrait::do_something;
use foo::MyTrait::SomeType;
//~^ ERROR E0253

fn main() {}
6 changes: 3 additions & 3 deletions tests/ui/error-codes/E0253.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0253]: `do_something` is not directly importable
error[E0253]: `SomeType` is not directly importable
--> $DIR/E0253.rs:7:5
|
LL | use foo::MyTrait::do_something;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly
LL | use foo::MyTrait::SomeType;
| ^^^^^^^^^^^^^^^^^^^^^^ cannot be imported directly

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//@ edition:2018
use std::collections::HashMap;

use A::{DEFAULT, new};
//~^ ERROR `use` associated items of traits is unstable [E0658]
//~| ERROR `use` associated items of traits is unstable [E0658]
use Default::default;
//~^ ERROR `use` associated items of traits is unstable [E0658]

struct S {
a: HashMap<i32, i32>,
}

impl S {
fn new() -> S {
S { a: default() }
}
}

trait A: Sized {
const DEFAULT: Option<Self> = None;
fn new() -> Self;
fn do_something(&self);
}

mod b {
use super::A::{self, DEFAULT, new};
//~^ ERROR `use` associated items of traits is unstable [E0658]
//~| ERROR `use` associated items of traits is unstable [E0658]

struct B();

impl A for B {
const DEFAULT: Option<Self> = Some(B());
fn new() -> Self {
B()
}

fn do_something(&self) {}
}

fn f() {
let b: B = new();
b.do_something();
let c: B = DEFAULT.unwrap();
}
}

impl A for S {
fn new() -> Self {
S::new()
}

fn do_something(&self) {}
}

fn f() {
let s: S = new();
s.do_something();
let t: Option<S> = DEFAULT;
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
error[E0658]: `use` associated items of traits is unstable
--> $DIR/feature-gate-import-trait-associated-functions.rs:4:9
|
LL | use A::{DEFAULT, new};
| ^^^^^^^
|
= 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/feature-gate-import-trait-associated-functions.rs:4:18
|
LL | use A::{DEFAULT, new};
| ^^^
|
= 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/feature-gate-import-trait-associated-functions.rs:7:5
|
LL | use Default::default;
| ^^^^^^^^^^^^^^^^
|
= 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/feature-gate-import-trait-associated-functions.rs:27:26
|
LL | use super::A::{self, DEFAULT, new};
| ^^^^^^^
|
= 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/feature-gate-import-trait-associated-functions.rs:27:35
|
LL | use super::A::{self, DEFAULT, new};
| ^^^
|
= 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 5 previous errors

For more information about this error, try `rustc --explain E0658`.
4 changes: 2 additions & 2 deletions tests/ui/imports/import-trait-method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ trait Foo {
fn foo();
}

use Foo::foo; //~ ERROR not directly importable
use Foo::foo; //~ ERROR `use` associated items of traits is unstable [E0658]

fn main() { foo(); }
fn main() { foo(); } //~ ERROR type annotations needed
21 changes: 17 additions & 4 deletions tests/ui/imports/import-trait-method.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
error[E0253]: `foo` is not directly importable
error[E0658]: `use` associated items of traits is unstable
--> $DIR/import-trait-method.rs:5:5
|
LL | use Foo::foo;
| ^^^^^^^^ 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[E0283]: type annotations needed
--> $DIR/import-trait-method.rs:7:13
|
LL | fn main() { foo(); }
| ^^^^^ cannot infer type
|
= note: cannot satisfy `_: Foo`

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

For more information about this error, try `rustc --explain E0253`.
Some errors have detailed explanations: E0283, E0658.
For more information about an error, try `rustc --explain E0283`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
error[E0425]: cannot find function `cmp` in this scope
--> $DIR/fn-to-method.rs:12:13
|
LL | let x = cmp(&1, &2);
| ^^^ not found in this scope
|
help: consider importing one of these associated functions
|
LL + use std::cmp::Ord::cmp;
|
LL + use std::iter::Iterator::cmp;
|

error[E0425]: cannot find function `len` in this scope
--> $DIR/fn-to-method.rs:16:13
|
LL | let y = len([1, 2, 3]);
| ^^^ not found in this scope
|
help: consider importing this associated function
|
LL + use std::iter::ExactSizeIterator::len;
|

error[E0425]: cannot find function `bar` in this scope
--> $DIR/fn-to-method.rs:20:13
|
LL | let z = bar(Foo);
| ^^^ not found in this scope
|
help: use the `.` operator to call the method `bar` on `Foo`
|
LL - let z = bar(Foo);
LL + let z = Foo.bar();
|

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0425`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0425]: cannot find function `cmp` in this scope
--> $DIR/fn-to-method.rs:8:13
--> $DIR/fn-to-method.rs:12:13
|
LL | let x = cmp(&1, &2);
| ^^^ not found in this scope
Expand All @@ -10,7 +10,7 @@ LL | let x = (&1).cmp(&2);
| ~ ~~~~~~~~~

error[E0425]: cannot find function `len` in this scope
--> $DIR/fn-to-method.rs:12:13
--> $DIR/fn-to-method.rs:16:13
|
LL | let y = len([1, 2, 3]);
| ^^^ not found in this scope
Expand All @@ -22,7 +22,7 @@ LL + let y = [1, 2, 3].len();
|

error[E0425]: cannot find function `bar` in this scope
--> $DIR/fn-to-method.rs:16:13
--> $DIR/fn-to-method.rs:20:13
|
LL | let z = bar(Foo);
| ^^^ not found in this scope
Expand Down
8 changes: 6 additions & 2 deletions tests/ui/suggestions/fn-to-method.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
//@ revisions: normal import_trait_associated_functions
#![cfg_attr(import_trait_associated_functions, feature(import_trait_associated_functions))]
struct Foo;
//[import_trait_associated_functions]~^ HELP consider importing one of these associated functions
//[import_trait_associated_functions]~| HELP consider importing this associated function

impl Foo {
fn bar(self) {}
Expand All @@ -7,11 +11,11 @@ impl Foo {
fn main() {
let x = cmp(&1, &2);
//~^ ERROR cannot find function `cmp` in this scope
//~| HELP use the `.` operator to call the method `Ord::cmp` on `&{integer}`
//[normal]~| HELP use the `.` operator to call the method `Ord::cmp` on `&{integer}`

let y = len([1, 2, 3]);
//~^ ERROR cannot find function `len` in this scope
//~| HELP use the `.` operator to call the method `len` on `&[{integer}]`
//[normal]~| HELP use the `.` operator to call the method `len` on `&[{integer}]`

let z = bar(Foo);
//~^ ERROR cannot find function `bar` in this scope
Expand Down
Loading
Loading