Add deeply_normalize_for_diagnostics, use it in coherence
This commit is contained in:
parent
8a7b2035f8
commit
334577f091
6 changed files with 80 additions and 4 deletions
|
@ -41,7 +41,9 @@ mod trait_goals;
|
|||
|
||||
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
|
||||
pub use fulfill::FulfillmentCtxt;
|
||||
pub(crate) use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
|
||||
pub(crate) use normalize::{
|
||||
deeply_normalize, deeply_normalize_for_diagnostics, deeply_normalize_with_skipped_universes,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum SolverMode {
|
||||
|
|
|
@ -4,10 +4,11 @@ use crate::traits::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
|
|||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_infer::infer::at::At;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::TraitEngineExt;
|
||||
use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc_middle::traits::Reveal;
|
||||
use rustc_middle::traits::{ObligationCause, Reveal};
|
||||
use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
|
||||
use rustc_middle::ty::{FallibleTypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
||||
|
@ -41,6 +42,19 @@ pub(crate) fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCt
|
|||
value.try_fold_with(&mut folder)
|
||||
}
|
||||
|
||||
// Deeply normalize a value and return it
|
||||
pub(crate) fn deeply_normalize_for_diagnostics<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
t: T,
|
||||
) -> T {
|
||||
infcx
|
||||
.commit_if_ok(|_| {
|
||||
deeply_normalize(infcx.at(&ObligationCause::dummy(), param_env), t.clone())
|
||||
})
|
||||
.unwrap_or(t)
|
||||
}
|
||||
|
||||
struct NormalizationFolder<'me, 'tcx> {
|
||||
at: At<'me, 'tcx>,
|
||||
fulfill_cx: FulfillmentCtxt<'tcx>,
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
use crate::infer::outlives::env::OutlivesEnvironment;
|
||||
use crate::infer::InferOk;
|
||||
use crate::solve::inspect;
|
||||
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
|
||||
use crate::traits::engine::TraitEngineExt;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs};
|
||||
|
@ -308,7 +308,13 @@ fn overlap<'tcx>(
|
|||
.iter()
|
||||
.any(|c| c.0.involves_placeholders());
|
||||
|
||||
let impl_header = selcx.infcx.resolve_vars_if_possible(impl1_header);
|
||||
let mut impl_header = infcx.resolve_vars_if_possible(impl1_header);
|
||||
|
||||
// Deeply normalize the impl header for diagnostics, ignoring any errors if this fails.
|
||||
if infcx.next_trait_solver() {
|
||||
impl_header = deeply_normalize_for_diagnostics(&infcx, param_env, impl_header);
|
||||
}
|
||||
|
||||
Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder })
|
||||
}
|
||||
|
||||
|
@ -1084,6 +1090,10 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
|
|||
Ok(Ok(())) => warn!("expected an unknowable trait ref: {trait_ref:?}"),
|
||||
Ok(Err(conflict)) => {
|
||||
if !trait_ref.references_error() {
|
||||
// Normalize the trait ref for diagnostics, ignoring any errors if this fails.
|
||||
let trait_ref =
|
||||
deeply_normalize_for_diagnostics(infcx, param_env, trait_ref);
|
||||
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty);
|
||||
ambiguity_cause = Some(match conflict {
|
||||
|
|
14
tests/ui/coherence/normalize-for-errors.current.stderr
Normal file
14
tests/ui/coherence/normalize-for-errors.current.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error[E0119]: conflicting implementations of trait `MyTrait` for type `Box<(MyType,)>`
|
||||
--> $DIR/normalize-for-errors.rs:17:1
|
||||
|
|
||||
LL | impl<T: Copy> MyTrait for T {}
|
||||
| --------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl MyTrait for Box<<(MyType,) as Mirror>::Assoc> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<(MyType,)>`
|
||||
|
|
||||
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
14
tests/ui/coherence/normalize-for-errors.next.stderr
Normal file
14
tests/ui/coherence/normalize-for-errors.next.stderr
Normal file
|
@ -0,0 +1,14 @@
|
|||
error[E0119]: conflicting implementations of trait `MyTrait` for type `Box<(MyType,)>`
|
||||
--> $DIR/normalize-for-errors.rs:17:1
|
||||
|
|
||||
LL | impl<T: Copy> MyTrait for T {}
|
||||
| --------------------------- first implementation here
|
||||
LL |
|
||||
LL | impl MyTrait for Box<<(MyType,) as Mirror>::Assoc> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Box<(MyType,)>`
|
||||
|
|
||||
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
22
tests/ui/coherence/normalize-for-errors.rs
Normal file
22
tests/ui/coherence/normalize-for-errors.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
|
||||
struct MyType;
|
||||
trait MyTrait {
|
||||
}
|
||||
|
||||
trait Mirror {
|
||||
type Assoc;
|
||||
}
|
||||
impl<T> Mirror for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
impl<T: Copy> MyTrait for T {}
|
||||
//~^ NOTE first implementation here
|
||||
impl MyTrait for Box<<(MyType,) as Mirror>::Assoc> {}
|
||||
//~^ ERROR conflicting implementations of trait `MyTrait` for type `Box<(MyType,)>`
|
||||
//~| NOTE conflicting implementation for `Box<(MyType,)>
|
||||
//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
|
||||
|
||||
fn main() {}
|
Loading…
Add table
Reference in a new issue