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

Actually use placeholder regions for trait method late bound regions in collect_return_position_impl_trait_in_trait_tys #133428

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
32 changes: 8 additions & 24 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_sig = ocx.normalize(
&misc_cause,
param_env,
tcx.liberate_late_bound_regions(
impl_m.def_id,
infcx.instantiate_binder_with_fresh_vars(
return_span,
infer::HigherRankedType,
tcx.fn_sig(impl_m.def_id).instantiate_identity(),
),
);
Expand All @@ -536,10 +537,9 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// them with inference variables.
// We will use these inference variables to collect the hidden types of RPITITs.
let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
let unnormalized_trait_sig = infcx
.instantiate_binder_with_fresh_vars(
return_span,
infer::HigherRankedType,
let unnormalized_trait_sig = tcx
.liberate_late_bound_regions(
impl_m.def_id,
tcx.fn_sig(trait_m.def_id).instantiate(tcx, trait_to_impl_args),
)
.fold_with(&mut collector);
Expand Down Expand Up @@ -702,8 +702,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(

let mut remapped_types = DefIdMap::default();
for (def_id, (ty, args)) in collected_types {
match infcx.fully_resolve((ty, args)) {
Ok((ty, args)) => {
match infcx.fully_resolve(ty) {
Ok(ty) => {
// `ty` contains free regions that we created earlier while liberating the
// trait fn signature. However, projection normalization expects `ty` to
// contains `def_id`'s early-bound regions.
Expand Down Expand Up @@ -883,22 +883,6 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
self.tcx
}

fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
Copy link
Member Author

Choose a reason for hiding this comment

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

We don't need this.

In fact, it has the potential to cause ICEs since us not remapping bivariant lifetimes on opaques may lead us to leaking infer vars into query responses. This does not happen in practice though.

if let ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = *t.kind() {
let mut mapped_args = Vec::with_capacity(args.len());
for (arg, v) in std::iter::zip(args, self.tcx.variances_of(def_id)) {
mapped_args.push(match (arg.unpack(), v) {
// Skip uncaptured opaque args
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
_ => arg.try_fold_with(self)?,
});
}
Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_args(&mapped_args)))
} else {
t.try_super_fold_with(self)
}
}

fn try_fold_region(
&mut self,
region: ty::Region<'tcx>,
Expand Down
30 changes: 30 additions & 0 deletions tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Make sure that we don't accidentally collect an RPITIT hidden type that does not
// hold for all instantiations of the trait signature.

trait MkStatic {
fn mk_static(self) -> &'static str;
}

impl MkStatic for &'static str {
fn mk_static(self) -> &'static str { self }
}

trait Foo {
fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic;
}

impl Foo for str {
fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
//~^ ERROR method not compatible with trait
self
}
}

fn call_foo<T: Foo + ?Sized>(t: &T) -> &'static str {
t.foo().mk_static()
}

fn main() {
let s = call_foo(String::from("hello, world").as_str());
println!("> {s}");
}
22 changes: 22 additions & 0 deletions tests/ui/impl-trait/in-trait/do-not-imply-from-trait-impl.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
error[E0308]: method not compatible with trait
--> $DIR/do-not-imply-from-trait-impl.rs:17:38
|
LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
| ^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected signature `fn(&'late _) -> _`
found signature `fn(&'a _) -> _`
note: the lifetime `'late` as defined here...
--> $DIR/do-not-imply-from-trait-impl.rs:13:25
|
LL | fn foo<'a: 'static, 'late>(&'late self) -> impl MkStatic;
| ^^^^^
note: ...does not necessarily outlive the lifetime `'a` as defined here
--> $DIR/do-not-imply-from-trait-impl.rs:17:12
|
LL | fn foo<'a: 'static>(&'a self) -> impl MkStatic + 'static {
| ^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ note: type in trait
|
LL | fn early<'early, T>(x: &'early T) -> impl Sized;
| ^^^^^^^^^
= note: expected signature `fn(&T)`
found signature `fn(&'late ())`
= note: expected signature `fn(&'early T)`
found signature `fn(&())`
help: change the parameter type to match the trait
|
LL | fn early<'late, T>(_: &T) {}
| ~~
LL | fn early<'late, T>(_: &'early T) {}
Copy link
Member Author

@compiler-errors compiler-errors Nov 24, 2024

Choose a reason for hiding this comment

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

You may think, wow this diagnostic sucks, since it's mentioning a lifetime that isn't even in the signature.

Well, it does suck, but it doesn't suck any more than the error you would get from the code if it had no RPITITs. So I don't think it needs fixing here.

| ~~~~~~~~~

error: aborting due to 1 previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) {
|
= note: the pointer is valid for the static lifetime
note: but the referenced data is only valid for the anonymous lifetime defined here
--> $DIR/rpitit-hidden-types-self-implied-wf.rs:6:18
--> $DIR/rpitit-hidden-types-self-implied-wf.rs:2:18
|
LL | fn extend(s: &str) -> (Option<&'static &'_ ()>, &'static str) {
LL | fn extend(_: &str) -> (impl Sized + '_, &'static str);
| ^^^^

error: aborting due to 1 previous error
Expand Down
15 changes: 8 additions & 7 deletions tests/ui/impl-trait/in-trait/signature-mismatch.failure.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
error[E0623]: lifetime mismatch
error[E0477]: the type `impl Future<Output = Vec<u8>>` does not fulfill the required lifetime
--> $DIR/signature-mismatch.rs:77:10
|
LL | &'a self,
| -------- this parameter and the return type are declared with different lifetimes...
...
LL | ) -> impl Future<Output = Vec<u8>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| ...but data from `buff` is returned here
|
note: type must outlive the lifetime `'a` as defined here as required by this binding
--> $DIR/signature-mismatch.rs:73:32
|
LL | fn async_fn_reduce_outlive<'a, 'b, T>(
| ^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0623`.
For more information about this error, try `rustc --explain E0477`.
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/in-trait/signature-mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl AsyncTrait for Struct {
buff: &'b [u8],
t: T,
) -> impl Future<Output = Vec<u8>> {
//[failure]~^ ERROR lifetime mismatch
//[failure]~^ ERROR the type `impl Future<Output = Vec<u8>>` does not fulfill the required lifetime
async move {
let _t = t;
vec![]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
error: return type captures more lifetimes than trait definition
--> $DIR/rpitit-impl-captures-too-much.rs:10:39
|
LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<Self>;
| -- this lifetime was captured
...
LL | fn hello(self_: Invariant<'_>) -> impl Sized + use<'_> {}
| -- ^^^^^^^^^^^^^^^^^^^^
| |
| this lifetime was captured
| ^^^^^^^^^^^^^^^^^^^^
|
note: hidden type must only reference lifetimes captured by this impl trait
--> $DIR/rpitit-impl-captures-too-much.rs:6:39
Expand Down
Loading