-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Normalize the RHS of an Unsize
goal in the new solver
#113393
Normalize the RHS of an Unsize
goal in the new solver
#113393
Conversation
Unsize
goalUnsize
goal in the new solver
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #113429) made this pull request unmergeable. Please resolve the merge conflicts. |
…in-selection, r=lcnr Structurally normalize in selection We need to do this because of the fact that we're checking the `Ty::kind` on a type during selection, but goals passed into select are not necessarily normalized. Right now, we're (kinda) unnecessarily normalizing the RHS of a trait upcasting goal, which is broken for different reasons (rust-lang#113393). But I'm waiting for this PR to land before discussing that one. r? `@lcnr`
a04d098
to
7035cb0
Compare
☔ The latest upstream changes (presumably #113637) made this pull request unmergeable. Please resolve the merge conflicts. |
…in-selection, r=lcnr Structurally normalize in selection We need to do this because of the fact that we're checking the `Ty::kind` on a type during selection, but goals passed into select are not necessarily normalized. Right now, we're (kinda) unnecessarily normalizing the RHS of a trait upcasting goal, which is broken for different reasons (rust-lang#113393). But I'm waiting for this PR to land before discussing that one. r? `@lcnr`
…in-selection, r=lcnr Structurally normalize in selection We need to do this because of the fact that we're checking the `Ty::kind` on a type during selection, but goals passed into select are not necessarily normalized. Right now, we're (kinda) unnecessarily normalizing the RHS of a trait upcasting goal, which is broken for different reasons (rust-lang#113393). But I'm waiting for this PR to land before discussing that one. r? `@lcnr`
7035cb0
to
6a0d852
Compare
84a2a55
to
e054b79
Compare
Some changes occurred to the core trait solver cc @rust-lang/initiative-trait-system-refactor |
r? lcnr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vibe: instead of adding separate impl sources for "special builtin sources", would it be nicer to change impl source builtin to
Builtin(BuiltinSourceData<'tcx>, Vec<N>)`
apart from that r=me
return vec![]; | ||
}; | ||
// Need to wrap in a probe since `normalize_non_self_ty` has side-effects. | ||
ecx.probe(|_| CandidateKind::DynUpcastingAssembly).enter(|ecx| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this probe feels quite complex now 🤔 is there something in here that we can move into a separate function?
also realized that
trait Trait {
fn foo(&self);
}
fn foo(x: Box<dyn Trait + Send>) -> Box<dyn Send> {
x
}
doesn't compile, this feels like an oversight to me? 🤔 i would except us to accept this 🤔 at least unstably
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I probably just forgot to handle the "dropping principal" case. I'll have to see how the current solver handles it, and see where I forgot to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, this doesn't work in the old solver either. I need to put this up in a separate PR -- while I do want to support this, it'll need T-lang FCP 🤣
I would, and I agree that adding a new |
8b8198b
to
71512ff
Compare
This comment has been minimized.
This comment has been minimized.
71512ff
to
0ffff70
Compare
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a lot of style suggestions and nits, I would love to see all of them implemented, but feel free to leave some of them as future work if you want. Going to not merge any PR which conflicts in the new solver until we land this.
@@ -172,7 +173,8 @@ impl Qualif for NeedsNonConstDrop { | |||
|
|||
if !matches!( | |||
impl_src, | |||
ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) | |||
ImplSource::Builtin(BuiltinImplSource::Misc, _) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all builtin destruct impls are not const 😅 i would like us to still use all ImplSource::Builtin
in this match, or even make this exhaustive xx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm gonna leave this here for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all builtin destruct impls are not const
Also, what do you mean? They're definitely const in the old solver?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a question of what exactly this fn does... missed the double negation of 1) returning true
if it is not const and 2) the !
infront of the match.
This automatically considers all builtin impls const if their source is Misc
which feels like a footgun to me 🤔 anyways, const trait is a bigger issue ^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sorry, I didn't understand what you meant there. Yeah, shrug... not really changing behavior here
param_env: ty::ParamEnv<'tcx>, | ||
a_ty: Ty<'tcx>, | ||
b_ty: Ty<'tcx>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
param_env: ty::ParamEnv<'tcx>, | |
a_ty: Ty<'tcx>, | |
b_ty: Ty<'tcx>, | |
goal: Goal<'tcx, (Ty<'tcx, Ty<'tcx>)>, |
🤔 and then let (a, b) = goal.predicate;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vibe: maybe this match should live in consider_builtin_unsize_and_upcast_candidates
and we probe in the match relevant match arms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really know what you're asking for in that "vibe" comment lol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of calling consider_builtin_unsize_candidate
and consider_builtin_upcast_candidates
for all a and b and then matching in each function individually, match on a
and b
in consider_builtin_unsize_and_upcast_candidates
... I guess merge unsize and upcast builtin impls back together completely 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I just thought the nesting was getting kinda gnarly when they were in one method. Yeah, I guess I can try that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess maybe move bigger match branches into separate functions, so we'd have consider_trait_upcast_candidates
, consider_tuple_unsize_candidate
and so on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That refactoring work is literally miserable actually, lol. I'm gonna do this in a follow-up, I don't think the current split we have right now is that different from what we currently have -- you're essentially just asking to break up consider_builtin_unsize_candidate
.
@@ -48,12 +48,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |||
let mut impl_src = match candidate { | |||
BuiltinCandidate { has_nested } => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for future PR, we should do the same for old style candidates 😁
have BuiltinCandidate
with a CandidateKind
. Definitely not in this PR
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Outdated
Show resolved
Hide resolved
0f97129
to
17ca258
Compare
Some changes occurred in cc @BoxyUwU Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri |
17ca258
to
eb92cf8
Compare
eb92cf8
to
a7ed9c1
Compare
// FIXME: We only need to do *any* of this if we're considering a trait goal, | ||
// since we don't need to look at any supertrait or anything if we are doing | ||
// a projection goal. | ||
if let Some(principal) = bounds.principal() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will maybe look at this myself in a separate PR, but this would be in the ExistentialPredicate::Trait
match arm instead 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only realized what you meant here after the PR. Yeah, if you want to follow-up with this and any other structural changes you'd like to see about this code, I'd be glad to review it.
@@ -404,20 +526,27 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { | |||
// Check that the type implements all of the predicates of the def-id. | |||
// (i.e. the principal, all of the associated types match, and any auto traits) | |||
ecx.add_goals( | |||
data.iter().map(|pred| goal.with(tcx, pred.with_self_ty(tcx, a_ty))), | |||
data.iter() | |||
.map(|pred| Goal::new(tcx, param_env, pred.with_self_ty(tcx, a_ty))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggested to use goal
as an arg to use goal.with
here, will experiment a bit with the code layout myself here after this is merged
@bors r+ rollup=never likely to get merge conflicts |
☀️ Test successful - checks-actions |
Finished benchmarking commit (8327047): comparison URL. Overall result: no relevant changes - no action needed@rustbot label: -perf-regression Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 650.083s -> 650.593s (0.08%) |
…hs, r=lcnr Normalize the RHS of an `Unsize` goal in the new solver `Unsize` goals are... tricky. Not only do they structurally match on their self type, but they're also structural on their other type parameter. I'm pretty certain that it is both incomplete and also just plain undesirable to not consider normalizing the RHS of an unsize goal. More practically, I'd like for this code to work: ```rust trait A {} trait B: A {} impl A for usize {} impl B for usize {} trait Mirror { type Assoc: ?Sized; } impl<T: ?Sized> Mirror for T { type Assoc = T; } fn main() { // usize: Unsize<dyn B> let x = Box::new(1usize) as Box<<dyn B as Mirror>::Assoc>; // dyn A: Unsize<dyn B> let y = x as Box<<dyn A as Mirror>::Assoc>; } ``` --- In order to achieve this, we add `EvalCtxt::normalize_non_self_ty` (naming modulo bikeshedding), which *must* be used for all non-self type arguments that are structurally matched in candidate assembly. Currently this is only necessary for `Unsize`'s argument, but I could see future traits requiring this (hopefully rarely) in the future. It uses `repeat_while_none` to limit infinite looping, and normalizes the self type until it is no longer an alias. Also, we need to fix feature gate detection for `trait_upcasting` and `unsized_tuple_coercion` when HIR typeck has unnormalized types. We can do that by checking the `ImplSource` returned by selection, which necessitates adding a new impl source for tuple upcasting.
Unsize
goals are... tricky. Not only do they structurally match on their self type, but they're also structural on their other type parameter. I'm pretty certain that it is both incomplete and also just plain undesirable to not consider normalizing the RHS of an unsize goal. More practically, I'd like for this code to work:In order to achieve this, we add
EvalCtxt::normalize_non_self_ty
(naming modulo bikeshedding), which must be used for all non-self type arguments that are structurally matched in candidate assembly. Currently this is only necessary forUnsize
's argument, but I could see future traits requiring this (hopefully rarely) in the future. It usesrepeat_while_none
to limit infinite looping, and normalizes the self type until it is no longer an alias.Also, we need to fix feature gate detection for
trait_upcasting
andunsized_tuple_coercion
when HIR typeck has unnormalized types. We can do that by checking theImplSource
returned by selection, which necessitates adding a new impl source for tuple upcasting.