From 016229260a2f404f0e03b7f0df1ac8da6cab649e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 6 Feb 2023 23:53:24 +0000 Subject: [PATCH] Deny some late-bound ty/ct in some positions, add tests --- .../rustc_hir_analysis/src/astconv/mod.rs | 50 +++++++++++++++++-- compiler/rustc_privacy/src/lib.rs | 3 +- tests/ui/traits/non_lifetime_binders/basic.rs | 19 +++++++ .../traits/non_lifetime_binders/basic.stderr | 11 ++++ tests/ui/traits/non_lifetime_binders/fail.rs | 23 +++++++++ .../traits/non_lifetime_binders/fail.stderr | 43 ++++++++++++++++ .../ui/traits/non_lifetime_binders/on-dyn.rs | 13 +++++ .../traits/non_lifetime_binders/on-dyn.stderr | 17 +++++++ .../ui/traits/non_lifetime_binders/on-ptr.rs | 13 +++++ .../traits/non_lifetime_binders/on-ptr.stderr | 17 +++++++ 10 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/non_lifetime_binders/basic.rs create mode 100644 tests/ui/traits/non_lifetime_binders/basic.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/fail.rs create mode 100644 tests/ui/traits/non_lifetime_binders/fail.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/on-dyn.rs create mode 100644 tests/ui/traits/non_lifetime_binders/on-dyn.stderr create mode 100644 tests/ui/traits/non_lifetime_binders/on-ptr.rs create mode 100644 tests/ui/traits/non_lifetime_binders/on-ptr.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index ae738177d76cb..b3f6649a5ae51 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2883,14 +2883,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn( + let fn_ptr_ty = tcx.mk_fn_ptr(self.ty_of_fn( ast_ty.hir_id, bf.unsafety, bf.abi, bf.decl, None, Some(ast_ty), - )) + )); + + if let Some(guar) = + deny_non_region_late_bound(tcx, bf.generic_params, "function pointer") + { + tcx.ty_error_with_guaranteed(guar) + } else { + fn_ptr_ty + } } hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.maybe_lint_bare_trait(ast_ty, in_path); @@ -2898,7 +2906,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, TraitObjectSyntax::DynStar => ty::DynStar, }; - self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr) + + let object_ty = self.conv_object_ty_poly_trait_ref( + ast_ty.span, + bounds, + lifetime, + borrowed, + repr, + ); + + if let Some(guar) = bounds.iter().find_map(|trait_ref| { + deny_non_region_late_bound(tcx, trait_ref.bound_generic_params, "trait object") + }) { + tcx.ty_error_with_guaranteed(guar) + } else { + object_ty + } } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -3359,3 +3382,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } + +fn deny_non_region_late_bound( + tcx: TyCtxt<'_>, + params: &[hir::GenericParam<'_>], + where_: &str, +) -> Option { + params.iter().find_map(|bad_param| { + let what = match bad_param.kind { + hir::GenericParamKind::Type { .. } => "type", + hir::GenericParamKind::Const { .. } => "const", + hir::GenericParamKind::Lifetime { .. } => return None, + }; + + let mut diag = tcx.sess.struct_span_err( + bad_param.span, + format!("late-bound {what} parameter not allowed on {where_} types"), + ); + + Some(if tcx.features().non_lifetime_binders { diag.emit() } else { diag.delay_as_bug() }) + }) +} diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9cff62e85146e..a48dc6c8aeebf 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -270,10 +270,11 @@ where | ty::Ref(..) | ty::FnPtr(..) | ty::Param(..) + | ty::Bound(..) | ty::Error(_) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => {} - ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => { + ty::Placeholder(..) | ty::Infer(..) => { bug!("unexpected type: {:?}", ty) } } diff --git a/tests/ui/traits/non_lifetime_binders/basic.rs b/tests/ui/traits/non_lifetime_binders/basic.rs new file mode 100644 index 0000000000000..a797aae65dba2 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/basic.rs @@ -0,0 +1,19 @@ +// check-pass +// Basic test that show's we can succesfully typeck a `for` where clause. + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Trait {} + +impl Trait for T {} + +fn foo() +where + for T: Trait, +{ +} + +fn main() { + foo(); +} diff --git a/tests/ui/traits/non_lifetime_binders/basic.stderr b/tests/ui/traits/non_lifetime_binders/basic.stderr new file mode 100644 index 0000000000000..fddc5d9fc2548 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/basic.stderr @@ -0,0 +1,11 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/basic.rs:4:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/fail.rs b/tests/ui/traits/non_lifetime_binders/fail.rs new file mode 100644 index 0000000000000..460f68907e889 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/fail.rs @@ -0,0 +1,23 @@ +// Error reporting for where `for T: Trait` doesn't hold + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Trait {} + +fn fail() +where + for T: Trait, +{} + +fn auto_trait() +where + for T: Send, +{} + +fn main() { + fail(); + //~^ ERROR the trait bound `T: Trait` is not satisfied + auto_trait(); + //~^ ERROR `T` cannot be sent between threads safely +} diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr new file mode 100644 index 0000000000000..ba5953193a47b --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -0,0 +1,43 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/fail.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: the trait bound `T: Trait` is not satisfied + --> $DIR/fail.rs:19:5 + | +LL | fail(); + | ^^^^ the trait `Trait` is not implemented for `T` + | +note: required by a bound in `fail` + --> $DIR/fail.rs:10:15 + | +LL | fn fail() + | ---- required by a bound in this +LL | where +LL | for T: Trait, + | ^^^^^ required by this bound in `fail` + +error[E0277]: `T` cannot be sent between threads safely + --> $DIR/fail.rs:21:5 + | +LL | auto_trait(); + | ^^^^^^^^^^ `T` cannot be sent between threads safely + | + = help: the trait `Send` is not implemented for `T` +note: required by a bound in `auto_trait` + --> $DIR/fail.rs:15:15 + | +LL | fn auto_trait() + | ---------- required by a bound in this +LL | where +LL | for T: Send, + | ^^^^ required by this bound in `auto_trait` + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.rs b/tests/ui/traits/non_lifetime_binders/on-dyn.rs new file mode 100644 index 0000000000000..8fb7dd27605f9 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.rs @@ -0,0 +1,13 @@ +// Tests to make sure that we reject polymorphic dyn trait. + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +trait Test {} + +fn foo() -> &'static dyn for Test { + //~^ ERROR late-bound type parameter not allowed on trait object types + todo!() +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/on-dyn.stderr b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr new file mode 100644 index 0000000000000..44071107de411 --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-dyn.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/on-dyn.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on trait object types + --> $DIR/on-dyn.rs:8:30 + | +LL | fn foo() -> &'static dyn for Test { + | ^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.rs b/tests/ui/traits/non_lifetime_binders/on-ptr.rs new file mode 100644 index 0000000000000..0aaff52b6d8cd --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.rs @@ -0,0 +1,13 @@ +// Tests to make sure that we reject polymorphic fn ptrs. + +#![feature(non_lifetime_binders)] +//~^ WARN the feature `non_lifetime_binders` is incomplete + +fn foo() -> for fn(T) { + //~^ ERROR late-bound type parameter not allowed on function pointer types + todo!() +} + +fn main() { + foo()(1i32); +} diff --git a/tests/ui/traits/non_lifetime_binders/on-ptr.stderr b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr new file mode 100644 index 0000000000000..bb7dccaf07d5f --- /dev/null +++ b/tests/ui/traits/non_lifetime_binders/on-ptr.stderr @@ -0,0 +1,17 @@ +warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/on-ptr.rs:3:12 + | +LL | #![feature(non_lifetime_binders)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #1 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: late-bound type parameter not allowed on function pointer types + --> $DIR/on-ptr.rs:6:17 + | +LL | fn foo() -> for fn(T) { + | ^ + +error: aborting due to previous error; 1 warning emitted +