diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index bb6fdd2ffc2c9..4503af03ca341 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -189,10 +189,19 @@ impl<'tcx> InferCtxt<'tcx> { // the expected const's type. Specifically, we don't want const infer vars // to do any type shapeshifting before and after resolution. if let Err(guar) = compatible_types { - return Ok(self.tcx.const_error_with_guaranteed( - if relation.a_is_expected() { a.ty() } else { b.ty() }, - guar, - )); + // HACK: equating both sides with `[const error]` eagerly prevents us + // from leaving unconstrained inference vars during things like impl + // matching in the solver. + let a_error = self.tcx.const_error_with_guaranteed(a.ty(), guar); + if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() { + return self.unify_const_variable(vid, a_error); + } + let b_error = self.tcx.const_error_with_guaranteed(b.ty(), guar); + if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() { + return self.unify_const_variable(vid, b_error); + } + + return Ok(if relation.a_is_expected() { a_error } else { b_error }); } match (a.kind(), b.kind()) { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 8e229dd8d6b98..8546bbe52dcc3 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -22,7 +22,7 @@ use crate::traits::{ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{error_code, DelayDm, Diagnostic}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt}; +use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK; use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS; @@ -350,6 +350,10 @@ fn report_conflicting_impls<'tcx>( impl_span: Span, err: &mut Diagnostic, ) { + if (overlap.trait_ref, overlap.self_ty).references_error() { + err.downgrade_to_delayed_bug(); + } + match tcx.span_of_impl(overlap.with_impl) { Ok(span) => { err.span_label(span, "first implementation here"); diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs new file mode 100644 index 0000000000000..e13dfbacd2422 --- /dev/null +++ b/tests/ui/const-generics/bad-subst-const-kind.rs @@ -0,0 +1,13 @@ +// incremental +#![crate_type = "lib"] + +trait Q { + const ASSOC: usize; +} + +impl Q for [u8; N] { + //~^ ERROR mismatched types + const ASSOC: usize = 1; +} + +pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() } diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr new file mode 100644 index 0000000000000..bd24f9140e4ea --- /dev/null +++ b/tests/ui/const-generics/bad-subst-const-kind.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/bad-subst-const-kind.rs:8:31 + | +LL | impl Q for [u8; N] { + | ^ expected `usize`, found `u64` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs index 582b480aa25be..5fd7c647c2531 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs @@ -2,11 +2,11 @@ // An impl that has an erroneous const substitution should not specialize one // that is well-formed. - +#[derive(Clone)] struct S; impl Copy for S {} +//~^ ERROR the constant `N` is not of type `usize` impl Copy for S {} -//~^ ERROR conflicting implementations of trait `Copy` for type `S<_>` fn main() {} diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr index a3906a9a22fec..6d7028c5e7088 100644 --- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr +++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr @@ -1,11 +1,14 @@ -error[E0119]: conflicting implementations of trait `Copy` for type `S<_>` - --> $DIR/bad-const-wf-doesnt-specialize.rs:9:1 +error: the constant `N` is not of type `usize` + --> $DIR/bad-const-wf-doesnt-specialize.rs:8:29 | LL | impl Copy for S {} - | -------------------------------- first implementation here -LL | impl Copy for S {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>` + | ^^^^ + | +note: required by a bound in `S` + --> $DIR/bad-const-wf-doesnt-specialize.rs:6:10 + | +LL | struct S; + | ^^^^^^^^^^^^^^ required by this bound in `S` error: aborting due to previous error -For more information about this error, try `rustc --explain E0119`.