From 5c9d28d303f316c6cc6895ec742839b79392720a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 5 Jul 2022 13:56:51 +0000 Subject: [PATCH 1/3] Opaque types' generic params do not imply anything about their hidden type's lifetimes --- compiler/rustc_middle/src/ty/visit.rs | 2 +- .../type-alias-impl-trait/constrain_inputs.rs | 24 +++++++-- .../constrain_inputs.stderr | 52 +++++++++++++++++++ .../constrain_inputs_unsound.rs | 31 +++++++++++ .../constrain_inputs_unsound.stderr | 9 ++++ 5 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/constrain_inputs.stderr create mode 100644 src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs create mode 100644 src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 5e042c3acfce2..5f8cb57820210 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -666,7 +666,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // ignore the inputs to a projection, as they may not appear // in the normalized form if self.just_constrained { - if let ty::Projection(..) = t.kind() { + if let ty::Projection(..) | ty::Opaque(..) = t.kind() { return ControlFlow::CONTINUE; } } diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs index c32174288ee68..1300a2e45d57d 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs @@ -1,17 +1,33 @@ -// check-pass - #![feature(type_alias_impl_trait)] -mod foo { +mod lifetime_params { type Ty<'a> = impl Sized; fn defining(s: &str) -> Ty<'_> { s } fn execute(ty: Ty<'_>) -> &str { todo!() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + + type BadFnSig = fn(Ty<'_>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime } -mod bar { +mod type_params { type Ty<'a> = impl FnOnce() -> &'a str; fn defining(s: &str) -> Ty<'_> { move || s } fn execute(ty: Ty<'_>) -> &str { ty() } + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types +} + +// regression test for https://github.com/rust-lang/rust/issues/97104 +mod type_params2 { + type Ty = impl Sized; + fn define(s: T) -> Ty { s } + + type BadFnSig = fn(Ty<&str>) -> &str; + //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types + type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + //~^ ERROR binding for associated type `Output` references an anonymous lifetime } fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr new file mode 100644 index 0000000000000..c35b55df64380 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -0,0 +1,52 @@ +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:6:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { todo!() } + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:9:35 + | +LL | type BadFnSig = fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:11:42 + | +LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:18:31 + | +LL | fn execute(ty: Ty<'_>) -> &str { ty() } + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types + --> $DIR/constrain_inputs.rs:27:37 + | +LL | type BadFnSig = fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types + --> $DIR/constrain_inputs.rs:29:44 + | +LL | type BadTraitRef = dyn Fn(Ty<&str>) -> &str; + | ^^^^ + | + = note: lifetimes appearing in an associated type are not considered constrained + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0581, E0582. +For more information about an error, try `rustc --explain E0581`. diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs new file mode 100644 index 0000000000000..937ca48a52dbd --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs @@ -0,0 +1,31 @@ +#![feature(type_alias_impl_trait)] + +trait Static: 'static {} +impl Static for () {} + +type Gal = impl Static; +fn _defining() -> Gal {} + +trait Callable { type Output; } + +/// We can infer `>::Output: 'static`, +/// because we know `C: 'static` and `Arg: 'static`, +fn box_str(s: C::Output) -> Box + 'static> +where + Arg: Static, + C: ?Sized + Callable + 'static, + C::Output: AsRef, +{ + Box::new(s) +} + +fn extend_lifetime(s: &str) -> Box + 'static> { + type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + //~^ ERROR binding for associated type `Output` references lifetime `'a` + box_str::(s) +} + +fn main() { + //let extended = extend_lifetime(&String::from("hello")); + //println!("{}", extended.as_ref().as_ref()); +} diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr new file mode 100644 index 0000000000000..d5fc46cb1f596 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr @@ -0,0 +1,9 @@ +error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types + --> $DIR/constrain_inputs_unsound.rs:23:58 + | +LL | type MalformedTy = dyn for<'a> Callable, Output = &'a str>; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0582`. From 5cd3cc134a41c92616ff74f652556135404ead8a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Aug 2022 10:23:22 +0000 Subject: [PATCH 2/3] Uncomment unsound code example --- src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs index 937ca48a52dbd..3bae0f1730994 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs_unsound.rs @@ -26,6 +26,6 @@ fn extend_lifetime(s: &str) -> Box + 'static> { } fn main() { - //let extended = extend_lifetime(&String::from("hello")); - //println!("{}", extended.as_ref().as_ref()); + let extended = extend_lifetime(&String::from("hello")); + println!("{}", extended.as_ref().as_ref()); } From 64d11fc8e336344a8b8a55a55131ded4be26cebd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 25 Aug 2022 10:30:46 +0000 Subject: [PATCH 3/3] Clarify some diagnostic messages --- compiler/rustc_typeck/src/astconv/mod.rs | 3 ++- src/test/ui/associated-types/issue-62200.rs | 3 ++- .../ui/associated-types/issue-62200.stderr | 3 ++- src/test/ui/issues/issue-47511.stderr | 3 ++- .../type-alias-impl-trait/constrain_inputs.rs | 4 ++-- .../constrain_inputs.stderr | 18 ++++++++++++------ 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 801063583e633..d66cf6d099ad5 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2940,8 +2940,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // though we can easily give a hint that ought to be // relevant. err.note( - "lifetimes appearing in an associated type are not considered constrained", + "lifetimes appearing in an associated or opaque type are not considered constrained", ); + err.note("consider introducing a named lifetime parameter"); } err.emit(); diff --git a/src/test/ui/associated-types/issue-62200.rs b/src/test/ui/associated-types/issue-62200.rs index 9d18690e96049..499bbd6b6fad2 100644 --- a/src/test/ui/associated-types/issue-62200.rs +++ b/src/test/ui/associated-types/issue-62200.rs @@ -10,6 +10,7 @@ impl T<'_> for S { fn foo(x: impl Fn(>::A) -> >::A) {} //~^ ERROR binding for associated type `Output` references an anonymous lifetime -//~^^ NOTE lifetimes appearing in an associated type are not considered constrained +//~| NOTE lifetimes appearing in an associated or opaque type are not considered constrained +//~| NOTE consider introducing a named lifetime parameter fn main() {} diff --git a/src/test/ui/associated-types/issue-62200.stderr b/src/test/ui/associated-types/issue-62200.stderr index f14cd81fdfe1f..04f0728f58ea8 100644 --- a/src/test/ui/associated-types/issue-62200.stderr +++ b/src/test/ui/associated-types/issue-62200.stderr @@ -4,7 +4,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet LL | fn foo(x: impl Fn(>::A) -> >::A) {} | ^^^^^^^^^^^^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error: aborting due to previous error diff --git a/src/test/ui/issues/issue-47511.stderr b/src/test/ui/issues/issue-47511.stderr index 5b84f7ed62c3a..9998ee0e8d0c6 100644 --- a/src/test/ui/issues/issue-47511.stderr +++ b/src/test/ui/issues/issue-47511.stderr @@ -4,7 +4,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | fn f(_: X) -> X { | ^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references lifetime `'a`, which is not constrained by the fn input types --> $DIR/issue-47511.rs:12:23 diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs index 1300a2e45d57d..03fb64b7b94d7 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs.rs +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.rs @@ -12,7 +12,7 @@ mod lifetime_params { //~^ ERROR binding for associated type `Output` references an anonymous lifetime } -mod type_params { +mod lifetime_params_2 { type Ty<'a> = impl FnOnce() -> &'a str; fn defining(s: &str) -> Ty<'_> { move || s } fn execute(ty: Ty<'_>) -> &str { ty() } @@ -20,7 +20,7 @@ mod type_params { } // regression test for https://github.com/rust-lang/rust/issues/97104 -mod type_params2 { +mod type_params { type Ty = impl Sized; fn define(s: T) -> Ty { s } diff --git a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr index c35b55df64380..93953fd06d1fd 100644 --- a/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr +++ b/src/test/ui/type-alias-impl-trait/constrain_inputs.stderr @@ -4,7 +4,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | fn execute(ty: Ty<'_>) -> &str { todo!() } | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:9:35 @@ -12,7 +13,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | type BadFnSig = fn(Ty<'_>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types --> $DIR/constrain_inputs.rs:11:42 @@ -20,7 +22,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet LL | type BadTraitRef = dyn Fn(Ty<'_>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:18:31 @@ -28,7 +31,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | fn execute(ty: Ty<'_>) -> &str { ty() } | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types --> $DIR/constrain_inputs.rs:27:37 @@ -36,7 +40,8 @@ error[E0581]: return type references an anonymous lifetime, which is not constra LL | type BadFnSig = fn(Ty<&str>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types --> $DIR/constrain_inputs.rs:29:44 @@ -44,7 +49,8 @@ error[E0582]: binding for associated type `Output` references an anonymous lifet LL | type BadTraitRef = dyn Fn(Ty<&str>) -> &str; | ^^^^ | - = note: lifetimes appearing in an associated type are not considered constrained + = note: lifetimes appearing in an associated or opaque type are not considered constrained + = note: consider introducing a named lifetime parameter error: aborting due to 6 previous errors