Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No need to validate_alias_bound_self_from_param_env in assemble_alias_bound_candidates #120598

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 1 addition & 115 deletions compiler/rustc_trait_selection/src/solve/assembly/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::solve::GoalSource;
use crate::traits::coherence;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::Reveal;
use rustc_middle::traits::solve::inspect::ProbeKind;
use rustc_middle::traits::solve::{
CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult,
Expand Down Expand Up @@ -70,20 +69,6 @@ pub(super) trait GoalKind<'tcx>:
})
}

/// Consider a bound originating from the item bounds of an alias. For this we
/// require that the well-formed requirements of the self type of the goal
/// are "satisfied from the param-env".
/// See [`EvalCtxt::validate_alias_bound_self_from_param_env`].
fn consider_alias_bound_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
assumption: ty::Clause<'tcx>,
) -> QueryResult<'tcx> {
Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| {
ecx.validate_alias_bound_self_from_param_env(goal)
})
}

/// Consider a clause specifically for a `dyn Trait` self type. This requires
/// additionally checking all of the supertraits and object bounds to hold,
/// since they're not implied by the well-formedness of the object type.
Expand Down Expand Up @@ -557,7 +542,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
for assumption in
self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args)
{
match G::consider_alias_bound_candidate(self, goal, assumption) {
match G::consider_implied_clause(self, goal, assumption, []) {
Ok(result) => {
candidates.push(Candidate { source: CandidateSource::AliasBound, result })
}
Expand All @@ -566,105 +551,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
}
}

/// Check that we are allowed to use an alias bound originating from the self
/// type of this goal. This means something different depending on the self type's
/// alias kind.
///
/// * Projection: Given a goal with a self type such as `<Ty as Trait>::Assoc`,
/// we require that the bound `Ty: Trait` can be proven using either a nested alias
/// bound candidate, or a param-env candidate.
///
/// * Opaque: The param-env must be in `Reveal::UserFacing` mode. Otherwise,
/// the goal should be proven by using the hidden type instead.
#[instrument(level = "debug", skip(self), ret)]
pub(super) fn validate_alias_bound_self_from_param_env<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
) -> QueryResult<'tcx> {
match *goal.predicate.self_ty().kind() {
ty::Alias(ty::Projection, projection_ty) => {
let mut param_env_candidates = vec![];
let self_trait_ref = projection_ty.trait_ref(self.tcx());

if self_trait_ref.self_ty().is_ty_var() {
return self
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
}

let trait_goal: Goal<'_, ty::TraitPredicate<'tcx>> = goal.with(
self.tcx(),
ty::TraitPredicate {
trait_ref: self_trait_ref,
polarity: ty::ImplPolarity::Positive,
},
);

self.assemble_param_env_candidates(trait_goal, &mut param_env_candidates);
// FIXME: We probably need some sort of recursion depth check here.
// Can't come up with an example yet, though, and the worst case
// we can have is a compiler stack overflow...
self.assemble_alias_bound_candidates(trait_goal, &mut param_env_candidates);

// FIXME: We must also consider alias-bound candidates for a peculiar
// class of built-in candidates that I'll call "defaulted" built-ins.
//
// For example, we always know that `T: Pointee` is implemented, but
// we do not always know what `<T as Pointee>::Metadata` actually is,
// similar to if we had a user-defined impl with a `default type ...`.
// For these traits, since we're not able to always normalize their
// associated types to a concrete type, we must consider their alias bounds
// instead, so we can prove bounds such as `<T as Pointee>::Metadata: Copy`.
self.assemble_alias_bound_candidates_for_builtin_impl_default_items(
trait_goal,
&mut param_env_candidates,
);

self.merge_candidates(param_env_candidates)
}
ty::Alias(ty::Opaque, _opaque_ty) => match goal.param_env.reveal() {
Reveal::UserFacing => {
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
Reveal::All => return Err(NoSolution),
},
_ => bug!("only expected to be called on alias tys"),
}
}

