Skip to content

Commit

Permalink
Deny some late-bound ty/ct in some positions, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Feb 13, 2023
1 parent bd3e324 commit 0162292
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 4 deletions.
50 changes: 47 additions & 3 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2883,22 +2883,45 @@ 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);
let repr = match repr {
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);
Expand Down Expand Up @@ -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<ErrorGuaranteed> {
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() })
})
}
3 changes: 2 additions & 1 deletion compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/traits/non_lifetime_binders/basic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// check-pass
// Basic test that show's we can succesfully typeck a `for<T>` where clause.

#![feature(non_lifetime_binders)]
//~^ WARN the feature `non_lifetime_binders` is incomplete

trait Trait {}

impl<T: ?Sized> Trait for T {}

fn foo()
where
for<T> T: Trait,
{
}

fn main() {
foo();
}
11 changes: 11 additions & 0 deletions tests/ui/traits/non_lifetime_binders/basic.stderr
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/1> for more information
= note: `#[warn(incomplete_features)]` on by default

warning: 1 warning emitted

23 changes: 23 additions & 0 deletions tests/ui/traits/non_lifetime_binders/fail.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Error reporting for where `for<T> T: Trait` doesn't hold

#![feature(non_lifetime_binders)]
//~^ WARN the feature `non_lifetime_binders` is incomplete

trait Trait {}

fn fail()
where
for<T> T: Trait,
{}

fn auto_trait()
where
for<T> T: Send,
{}

fn main() {
fail();
//~^ ERROR the trait bound `T: Trait` is not satisfied
auto_trait();
//~^ ERROR `T` cannot be sent between threads safely
}
43 changes: 43 additions & 0 deletions tests/ui/traits/non_lifetime_binders/fail.stderr
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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> 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> 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`.
13 changes: 13 additions & 0 deletions tests/ui/traits/non_lifetime_binders/on-dyn.rs
Original file line number Diff line number Diff line change
@@ -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<T> {}

fn foo() -> &'static dyn for<T> Test<T> {
//~^ ERROR late-bound type parameter not allowed on trait object types
todo!()
}

fn main() {}
17 changes: 17 additions & 0 deletions tests/ui/traits/non_lifetime_binders/on-dyn.stderr
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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<T> Test<T> {
| ^

error: aborting due to previous error; 1 warning emitted

13 changes: 13 additions & 0 deletions tests/ui/traits/non_lifetime_binders/on-ptr.rs
Original file line number Diff line number Diff line change
@@ -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<T> fn(T) {
//~^ ERROR late-bound type parameter not allowed on function pointer types
todo!()
}

fn main() {
foo()(1i32);
}
17 changes: 17 additions & 0 deletions tests/ui/traits/non_lifetime_binders/on-ptr.stderr
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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<T> fn(T) {
| ^

error: aborting due to previous error; 1 warning emitted

0 comments on commit 0162292

Please sign in to comment.