Skip to content

Commit a7b3d59

Browse files
Add deeply_normalize_for_diagnostics, use it in coherence
1 parent 6cf0888 commit a7b3d59

File tree

6 files changed

+80
-4
lines changed

6 files changed

+80
-4
lines changed

compiler/rustc_trait_selection/src/solve/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ mod trait_goals;
4141

4242
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
4343
pub use fulfill::FulfillmentCtxt;
44-
pub(crate) use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
44+
pub(crate) use normalize::{
45+
deeply_normalize, deeply_normalize_for_diagnostics, deeply_normalize_with_skipped_universes,
46+
};
4547

4648
#[derive(Debug, Clone, Copy)]
4749
enum SolverMode {

compiler/rustc_trait_selection/src/solve/normalize.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use crate::traits::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
44
use rustc_data_structures::stack::ensure_sufficient_stack;
55
use rustc_infer::infer::at::At;
66
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
7+
use rustc_infer::infer::InferCtxt;
78
use rustc_infer::traits::TraitEngineExt;
89
use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
910
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
10-
use rustc_middle::traits::Reveal;
11+
use rustc_middle::traits::{ObligationCause, Reveal};
1112
use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
1213
use rustc_middle::ty::{FallibleTypeFolder, TypeSuperFoldable};
1314
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
@@ -41,6 +42,19 @@ pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCt
4142
value.try_fold_with(&mut folder)
4243
}
4344

45+
// Deeply normalize a value and return it
46+
pub(crate) fn deeply_normalize_for_diagnostics<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
47+
infcx: &InferCtxt<'tcx>,
48+
param_env: ty::ParamEnv<'tcx>,
49+
t: T,
50+
) -> T {
51+
infcx
52+
.commit_if_ok(|_| {
53+
deeply_normalize(infcx.at(&ObligationCause::dummy(), param_env), t.clone())
54+
})
55+
.unwrap_or(t)
56+
}
57+
4458
struct NormalizationFolder<'me, 'tcx> {
4559
at: At<'me, 'tcx>,
4660
fulfill_cx: FulfillmentCtxt<'tcx>,

compiler/rustc_trait_selection/src/traits/coherence.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
77
use crate::infer::outlives::env::OutlivesEnvironment;
88
use crate::infer::InferOk;
9-
use crate::solve::inspect;
109
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
10+
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
1111
use crate::traits::engine::TraitEngineExt;
1212
use crate::traits::query::evaluate_obligation::InferCtxtExt;
1313
use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs};
@@ -308,7 +308,13 @@ fn overlap<'tcx>(
308308
.iter()
309309
.any(|c| c.0.involves_placeholders());
310310

311-
let impl_header = selcx.infcx.resolve_vars_if_possible(impl1_header);
311+
let mut impl_header = infcx.resolve_vars_if_possible(impl1_header);
312+
313+
// Deeply normalize the impl header for diagnostics, ignoring any errors if this fails.
314+
if infcx.next_trait_solver() {
315+
impl_header = deeply_normalize_for_diagnostics(&infcx, param_env, impl_header);
316+
}
317+
312318
Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
313319
}
314320

@@ -1084,6 +1090,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
10841090
Ok(Ok(())) => warn!("expected an unknowable trait ref: {trait_ref:?}"),
10851091
Ok(Err(conflict)) => {
10861092
if !trait_ref.references_error() {
1093+
// Noramlize the trait ref for diagnostics, ignoring any errors if this fails.
1094+
let trait_ref =
1095+
deeply_normalize_for_diagnostics(infcx, param_env, trait_ref);
1096+
10871097
let self_ty = trait_ref.self_ty();
10881098
let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty);
10891099
ambiguity_cause = Some(match conflict {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0119]: conflicting implementations of trait `MyTrait` for type `Box<(MyType,)>`
2+
--> $DIR/normalize-for-errors.rs:17:1
3+
|
4+
LL | impl<T: Copy> MyTrait for T {}
5+
| --------------------------- first implementation here
6+
LL |
7+
LL | impl MyTrait for Box<<(MyType,) as Mirror>::Assoc> {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<(MyType,)>`
9+
|
10+
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0119`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0119]: conflicting implementations of trait `MyTrait` for type `Box<(MyType,)>`
2+
--> $DIR/normalize-for-errors.rs:17:1
3+
|
4+
LL | impl<T: Copy> MyTrait for T {}
5+
| --------------------------- first implementation here
6+
LL |
7+
LL | impl MyTrait for Box<<(MyType,) as Mirror>::Assoc> {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<(MyType,)>`
9+
|
10+
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0119`.
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// revisions: current next
2+
//[next] compile-flags: -Ztrait-solver=next
3+
4+
struct MyType;
5+
trait MyTrait {
6+
}
7+
8+
trait Mirror {
9+
type Assoc;
10+
}
11+
impl<T> Mirror for T {
12+
type Assoc = T;
13+
}
14+
15+
impl<T: Copy> MyTrait for T {}
16+
//~^ NOTE first implementation here
17+
impl MyTrait for Box<<(MyType,) as Mirror>::Assoc> {}
18+
//~^ ERROR conflicting implementations of trait `MyTrait` for type `Box<(MyType,)>`
19+
//~| NOTE conflicting implementation for `Box<(MyType,)>
20+
//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
21+
22+
fn main() {}

0 commit comments

Comments
 (0)