Skip to content

Do not create trait object type if missing associated types #133660

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

Merged
merged 1 commit into from
Dec 1, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
def_ids.retain(|def_id| !tcx.generics_require_sized_self(def_id));
}

self.complain_about_missing_assoc_tys(
if let Err(guar) = self.check_for_required_assoc_tys(
associated_types,
potential_assoc_types,
hir_trait_bounds,
);
) {
return Ty::new_error(tcx, guar);
}

// De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as
// `dyn Trait + Send`.
Expand Down
25 changes: 16 additions & 9 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,14 +714,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// reasonable suggestion on how to write it. For the case of multiple associated types in the
/// same trait bound have the same name (as they come from different supertraits), we instead
/// emit a generic note suggesting using a `where` clause to constraint instead.
pub(crate) fn complain_about_missing_assoc_tys(
pub(crate) fn check_for_required_assoc_tys(
&self,
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
potential_assoc_types: Vec<usize>,
trait_bounds: &[hir::PolyTraitRef<'_>],
) {
) -> Result<(), ErrorGuaranteed> {
if associated_types.values().all(|v| v.is_empty()) {
return;
return Ok(());
}

let tcx = self.tcx();
Expand All @@ -739,7 +739,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
// `issue-22560.rs`.
let mut trait_bound_spans: Vec<Span> = vec![];
let mut dyn_compatibility_violations = false;
let mut dyn_compatibility_violations = Ok(());
for (span, items) in &associated_types {
if !items.is_empty() {
trait_bound_spans.push(*span);
Expand All @@ -752,13 +752,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let violations =
dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
if !violations.is_empty() {
report_dyn_incompatibility(tcx, *span, None, trait_def_id, &violations).emit();
dyn_compatibility_violations = true;
dyn_compatibility_violations = Err(report_dyn_incompatibility(
tcx,
*span,
None,
trait_def_id,
&violations,
)
.emit());
}
}
}
if dyn_compatibility_violations {
return;

if let Err(guar) = dyn_compatibility_violations {
return Err(guar);
}

// related to issue #91997, turbofishes added only when in an expr or pat
Expand Down Expand Up @@ -965,7 +972,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}

err.emit();
Err(err.emit())
}

/// On ambiguous associated type, look for an associated function whose name matches the
Expand Down
12 changes: 0 additions & 12 deletions tests/crashes/131668.rs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ trait Item {
pub struct Flatten<I> {
inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
//~^ ERROR E0191
//~| ERROR E0223
}

fn main() {}
16 changes: 2 additions & 14 deletions tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@ error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIt
LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator<Item: IntoIterator<Item: >, Item = Type, IntoIter = Type>`

error[E0223]: ambiguous associated type
--> $DIR/overlaping-bound-suggestion.rs:6:13
|
LL | inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `IntoIterator` implemented for `(dyn IntoIterator + 'static)`, you could use the fully-qualified path
|
LL | inner: <<(dyn IntoIterator + 'static) as Example>::IntoIterator as Item>::Core,
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

Some errors have detailed explanations: E0191, E0223.
For more information about an error, try `rustc --explain E0191`.
For more information about this error, try `rustc --explain E0191`.
5 changes: 1 addition & 4 deletions tests/ui/async-await/async-fn/dyn-pos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
#![feature(async_closure)]

fn foo(x: &dyn async Fn()) {}
//~^ ERROR the trait `AsyncFn` cannot be made into an object
//~| ERROR the trait `AsyncFnMut` cannot be made into an object
//~| ERROR the trait `AsyncFnMut` cannot be made into an object
//~| ERROR the trait `AsyncFnMut` cannot be made into an object
//~^ ERROR the trait `AsyncFnMut` cannot be made into an object

fn main() {}
48 changes: 1 addition & 47 deletions tests/ui/async-await/async-fn/dyn-pos.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,52 +13,6 @@ note: for a trait to be "dyn-compatible" it needs to allow building a vtable to
&mut F
std::boxed::Box<F, A>

error[E0038]: the trait `AsyncFnMut` cannot be made into an object
--> $DIR/dyn-pos.rs:5:16
|
LL | fn foo(x: &dyn async Fn()) {}
| ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
|
= note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture`
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead:
&F
&mut F
std::boxed::Box<F, A>
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0038]: the trait `AsyncFnMut` cannot be made into an object
--> $DIR/dyn-pos.rs:5:16
|
LL | fn foo(x: &dyn async Fn()) {}
| ^^^^^^^^^^ `AsyncFnMut` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
|
= note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture`
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead:
&F
&mut F
std::boxed::Box<F, A>
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0038]: the trait `AsyncFn` cannot be made into an object
--> $DIR/dyn-pos.rs:5:12
|
LL | fn foo(x: &dyn async Fn()) {}
| ^^^^^^^^^^^^^^ `AsyncFn` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $SRC_DIR/core/src/ops/async_function.rs:LL:COL
|
= note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture`
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFn` for this new enum and using it instead:
&F
std::boxed::Box<F, A>

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

For more information about this error, try `rustc --explain E0038`.
3 changes: 0 additions & 3 deletions tests/ui/dyn-compatibility/missing-assoc-type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,5 @@ trait Foo {
}

fn bar(x: &dyn Foo) {} //~ ERROR the trait `Foo` cannot be made into an object
//~^ ERROR the trait `Foo` cannot be made into an object
//~| ERROR the trait `Foo` cannot be made into an object
//~| ERROR the trait `Foo` cannot be made into an object

fn main() {}
49 changes: 1 addition & 48 deletions tests/ui/dyn-compatibility/missing-assoc-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,53 +13,6 @@ LL | type Bar<T>;
| ^^^ ...because it contains the generic associated type `Bar`
= help: consider moving `Bar` to another trait

error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/missing-assoc-type.rs:5:16
|
LL | fn bar(x: &dyn Foo) {}
| ^^^ `Foo` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/missing-assoc-type.rs:2:10
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | type Bar<T>;
| ^^^ ...because it contains the generic associated type `Bar`
= help: consider moving `Bar` to another trait
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/missing-assoc-type.rs:5:16
|
LL | fn bar(x: &dyn Foo) {}
| ^^^ `Foo` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/missing-assoc-type.rs:2:10
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | type Bar<T>;
| ^^^ ...because it contains the generic associated type `Bar`
= help: consider moving `Bar` to another trait
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/missing-assoc-type.rs:5:12
|
LL | fn bar(x: &dyn Foo) {}
| ^^^^^^^ `Foo` cannot be made into an object
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/missing-assoc-type.rs:2:10
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | type Bar<T>;
| ^^^ ...because it contains the generic associated type `Bar`
= help: consider moving `Bar` to another trait

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

For more information about this error, try `rustc --explain E0038`.
3 changes: 1 addition & 2 deletions tests/ui/issues/issue-21950.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,5 @@ impl Add for i32 {

fn main() {
let x = &10 as &dyn Add;
//~^ ERROR E0393
//~| ERROR E0191
//~^ ERROR E0191
}
20 changes: 2 additions & 18 deletions tests/ui/issues/issue-21950.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,6 @@ LL | type Output;
LL | let x = &10 as &dyn Add;
| ^^^ help: specify the associated type: `Add<Output = Type>`

error[E0393]: the type parameter `Rhs` must be explicitly specified
--> $DIR/issue-21950.rs:10:25
|
LL | trait Add<Rhs=Self> {
| ------------------- type parameter `Rhs` must be specified for this
...
LL | let x = &10 as &dyn Add;
| ^^^
|
= note: because of the default `Self` reference, type parameters must be specified on object types
help: set the type parameter to the desired type
|
LL | let x = &10 as &dyn Add<Rhs>;
| +++++

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

Some errors have detailed explanations: E0191, E0393.
For more information about an error, try `rustc --explain E0191`.
For more information about this error, try `rustc --explain E0191`.
2 changes: 0 additions & 2 deletions tests/ui/issues/issue-28344.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ use std::ops::BitXor;
fn main() {
let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
//~^ ERROR must be specified
//~| no function or associated item named
//~| WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition

let g = BitXor::bitor;
//~^ ERROR must be specified
//~| no function or associated item named
//~| WARN trait objects without an explicit `dyn` are deprecated
//~| WARN this is accepted in the current edition
}
27 changes: 4 additions & 23 deletions tests/ui/issues/issue-28344.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,8 @@ error[E0191]: the value of the associated type `Output` in `BitXor` must be spec
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
| ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>`

error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope
--> $DIR/issue-28344.rs:4:25
|
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
| ^^^^^ function or associated item not found in `dyn BitXor<_>`
|
help: there is a method `bitxor` with a similar name, but with different arguments
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL

warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/issue-28344.rs:10:13
--> $DIR/issue-28344.rs:9:13
|
LL | let g = BitXor::bitor;
| ^^^^^^
Expand All @@ -41,21 +32,11 @@ LL | let g = <dyn BitXor>::bitor;
| ++++ +

error[E0191]: the value of the associated type `Output` in `BitXor` must be specified
--> $DIR/issue-28344.rs:10:13
--> $DIR/issue-28344.rs:9:13
|
LL | let g = BitXor::bitor;
| ^^^^^^ help: specify the associated type: `BitXor::<Output = Type>`

error[E0599]: no function or associated item named `bitor` found for trait object `dyn BitXor<_>` in the current scope
--> $DIR/issue-28344.rs:10:21
|
LL | let g = BitXor::bitor;
| ^^^^^ function or associated item not found in `dyn BitXor<_>`
|
help: there is a method `bitxor` with a similar name
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL

error: aborting due to 4 previous errors; 2 warnings emitted
error: aborting due to 2 previous errors; 2 warnings emitted

Some errors have detailed explanations: E0191, E0599.
For more information about an error, try `rustc --explain E0191`.
For more information about this error, try `rustc --explain E0191`.
2 changes: 0 additions & 2 deletions tests/ui/suggestions/trait-hidden-method.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// #107983 - testing that `__iterator_get_unchecked` isn't suggested
// HELP included so that compiletest errors on the bad suggestion
pub fn i_can_has_iterator() -> impl Iterator<Item = u32> {
//~^ ERROR expected `Box<dyn Iterator>`
//~| HELP consider constraining the associated type
Box::new(1..=10) as Box<dyn Iterator>
//~^ ERROR the value of the associated type `Item`
//~| HELP specify the associated type
Expand Down
21 changes: 3 additions & 18 deletions tests/ui/suggestions/trait-hidden-method.stderr
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
error[E0191]: the value of the associated type `Item` in `Iterator` must be specified
--> $DIR/trait-hidden-method.rs:6:33
--> $DIR/trait-hidden-method.rs:4:33
|
LL | Box::new(1..=10) as Box<dyn Iterator>
| ^^^^^^^^ help: specify the associated type: `Iterator<Item = Type>`

error[E0271]: expected `Box<dyn Iterator>` to be an iterator that yields `u32`, but it yields `<dyn Iterator as Iterator>::Item`
--> $DIR/trait-hidden-method.rs:3:32
|
LL | pub fn i_can_has_iterator() -> impl Iterator<Item = u32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found associated type
...
LL | Box::new(1..=10) as Box<dyn Iterator>
| ------------------------------------- return type was inferred to be `Box<dyn Iterator>` here
|
= note: expected type `u32`
found associated type `<dyn Iterator as Iterator>::Item`
= help: consider constraining the associated type `<dyn Iterator as Iterator>::Item` to `u32`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

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

Some errors have detailed explanations: E0191, E0271.
For more information about an error, try `rustc --explain E0191`.
For more information about this error, try `rustc --explain E0191`.
Loading