Skip to content
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
86 changes: 83 additions & 3 deletions compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{self as hir};
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::dep_graph::DepContext;
Expand All @@ -72,12 +73,17 @@ use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Pos, Span, sym};
use tracing::{debug, instrument};

use crate::error_reporting::TypeErrCtxt;
use crate::error_reporting::traits::ambiguity::{
CandidateSource, compute_applicable_impls_for_diagnostics,
};
use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags};
use crate::infer;
use crate::infer::relate::{self, RelateResult, TypeRelation};
use crate::infer::{InferCtxt, InferCtxtExt as _, TypeTrace, ValuePairs};
use crate::solve::deeply_normalize_for_diagnostics;
use crate::traits::{MatchExpressionArmCause, ObligationCause, ObligationCauseCode};
use crate::traits::{
MatchExpressionArmCause, Obligation, ObligationCause, ObligationCauseCode, specialization_graph,
};

mod note_and_explain;
mod suggest;
Expand Down Expand Up @@ -149,11 +155,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
actual: Ty<'tcx>,
err: TypeError<'tcx>,
) -> Diag<'a> {
self.report_and_explain_type_error(
let mut diag = self.report_and_explain_type_error(
TypeTrace::types(cause, expected, actual),
param_env,
err,
)
);

self.suggest_param_env_shadowing(&mut diag, expected, actual, param_env);

diag
}

pub fn report_mismatched_consts(
Expand Down Expand Up @@ -240,6 +250,76 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
false
}

fn suggest_param_env_shadowing(
&self,
diag: &mut Diag<'_>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) {
let (alias, concrete) = match (expected.kind(), found.kind()) {
(ty::Alias(ty::Projection, proj), _) => (proj, found),
(_, ty::Alias(ty::Projection, proj)) => (proj, expected),
_ => return,
};

let tcx = self.tcx;

let trait_ref = alias.trait_ref(tcx);
let obligation =
Obligation::new(tcx, ObligationCause::dummy(), param_env, ty::Binder::dummy(trait_ref));

let applicable_impls = compute_applicable_impls_for_diagnostics(self.infcx, &obligation);

for candidate in applicable_impls {
let impl_def_id = match candidate {
CandidateSource::DefId(did) => did,
CandidateSource::ParamEnv(_) => continue,
};

let is_shadowed = self.infcx.probe(|_| {
let impl_substs = self.infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_substs);

let expected_trait_ref = alias.trait_ref(tcx);

if let Err(_) = self.infcx.at(&ObligationCause::dummy(), param_env).eq(
DefineOpaqueTypes::No,
expected_trait_ref,
impl_trait_ref,
) {
return false;
}

let trait_def_id = alias.trait_def_id(tcx);
let rebased_args = alias.args.rebase_onto(tcx, trait_def_id, impl_substs);

let leaf_def = match specialization_graph::assoc_def(tcx, impl_def_id, alias.def_id)
{
Ok(leaf) => leaf,
Err(_) => return false,
};

let impl_item_def_id = leaf_def.item.def_id;
let impl_assoc_ty = tcx.type_of(impl_item_def_id).instantiate(tcx, rebased_args);

self.infcx.can_eq(param_env, impl_assoc_ty, concrete)
});

if is_shadowed {
diag.note(format!(
"the associated type `{}` is defined as `{}` in the implementation, \
but the where-bound `{}` shadows this definition\n\
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information",
self.ty_to_string(tcx.mk_ty_from_kind(ty::Alias(ty::Projection, *alias))),
self.ty_to_string(concrete),
self.ty_to_string(alias.self_ty())
));
return;
}
}
}

