mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Stall auto-trait assembly for int/float vars in new solver
This commit is contained in:
parent
2a198c7f62
commit
8d2dbba63e
@ -24,21 +24,19 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Error(_)
|
||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Never
|
||||
| ty::Char => Ok(vec![]),
|
||||
|
||||
// Treat this like `struct str([u8]);`
|
||||
// Treat `str` like it's defined as `struct str([u8]);`
|
||||
ty::Str => Ok(vec![tcx.mk_slice(tcx.types.u8)]),
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Alias(ty::Projection, ..)
|
||||
| ty::Placeholder(..) => Err(NoSolution),
|
||||
|
||||
ty::Bound(..)
|
||||
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
| ty::Placeholder(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Infer(_) => {
|
||||
bug!("unexpected type `{ty}`")
|
||||
}
|
||||
|
||||
|
@ -147,24 +147,66 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
|
||||
ecx: &mut EvalCtxt<'_, 'tcx>,
|
||||
goal: Goal<'tcx, Self>,
|
||||
) -> QueryResult<'tcx> {
|
||||
// This differs from the current stable behavior and
|
||||
// fixes #84857. Due to breakage found via crater, we
|
||||
// currently instead lint patterns which can be used to
|
||||
// exploit this unsoundness on stable, see #93367 for
|
||||
// more details.
|
||||
//
|
||||
// Using `TreatProjections::NextSolverLookup` is fine here because
|
||||
// `instantiate_constituent_tys_for_auto_trait` returns nothing for
|
||||
// projection types anyways. So it doesn't really matter what we do
|
||||
// here, and this is faster.
|
||||
if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
|
||||
goal.predicate.def_id(),
|
||||
goal.predicate.self_ty(),
|
||||
TreatProjections::NextSolverLookup,
|
||||
Some,
|
||||
) {
|
||||
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
|
||||
return Err(NoSolution);
|
||||
let self_ty = goal.predicate.self_ty();
|
||||
match *self_ty.kind() {
|
||||
// Stall int and float vars until they are resolved to a concrete
|
||||
// numerical type. That's because the check for impls below treats
|
||||
// int vars as matching any impl. Even if we filtered such impls,
|
||||
// we probably don't want to treat an `impl !AutoTrait for i32` as
|
||||
// disqualifying the built-in auto impl for `i64: AutoTrait` either.
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
|
||||
return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
|
||||
}
|
||||
|
||||
// These types cannot be structurally decomposed into constitutent
|
||||
// types, and therefore have no builtin impl.
|
||||
ty::Dynamic(..)
|
||||
| ty::Param(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Alias(ty::Projection, ..)
|
||||
| ty::Placeholder(..) => return Err(NoSolution),
|
||||
|
||||
ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),
|
||||
|
||||
// For rigid types, we only register a builtin auto implementation
|
||||
// if there is no implementation that could ever apply to the self
|
||||
// type.
|
||||
//
|
||||
// This differs from the current stable behavior and fixes #84857.
|
||||
// Due to breakage found via crater, we currently instead lint
|
||||
// patterns which can be used to exploit this unsoundness on stable,
|
||||
// see #93367 for more details.
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::Str
|
||||
| ty::Array(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(_)
|
||||
| ty::Ref(_, _, _)
|
||||
| ty::FnDef(_, _)
|
||||
| ty::FnPtr(_)
|
||||
| ty::Closure(_, _)
|
||||
| ty::Generator(_, _, _)
|
||||
| ty::GeneratorWitness(_)
|
||||
| ty::GeneratorWitnessMIR(_, _)
|
||||
| ty::Never
|
||||
| ty::Tuple(_)
|
||||
| ty::Error(_)
|
||||
| ty::Adt(_, _)
|
||||
| ty::Alias(ty::Opaque, _) => {
|
||||
if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
|
||||
goal.predicate.def_id(),
|
||||
goal.predicate.self_ty(),
|
||||
TreatProjections::NextSolverLookup,
|
||||
Some,
|
||||
) {
|
||||
debug!(?def_id, ?goal, "disqualified auto-trait implementation");
|
||||
return Err(NoSolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
||||
|
8
tests/ui/traits/new-solver/int-var-is-send.rs
Normal file
8
tests/ui/traits/new-solver/int-var-is-send.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
|
||||
fn needs_send(_: impl Send) {}
|
||||
|
||||
fn main() {
|
||||
needs_send(1);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
error[E0277]: the trait bound `i32: Foo` is not satisfied
|
||||
--> $DIR/stall-num-var-auto-trait.rs:18:15
|
||||
|
|
||||
LL | needs_foo(x);
|
||||
| --------- ^ the trait `Foo` is not implemented for `i32`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `needs_foo`
|
||||
--> $DIR/stall-num-var-auto-trait.rs:14:22
|
||||
|
|
||||
LL | fn needs_foo(x: impl Foo) {}
|
||||
| ^^^ required by this bound in `needs_foo`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
25
tests/ui/traits/new-solver/stall-num-var-auto-trait.rs
Normal file
25
tests/ui/traits/new-solver/stall-num-var-auto-trait.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
// revisions: fallback constrain
|
||||
//[constrain] check-pass
|
||||
|
||||
// Tests that we stall the `{integer}: Foo` obligation until after we
|
||||
// constrain the int type (or fallback occurs).
|
||||
|
||||
#![feature(negative_impls, auto_traits)]
|
||||
|
||||
auto trait Foo {}
|
||||
|
||||
impl !Foo for i32 {}
|
||||
|
||||
fn needs_foo(x: impl Foo) {}
|
||||
|
||||
fn main() {
|
||||
let mut x = 0;
|
||||
needs_foo(x);
|
||||
//[fallback]~^ ERROR the trait bound `i32: Foo` is not satisfied
|
||||
|
||||
#[cfg(constrain)]
|
||||
{
|
||||
x = 1u64;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user