-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Fix default methods with return-position impl Trait
in trait
#107013
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
Changes from all commits
6fe1f9f
9f76362
52d847b
5e7bb83
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 |
---|---|---|
|
@@ -27,6 +27,7 @@ use crate::infer::{ConstVarValue, ConstVariableValue}; | |
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; | ||
use crate::traits::{Obligation, PredicateObligation}; | ||
use rustc_data_structures::fx::FxHashMap; | ||
use rustc_hir::def::DefKind; | ||
use rustc_middle::traits::ObligationCause; | ||
use rustc_middle::ty::error::TypeError; | ||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; | ||
|
@@ -410,7 +411,7 @@ where | |
let (a, b) = match (a.kind(), b.kind()) { | ||
(&ty::Alias(ty::Opaque, ..), _) => (a, generalize(b, false)?), | ||
(_, &ty::Alias(ty::Opaque, ..)) => (generalize(a, true)?, b), | ||
_ => unreachable!(), | ||
_ => unreachable!("expected an opaque, got {a} and {b}"), | ||
}; | ||
let cause = ObligationCause::dummy_with_span(self.delegate.span()); | ||
let obligations = self | ||
|
@@ -627,6 +628,42 @@ where | |
self.relate_opaques(a, b) | ||
} | ||
|
||
// Handle default-body RPITITs | ||
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. Within a method, relating one of that method's RPITITs against a concrete type should act just like opaque type inference. 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. Looked at this for ~10 minutes and I don't understand it '^^ would probably be best to chat about this in sync next week |
||
( | ||
&ty::Alias(ty::Projection, ty::AliasTy { def_id: a_def_id, .. }), | ||
&ty::Alias(ty::Projection, ty::AliasTy { def_id: b_def_id, .. }), | ||
) if a_def_id == b_def_id | ||
&& self.tcx().def_kind(a_def_id) == DefKind::ImplTraitPlaceholder | ||
&& a_def_id.as_local().map_or(false, |def_id| { | ||
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some() | ||
}) => | ||
{ | ||
infcx.super_combine_tys(self, a, b).or_else(|err| { | ||
self.tcx().sess.delay_span_bug( | ||
self.delegate.span(), | ||
"failure to relate an opaque to itself should result in an error later on", | ||
); | ||
if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) } | ||
}) | ||
} | ||
(&ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. }), _) | ||
if self.tcx().def_kind(def_id) == DefKind::ImplTraitPlaceholder | ||
&& def_id.as_local().map_or(false, |def_id| { | ||
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some() | ||
}) => | ||
{ | ||
self.relate_opaques(self.tcx().mk_opaque(def_id, substs), b) | ||
} | ||
|
||
(_, &ty::Alias(ty::Projection, ty::AliasTy { def_id, substs, .. })) | ||
if self.tcx().def_kind(def_id) == DefKind::ImplTraitPlaceholder | ||
&& def_id.as_local().map_or(false, |def_id| { | ||
self.infcx.opaque_type_origin(def_id, self.delegate.span()).is_some() | ||
}) => | ||
{ | ||
self.relate_opaques(a, self.tcx().mk_opaque(def_id, substs)) | ||
} | ||
|
||
(&ty::Alias(ty::Projection, projection_ty), _) | ||
if D::normalization() == NormalizationStrategy::Lazy => | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,7 +52,7 @@ impl<'tcx> InferCtxt<'tcx> { | |
span: Span, | ||
param_env: ty::ParamEnv<'tcx>, | ||
) -> InferOk<'tcx, T> { | ||
if !value.has_opaque_types() { | ||
if !value.has_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. We need to handle either RPITITs (projections) and opaques... hopefully this doesn't hurt perf too much :/ |
||
return InferOk { value, obligations: vec![] }; | ||
} | ||
let mut obligations = vec![]; | ||
|
@@ -66,8 +66,11 @@ impl<'tcx> InferCtxt<'tcx> { | |
lt_op: |lt| lt, | ||
ct_op: |ct| ct, | ||
ty_op: |ty| match *ty.kind() { | ||
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) | ||
if replace_opaque_type(def_id) => | ||
ty::Alias(_, ty::AliasTy { def_id, substs, .. }) | ||
if matches!( | ||
self.tcx.def_kind(def_id), | ||
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder | ||
) && replace_opaque_type(def_id) => | ||
{ | ||
let def_span = self.tcx.def_span(def_id); | ||
let span = if span.contains(def_span) { def_span } else { span }; | ||
|
@@ -81,9 +84,15 @@ impl<'tcx> InferCtxt<'tcx> { | |
span, | ||
}); | ||
obligations.extend( | ||
self.handle_opaque_type(ty, ty_var, true, &cause, param_env) | ||
.unwrap() | ||
.obligations, | ||
self.handle_opaque_type( | ||
self.tcx.mk_opaque(def_id, substs), | ||
ty_var, | ||
true, | ||
&cause, | ||
param_env, | ||
) | ||
.unwrap() | ||
.obligations, | ||
); | ||
ty_var | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// run-pass | ||
// edition:2021 | ||
// check-run-results | ||
|
||
#![feature(async_fn_in_trait)] | ||
//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use | ||
|
||
use std::future::Future; | ||
|
||
trait AsyncTrait { | ||
async fn default_impl() { | ||
println!("A"); | ||
} | ||
|
||
async fn call_default_impl() { | ||
Self::default_impl().await | ||
} | ||
} | ||
|
||
struct AsyncType; | ||
|
||
impl AsyncTrait for AsyncType { | ||
async fn default_impl() { | ||
println!("B"); | ||
} | ||
} | ||
|
||
async fn async_main() { | ||
AsyncType::call_default_impl().await; | ||
} | ||
|
||
// ------------------------------------------------------------------------- // | ||
// Implementation Details Below... | ||
|
||
use std::pin::Pin; | ||
use std::task::*; | ||
|
||
pub fn noop_waker() -> Waker { | ||
let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE); | ||
|
||
// SAFETY: the contracts for RawWaker and RawWakerVTable are upheld | ||
unsafe { Waker::from_raw(raw) } | ||
} | ||
|
||
const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); | ||
|
||
unsafe fn noop_clone(_p: *const ()) -> RawWaker { | ||
RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE) | ||
} | ||
|
||
unsafe fn noop(_p: *const ()) {} | ||
|
||
fn main() { | ||
let mut fut = async_main(); | ||
|
||
// Poll loop, just to test the future... | ||
let waker = noop_waker(); | ||
let ctx = &mut Context::from_waker(&waker); | ||
|
||
loop { | ||
match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { | ||
Poll::Pending => {} | ||
Poll::Ready(()) => break, | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
B | ||
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. instead of printing stuff return a |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes | ||
--> $DIR/async-default-fn-overridden.rs:5:12 | ||
| | ||
LL | #![feature(async_fn_in_trait)] | ||
| ^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information | ||
= note: `#[warn(incomplete_features)]` on by default | ||
|
||
warning: 1 warning emitted | ||
|
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.
Within a method, treat its own RPITITs as
ty::Opaque
.This probably could be a custom folder so it's more efficient... perf will tell.