fn note_error_origin(
&self,
err: &mut Diag<'_>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub mod project;
pub mod query;
#[allow(hidden_glob_reexports)]
mod select;
mod specialize;
pub mod specialize;
mod structural_normalize;
#[allow(hidden_glob_reexports)]
mod util;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ LL | const N: C::M = 4u8;
|
= note: expected associated type `<C as O>::M`
found type `u8`
= note: the associated type `<C as O>::M` is defined as `u8` in the implementation, but the where-bound `C` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
help: consider constraining the associated type `<C as O>::M` to `u8`
|
LL | impl<C: O<M = u8>> U<C> for u16 {
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/associated-types/defaults-specialization.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ LL | fn make() -> Self::Ty { 0u8 }
found type `u8`
= help: consider constraining the associated type `<A2<T> as Tr>::Ty` to `u8` or calling a method that returns `<A2<T> as Tr>::Ty`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: the associated type `<A2<T> as Tr>::Ty` is defined as `u8` in the implementation, but the where-bound `A2<T>` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:44:29
Expand All @@ -89,6 +91,8 @@ LL | fn make() -> Self::Ty { true }
|
= note: expected associated type `<B2<T> as Tr>::Ty`
found type `bool`
= note: the associated type `<B2<T> as Tr>::Ty` is defined as `bool` in the implementation, but the where-bound `B2<T>` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:87:32
Expand Down Expand Up @@ -121,6 +125,8 @@ help: a method is available that returns `<B<()> as Tr>::Ty`
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
= note: the associated type `<B<()> as Tr>::Ty` is defined as `bool` in the implementation, but the where-bound `B<()>` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error[E0308]: mismatched types
--> $DIR/defaults-specialization.rs:89:33
Expand Down Expand Up @@ -153,6 +159,8 @@ help: a method is available that returns `<B2<()> as Tr>::Ty`
|
LL | fn make() -> Self::Ty {
| ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
= note: the associated type `<B2<()> as Tr>::Ty` is defined as `bool` in the implementation, but the where-bound `B2<()>` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error: aborting due to 9 previous errors; 1 warning emitted

Expand Down
17 changes: 17 additions & 0 deletions tests/ui/associated-types/param-env-shadowing-false-positive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Regression test for issue #149910.
// The compiler previously incorrectly claimed that the local param-env bound
// shadowed the global impl, but they are actually the same.

trait Trait {
type Assoc;
}

impl<T> Trait for T {
type Assoc = T;
}

fn foo<T: Trait>(x: T::Assoc) -> u32 {
x //~ ERROR mismatched types
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0308]: mismatched types
--> $DIR/param-env-shadowing-false-positive.rs:14:5
|
LL | fn foo<T: Trait>(x: T::Assoc) -> u32 {
| --- expected `u32` because of return type
LL | x
| ^ expected `u32`, found associated type
|
= note: expected type `u32`
found associated type `<T as Trait>::Assoc`
help: consider constraining the associated type `<T as Trait>::Assoc` to `u32`
|
LL | fn foo<T: Trait<Assoc = u32>>(x: T::Assoc) -> u32 {
| +++++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
17 changes: 17 additions & 0 deletions tests/ui/associated-types/param-env-shadowing-gat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Regression test for issue #149910.
// This ensures that the diagnostics logic handles Generic Associated Types (GATs)
// correctly without crashing (ICE).

trait Trait {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a comment to each test explaining what it is testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added all the comments for the tests.

type Assoc<T>;
}

impl<T> Trait for T {
type Assoc<U> = U;
}

fn foo<T: Trait>(x: T::Assoc<T>) -> u32 {
x //~ ERROR mismatched types
}

fn main() {}
18 changes: 18 additions & 0 deletions tests/ui/associated-types/param-env-shadowing-gat.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error[E0308]: mismatched types
--> $DIR/param-env-shadowing-gat.rs:14:5
|
LL | fn foo<T: Trait>(x: T::Assoc<T>) -> u32 {
| --- expected `u32` because of return type
LL | x
| ^ expected `u32`, found associated type
|
= note: expected type `u32`
found associated type `<T as Trait>::Assoc<T>`
help: consider constraining the associated type `<T as Trait>::Assoc<T>` to `u32`
|
LL | fn foo<T: Trait<Assoc<T> = u32>>(x: T::Assoc<T>) -> u32 {
| ++++++++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
14 changes: 14 additions & 0 deletions tests/ui/associated-types/param-env-shadowing-issue-149910.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
trait Trait {
type Assoc;
}

impl<T> Trait for T {
type Assoc = T;
}

fn foo<T: Trait>(x: T) -> T::Assoc {
x
//~^ ERROR mismatched types
}

fn main() {}
22 changes: 22 additions & 0 deletions tests/ui/associated-types/param-env-shadowing-issue-149910.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0308]: mismatched types
--> $DIR/param-env-shadowing-issue-149910.rs:10:5
|
LL | fn foo<T: Trait>(x: T) -> T::Assoc {
| - -------- expected `<T as Trait>::Assoc` because of return type
| |
| found this type parameter
LL | x
| ^ expected associated type, found type parameter `T`
|
= note: expected associated type `<T as Trait>::Assoc`
found type parameter `T`
= note: the associated type `<T as Trait>::Assoc` is defined as `T` in the implementation, but the where-bound `T` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information
help: consider further restricting this bound
|
LL | fn foo<T: Trait<Assoc = T>>(x: T) -> T::Assoc {
| +++++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ LL | ()
found unit type `()`
= help: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: the associated type `<T as Foo>::Assoc` is defined as `()` in the implementation, but the where-bound `T` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error[E0308]: mismatched types
--> $DIR/specialization-default-projection.rs:32:5
Expand All @@ -37,6 +39,8 @@ LL | generic::<()>()
found associated type `<() as Foo>::Assoc`
= help: consider constraining the associated type `<() as Foo>::Assoc` to `()`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: the associated type `<() as Foo>::Assoc` is defined as `()` in the implementation, but the where-bound `()` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error: aborting due to 2 previous errors; 1 warning emitted

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ LL | ()
found unit type `()`
= help: consider constraining the associated type `<T as Foo>::Assoc` to `()` or calling a method that returns `<T as Foo>::Assoc`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: the associated type `<T as Foo>::Assoc` is defined as `()` in the implementation, but the where-bound `T` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error[E0308]: mismatched types
--> $DIR/specialization-default-projection.rs:32:5
Expand All @@ -37,6 +39,8 @@ LL | generic::<()>()
found associated type `<() as Foo>::Assoc`
= help: consider constraining the associated type `<() as Foo>::Assoc` to `()`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: the associated type `<() as Foo>::Assoc` is defined as `()` in the implementation, but the where-bound `()` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error: aborting due to 2 previous errors; 1 warning emitted

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ LL | Box::new(self)
|
= note: expected associated type `<T as Example>::Output`
found struct `Box<T>`
= note: the associated type `<T as Example>::Output` is defined as `Box<T>` in the implementation, but the where-bound `T` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error[E0308]: mismatched types
--> $DIR/specialization-default-types.rs:29:5
Expand All @@ -33,6 +35,8 @@ LL | Example::generate(t)
found associated type `<T as Example>::Output`
= help: consider constraining the associated type `<T as Example>::Output` to `Box<T>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: the associated type `<T as Example>::Output` is defined as `Box<T>` in the implementation, but the where-bound `T` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error: aborting due to 2 previous errors; 1 warning emitted

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ LL | Box::new(self)
|
= note: expected associated type `<T as Example>::Output`
found struct `Box<T>`
= note: the associated type `<T as Example>::Output` is defined as `Box<T>` in the implementation, but the where-bound `T` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error[E0308]: mismatched types
--> $DIR/specialization-default-types.rs:29:5
Expand All @@ -33,6 +35,8 @@ LL | Example::generate(t)
found associated type `<T as Example>::Output`
= help: consider constraining the associated type `<T as Example>::Output` to `Box<T>`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: the associated type `<T as Example>::Output` is defined as `Box<T>` in the implementation, but the where-bound `T` shadows this definition
see issue #152409 <https://github.com/rust-lang/rust/issues/152409> for more information

error: aborting due to 2 previous errors; 1 warning emitted

Expand Down
Loading