/// Assemble a subset of builtin impl candidates for a class of candidates called
/// "defaulted" built-in traits.
///
/// For example, we always know that `T: Pointee` is implemented, but we do not
/// always know what `<T as Pointee>::Metadata` actually is! See the comment in
/// [`EvalCtxt::validate_alias_bound_self_from_param_env`] for more detail.
#[instrument(level = "debug", skip_all)]
fn assemble_alias_bound_candidates_for_builtin_impl_default_items<G: GoalKind<'tcx>>(
&mut self,
goal: Goal<'tcx, G>,
candidates: &mut Vec<Candidate<'tcx>>,
) {
let lang_items = self.tcx().lang_items();
let trait_def_id = goal.predicate.trait_def_id(self.tcx());

// You probably shouldn't add anything to this list unless you
// know what you're doing.
let result = if lang_items.pointee_trait() == Some(trait_def_id) {
G::consider_builtin_pointee_candidate(self, goal)
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
G::consider_builtin_discriminant_kind_candidate(self, goal)
} else {
Err(NoSolution)
};

match result {
Ok(result) => candidates.push(Candidate {
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
result,
}),
Err(NoSolution) => (),
}
}

#[instrument(level = "debug", skip_all)]
fn assemble_object_bound_candidates<G: GoalKind<'tcx>>(
&mut self,
Expand Down
42 changes: 2 additions & 40 deletions tests/ui/for/issue-20605.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,12 @@ error[E0277]: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is
LL | for item in *things { *item = 0 }
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`

error[E0277]: the size for values of type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` cannot be known at compilation time
--> $DIR/issue-20605.rs:5:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter`
= note: all local variables must have a statically known size
= help: unsized locals are gated as an unstable feature

error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:5:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^

error[E0277]: `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only case where this matters is not-well-formed projections, which who cares if they're treated as rigid or not.

--> $DIR/issue-20605.rs:5:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^ `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
|
= help: the trait `Iterator` is not implemented for `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter`

error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:5:17
|
Expand All @@ -40,33 +22,13 @@ error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Into
LL | for item in *things { *item = 0 }
| ^^^^^^^

error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
--> $DIR/issue-20605.rs:5:5
|
LL | for item in *things { *item = 0 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
note: required by a bound in `None`
--> $SRC_DIR/core/src/option.rs:LL:COL

error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
--> $DIR/issue-20605.rs:5:9
|
LL | for item in *things { *item = 0 }
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
= note: all local variables must have a statically known size
= help: unsized locals are gated as an unstable feature

error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
--> $DIR/issue-20605.rs:5:27
|
LL | for item in *things { *item = 0 }
| ^^^^^

error: aborting due to 9 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0277, E0614.
For more information about an error, try `rustc --explain E0277`.
7 changes: 2 additions & 5 deletions tests/ui/for/issue-20605.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
for item in *things { *item = 0 }
//[current]~^ ERROR the size for values of type
//[next]~^^ ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
//[next]~| ERROR the size for values of type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` cannot be known at compilation time
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
//[next]~| ERROR the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
//[next]~| ERROR type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
//[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced

// FIXME(-Znext-solver): these error messages are horrible and have to be
// improved before we stabilize the new solver.
}
Expand Down
1 change: 0 additions & 1 deletion tests/ui/traits/next-solver/object-unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pub fn copy_any<T>(t: &T) -> T {
//~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
//~| ERROR mismatched types
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
//~| ERROR the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time

// FIXME(-Znext-solver): These error messages are horrible and some of them
// are even simple fallout from previous error.
Expand Down
15 changes: 1 addition & 14 deletions tests/ui/traits/next-solver/object-unsafety.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,7 @@ error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
LL | copy::<dyn Setup<From=T>>(t)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
--> $DIR/object-unsafety.rs:12:5
|
LL | copy::<dyn Setup<From=T>>(t)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `<dyn Setup<From = T> as Setup>::From`
= note: the return type of a function must have a statically known size
help: consider further restricting the associated type
|
LL | pub fn copy_any<T>(t: &T) -> T where <dyn Setup<From = T> as Setup>::From: Sized {
| +++++++++++++++++++++++++++++++++++++++++++++++++

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

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