diff options
| author | Yuki Okushi <jtitor@2k36.org> | 2023-03-30 21:07:02 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-30 21:07:02 +0900 |
| commit | c1b28c3435e6ae5297f4c888c9c3ac494fe8e26f (patch) | |
| tree | fb2a1d38ff3ab22951f8df96d8a56f2d1b30da79 | |
| parent | ae9c1bf0903a75e6f7229425ce6b0f2d9f9d8e7a (diff) | |
| parent | 321a5dba9ee42e2950bbff14c7dfb38e07d21bc4 (diff) | |
| download | rust-c1b28c3435e6ae5297f4c888c9c3ac494fe8e26f.tar.gz rust-c1b28c3435e6ae5297f4c888c9c3ac494fe8e26f.zip | |
Rollup merge of #109748 - compiler-errors:new-solver-discr-kind-ice, r=lcnr
Don't ICE on `DiscriminantKind` projection in new solver As title says, since we now actually call `Ty::discriminant_kind` on placeholder types 😃 Also drive-by simplify `Pointee::Metadata` projection logic, and fix the UI test because the `<T as Pointee>::Metadata` tests weren't actually exercising the new projection logic, since we still eagerly normalize (which hits `project.rs` in the old solver) in HIR typeck. r? `@lcnr` tho feel free to re-roll, this pr is very low-priority and not super specific to the new trait solver. Fixes compiler-errors/next-solver-hir-issues#14
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/project_goals.rs | 48 | ||||
| -rw-r--r-- | tests/ui/traits/new-solver/param-discr-kind.rs | 8 | ||||
| -rw-r--r-- | tests/ui/traits/new-solver/pointee.rs | 18 | ||||
| -rw-r--r-- | tests/ui/traits/new-solver/projection-discr-kind.rs | 18 | ||||
| -rw-r--r-- | tests/ui/traits/new-solver/projection-discr-kind.stderr | 17 |
5 files changed, 94 insertions, 15 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 48f7d3e3e40..fd2aa10caa2 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -344,10 +344,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { LangItem::Sized, [ty::GenericArg::from(goal.predicate.self_ty())], )); - ecx.add_goal(goal.with(tcx, sized_predicate)); - ecx.eq(goal.param_env, goal.predicate.term, tcx.types.unit.into())?; - return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + tcx.types.unit } ty::Adt(def, substs) if def.is_struct() => { @@ -483,9 +481,49 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { - let discriminant = goal.predicate.self_ty().discriminant_ty(ecx.tcx()); + let self_ty = goal.predicate.self_ty(); + let discriminant_ty = match *self_ty.kind() { + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Array(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Closure(..) + | ty::Infer(ty::IntVar(..) | ty::FloatVar(..)) + | ty::Generator(..) + | ty::GeneratorWitness(..) + | ty::GeneratorWitnessMIR(..) + | ty::Never + | ty::Foreign(..) + | ty::Adt(_, _) + | ty::Str + | ty::Slice(_) + | ty::Dynamic(_, _, _) + | ty::Tuple(_) + | ty::Error(_) => self_ty.discriminant_ty(ecx.tcx()), + + // We do not call `Ty::discriminant_ty` on alias, param, or placeholder + // types, which return `<self_ty as DiscriminantKind>::Discriminant` + // (or ICE in the case of placeholders). Projecting a type to itself + // is never really productive. + ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { + return Err(NoSolution); + } + + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Bound(..) => bug!( + "unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`", + goal.predicate.self_ty() + ), + }; + ecx.probe(|ecx| { - ecx.eq(goal.param_env, goal.predicate.term, discriminant.into())?; + ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/tests/ui/traits/new-solver/param-discr-kind.rs b/tests/ui/traits/new-solver/param-discr-kind.rs new file mode 100644 index 00000000000..e319ddea106 --- /dev/null +++ b/tests/ui/traits/new-solver/param-discr-kind.rs @@ -0,0 +1,8 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +fn foo<T>(x: T) { + std::mem::discriminant(&x); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/pointee.rs b/tests/ui/traits/new-solver/pointee.rs index fa6ee2e2daf..93c0542ace4 100644 --- a/tests/ui/traits/new-solver/pointee.rs +++ b/tests/ui/traits/new-solver/pointee.rs @@ -7,17 +7,15 @@ use std::ptr::{DynMetadata, Pointee}; trait Trait<U> {} struct MyDst<T: ?Sized>(T); -fn works<T>() { - let _: <T as Pointee>::Metadata = (); - let _: <[T] as Pointee>::Metadata = 1_usize; - let _: <str as Pointee>::Metadata = 1_usize; - let _: <dyn Trait<T> as Pointee>::Metadata = give::<DynMetadata<dyn Trait<T>>>(); - let _: <MyDst<T> as Pointee>::Metadata = (); - let _: <((((([u8],),),),),) as Pointee>::Metadata = 1_usize; -} +fn meta_is<T: Pointee<Metadata = U> + ?Sized, U>() {} -fn give<U>() -> U { - loop {} +fn works<T>() { + meta_is::<T, ()>(); + meta_is::<[T], usize>(); + meta_is::<str, usize>(); + meta_is::<dyn Trait<T>, DynMetadata<dyn Trait<T>>>(); + meta_is::<MyDst<T>, ()>(); + meta_is::<((((([u8],),),),),), usize>(); } fn main() {} diff --git a/tests/ui/traits/new-solver/projection-discr-kind.rs b/tests/ui/traits/new-solver/projection-discr-kind.rs new file mode 100644 index 00000000000..20296b287b1 --- /dev/null +++ b/tests/ui/traits/new-solver/projection-discr-kind.rs @@ -0,0 +1,18 @@ +// compile-flags: -Ztrait-solver=next + +// Check that `<T::Assoc as DiscriminantKind>::Discriminant` doesn't normalize +// to itself and cause overflow/ambiguity. + +trait Foo { + type Assoc; +} + +trait Bar {} +fn needs_bar(_: impl Bar) {} + +fn foo<T: Foo>(x: T::Assoc) { + needs_bar(std::mem::discriminant(&x)); + //~^ ERROR the trait bound `Discriminant<<T as Foo>::Assoc>: Bar` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/projection-discr-kind.stderr b/tests/ui/traits/new-solver/projection-discr-kind.stderr new file mode 100644 index 00000000000..03e28f993e2 --- /dev/null +++ b/tests/ui/traits/new-solver/projection-discr-kind.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Discriminant<<T as Foo>::Assoc>: Bar` is not satisfied + --> $DIR/projection-discr-kind.rs:14:15 + | +LL | needs_bar(std::mem::discriminant(&x)); + | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `Discriminant<<T as Foo>::Assoc>` + | | + | required by a bound introduced by this call + | +note: required by a bound in `needs_bar` + --> $DIR/projection-discr-kind.rs:11:22 + | +LL | fn needs_bar(_: impl Bar) {} + | ^^^ required by this bound in `needs_bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. |
