Skip to content

Commit

Permalink
Rollup merge of #108947 - compiler-errors:ct-infer-no-shapeshifting, …
Browse files Browse the repository at this point in the history
…r=BoxyUwU

Don't even try to combine consts with incompatible types

~I left a more detailed explanation for why this fixes this issue in the UI test, but in general, we should not try to unify const infer vars and rigid consts if they have incompatible types. That's because we don't want something like a `ConstArgHasType` predicate to suddenly go from passing to failing, or vice versa, due to a shallow resolve.~

1. Use the `type_of` for a parameter in `try_eval_lit_or_param`, instead of the "expected" type from a `WithOptConstParam` def id.
2. Don't combine consts that have incompatible types.

Fixes #108781
  • Loading branch information
matthiaskrgr authored Mar 10, 2023
2 parents 772b1ce + f714613 commit 145e620
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 34 deletions.
22 changes: 15 additions & 7 deletions compiler/rustc_infer/src/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ use rustc_hir::def_id::DefId;
use rustc_middle::infer::canonical::OriginalQueryValues;
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
Expand Down Expand Up @@ -171,9 +170,9 @@ impl<'tcx> InferCtxt<'tcx> {
//
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
self.probe(|_| {
let compatible_types = self.probe(|_| {
if a.ty() == b.ty() {
return;
return Ok(());
}

// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
Expand All @@ -183,15 +182,24 @@ impl<'tcx> InferCtxt<'tcx> {
(relation.param_env(), a.ty(), b.ty()),
&mut OriginalQueryValues::default(),
);

if let Err(NoSolution) = self.tcx.check_tys_might_be_eq(canonical) {
self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
self.tcx.sess.delay_span_bug(
DUMMY_SP,
&format!("cannot relate consts of different types (a={:?}, b={:?})", a, b,),
);
}
)
})
});

// If the consts have differing types, just bail with a const error with
// 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,
));
}

match (a.kind(), b.kind()) {
(
ty::ConstKind::Infer(InferConst::Var(a_vid)),
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ impl<'tcx> Const<'tcx> {
_,
&hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. },
)) => {
// Use the type from the param's definition, since we can resolve it,
// not the expected parameter type from WithOptConstParam.
let param_ty = tcx.type_of(def_id).subst_identity();
match tcx.named_bound_var(expr.hir_id) {
Some(rbv::ResolvedArg::EarlyBound(_)) => {
// Find the name and index of the const parameter by indexing the generics of
Expand All @@ -143,14 +146,14 @@ impl<'tcx> Const<'tcx> {
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
Some(tcx.mk_const(ty::ParamConst::new(index, name), ty))
Some(tcx.mk_const(ty::ParamConst::new(index, name), param_ty))
}
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => Some(tcx.mk_const(
ty::ConstKind::Bound(debruijn, ty::BoundVar::from_u32(index)),
ty,
param_ty,
)),
Some(rbv::ResolvedArg::Error(guar)) => {
Some(tcx.const_error_with_guaranteed(ty, guar))
Some(tcx.const_error_with_guaranteed(param_ty, guar))
}
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id),
}
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_trait_selection/src/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@ pub fn translate_substs<'tcx>(
}

fulfill_implication(infcx, param_env, source_trait_ref, target_impl).unwrap_or_else(
|_| {
|()| {
bug!(
"When translating substitutions for specialization, the expected \
specialization failed to hold"
"When translating substitutions from {source_impl:?} to {target_impl:?}, \
the expected specialization failed to hold"
)
},
)
Expand Down
1 change: 1 addition & 0 deletions tests/ui/const-generics/type_mismatch.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
fn foo<const N: usize>() -> [u8; N] {
bar::<N>() //~ ERROR mismatched types
//~^ ERROR the constant `N` is not of type `u8`
}

fn bar<const N: u8>() -> [u8; N] {}
Expand Down
18 changes: 15 additions & 3 deletions tests/ui/const-generics/type_mismatch.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
error: the constant `N` is not of type `u8`
--> $DIR/type_mismatch.rs:2:5
|
LL | bar::<N>()
| ^^^^^^^^
|
note: required by a bound in `bar`
--> $DIR/type_mismatch.rs:6:8
|
LL | fn bar<const N: u8>() -> [u8; N] {}
| ^^^^^^^^^^^ required by this bound in `bar`

error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:2:11
|
LL | bar::<N>()
| ^ expected `u8`, found `usize`

error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:5:26
--> $DIR/type_mismatch.rs:6:26
|
LL | fn bar<const N: u8>() -> [u8; N] {}
| --- ^^^^^^^ expected `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression

error[E0308]: mismatched types
--> $DIR/type_mismatch.rs:5:31
--> $DIR/type_mismatch.rs:6:31
|
LL | fn bar<const N: u8>() -> [u8; N] {}
| ^ expected `usize`, found `u8`

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

For more information about this error, try `rustc --explain E0308`.
1 change: 0 additions & 1 deletion tests/ui/const-generics/type_not_in_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ impl X {
}
fn getn<const N: cfg_attr>() -> [u8; N] {}
//~^ ERROR expected type, found built-in attribute `cfg_attr`
//~| ERROR mismatched types

fn main() {}
14 changes: 3 additions & 11 deletions tests/ui/const-generics/type_not_in_scope.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ error[E0573]: expected type, found built-in attribute `cfg_attr`
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
| ^^^^^^^^ not a type

error[E0308]: mismatched types
--> $DIR/type_not_in_scope.rs:7:33
|
LL | fn getn<const N: cfg_attr>() -> [u8; N] {}
| ---- ^^^^^^^ expected `[u8; N]`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression

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

Some errors have detailed explanations: E0308, E0412, E0573.
For more information about an error, try `rustc --explain E0308`.
Some errors have detailed explanations: E0412, E0573.
For more information about an error, try `rustc --explain E0412`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(min_specialization)]

// An impl that has an erroneous const substitution should not specialize one
// that is well-formed.

struct S<const L: usize>;

impl<const N: i32> Copy for S<N> {}
impl<const M: usize> Copy for S<M> {}
//~^ ERROR conflicting implementations of trait `Copy` for type `S<_>`

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
--> $DIR/bad-const-wf-doesnt-specialize.rs:9:1
|
LL | impl<const N: i32> Copy for S<N> {}
| -------------------------------- first implementation here
LL | impl<const M: usize> Copy for S<M> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0119`.
2 changes: 1 addition & 1 deletion tests/ui/transmutability/issue-101739-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod assert {
pub fn is_transmutable<Src, Context, const ASSUME_ALIGNMENT: bool>()
where
Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
//~^ ERROR mismatched types
//~^ the constant `ASSUME_ALIGNMENT` is not of type `Assume`
{
}
}
Expand Down
12 changes: 7 additions & 5 deletions tests/ui/transmutability/issue-101739-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ error[E0412]: cannot find type `Dst` in this scope
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
| ^^^ not found in this scope

error[E0308]: mismatched types
--> $DIR/issue-101739-1.rs:8:50
error: the constant `ASSUME_ALIGNMENT` is not of type `Assume`
--> $DIR/issue-101739-1.rs:8:14
|
LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
| ^^^^^^^^^^^^^^^^ expected `Assume`, found `bool`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: required by a bound in `BikeshedIntrinsicFrom`
--> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL

error: aborting due to 2 previous errors

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

0 comments on commit 145e620

Please sign in to comment.