-
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
Only mark projection as ambiguous if GAT substs are constrained #93892
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1508,12 +1508,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
}) | ||
} | ||
|
||
/// Return Some(true) if the obligation's predicate type applies to the env_predicate, and | ||
/// Some(false) if it does not. Returns None in the case that the projection type is a GAT, | ||
/// and applying this env_predicate constrains any of the obligation's GAT substitutions. | ||
pub(super) fn match_projection_projections( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment is slightly outdated now that the return type has changed to an enum There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. |
||
&mut self, | ||
obligation: &ProjectionTyObligation<'tcx>, | ||
env_predicate: PolyProjectionPredicate<'tcx>, | ||
potentially_unnormalized_candidates: bool, | ||
) -> bool { | ||
) -> Option<bool> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's return an enum here |
||
let mut nested_obligations = Vec::new(); | ||
let (infer_predicate, _) = self.infcx.replace_bound_vars_with_fresh_vars( | ||
obligation.cause.span, | ||
|
@@ -1535,7 +1538,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
infer_predicate.projection_ty | ||
}; | ||
|
||
self.infcx | ||
let is_match = self | ||
.infcx | ||
.at(&obligation.cause, obligation.param_env) | ||
.define_opaque_types(false) | ||
.sup(obligation.predicate, infer_projection) | ||
|
@@ -1545,7 +1549,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | |
nested_obligations.into_iter().chain(obligations), | ||
) | ||
.map_or(false, |res| res.may_apply()) | ||
}) | ||
}); | ||
|
||
if is_match { | ||
let generics = self.tcx().generics_of(obligation.predicate.item_def_id); | ||
if !generics.params.is_empty() { | ||
// If any of the obligation's predicate substs shallow-resolve to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I leave a note here saying that this is still kinda a hack? |
||
// something new, that means that we must have newly inferred something | ||
// about the GAT. We should give up with ambiguity in that case. | ||
if obligation.predicate.substs[generics.parent_count..] | ||
.iter() | ||
.any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p) | ||
{ | ||
return None; | ||
} | ||
} | ||
} | ||
|
||
Some(is_match) | ||
} | ||
|
||
/////////////////////////////////////////////////////////////////////////// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// check-pass | ||
|
||
#![feature(generic_associated_types)] | ||
|
||
pub trait Build { | ||
type Output<O>; | ||
fn build<O>(self, input: O) -> Self::Output<O>; | ||
} | ||
|
||
pub struct IdentityBuild; | ||
impl Build for IdentityBuild { | ||
type Output<O> = O; | ||
fn build<O>(self, input: O) -> Self::Output<O> { | ||
input | ||
} | ||
} | ||
|
||
fn a() { | ||
let _x: u8 = IdentityBuild.build(10); | ||
} | ||
|
||
fn b() { | ||
let _x: Vec<u8> = IdentityBuild.build(Vec::new()); | ||
} | ||
|
||
fn c() { | ||
let mut f = IdentityBuild.build(|| ()); | ||
(f)(); | ||
} | ||
|
||
pub fn main() { | ||
a(); | ||
b(); | ||
c(); | ||
} |
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.
Is this diff new?
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.
function returns () and the rest have semicolons, but i'll double check