Skip to content

Commit

Permalink
Account for bad placeholder types in where clauses
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Mar 23, 2020
1 parent 5ae85f4 commit e75158d
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 86 deletions.
34 changes: 14 additions & 20 deletions src/librustc_typeck/astconv.rs
Expand Up @@ -20,7 +20,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::intravisit::{walk_generics, Visitor};
use rustc_hir::print;
use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS};
Expand Down Expand Up @@ -838,18 +838,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
},
);
if !inferred_params.is_empty() {
// We always collect the spans for placeholder types when evaluating `fn`s, but we
// only want to emit an error complaining about them if infer types (`_`) are not
// allowed. `allow_ty_infer` gates this behavior.
crate::collect::placeholder_type_error(
tcx,
inferred_params[0],
&[],
inferred_params,
false,
);
}

self.complain_about_missing_type_params(
missing_type_params,
Expand Down Expand Up @@ -2739,7 +2727,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
hir::TyKind::BareFn(ref bf) => {
require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl, &[], None))
tcx.mk_fn_ptr(self.ty_of_fn(
bf.unsafety,
bf.abi,
&bf.decl,
&hir::Generics::empty(),
None,
))
}
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
Expand Down Expand Up @@ -2922,7 +2916,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
unsafety: hir::Unsafety,
abi: abi::Abi,
decl: &hir::FnDecl<'_>,
generic_params: &[hir::GenericParam<'_>],
generics: &hir::Generics<'_>,
ident_span: Option<Span>,
) -> ty::PolyFnSig<'tcx> {
debug!("ty_of_fn");
Expand All @@ -2934,6 +2928,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
for ty in decl.inputs {
visitor.visit_ty(ty);
}
walk_generics(&mut visitor, generics);

let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
let output_ty = match decl.output {
hir::FnRetTy::Return(ref output) => {
Expand All @@ -2955,7 +2951,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
crate::collect::placeholder_type_error(
tcx,
ident_span.map(|sp| sp.shrink_to_hi()).unwrap_or(DUMMY_SP),
generic_params,
&generics.params[..],
visitor.0,
ident_span.is_some(),
);
Expand All @@ -2981,8 +2977,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.sess,
decl.output.span(),
E0581,
"return type references {} \
which is not constrained by the fn input types",
"return type references {} which is not constrained by the fn input types",
lifetime_name
);
if let ty::BrAnon(_) = *br {
Expand All @@ -2993,8 +2988,7 @@ 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 type are not considered constrained",
);
}
err.emit();
Expand Down
9 changes: 8 additions & 1 deletion src/librustc_typeck/check/mod.rs
Expand Up @@ -1003,7 +1003,14 @@ fn typeck_tables_of_with_fallback<'tcx>(
let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) {
let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl, &[], None)
AstConv::ty_of_fn(
&fcx,
header.unsafety,
header.abi,
decl,
&hir::Generics::empty(),
None,
)
} else {
tcx.fn_sig(def_id)
};
Expand Down
22 changes: 12 additions & 10 deletions src/librustc_typeck/collect.rs
Expand Up @@ -1502,7 +1502,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
sig.header.unsafety,
sig.header.abi,
&sig.decl,
&generics.params[..],
&generics,
Some(ident.span),
),
}
Expand All @@ -1513,14 +1513,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
ident,
generics,
..
}) => AstConv::ty_of_fn(
&icx,
header.unsafety,
header.abi,
decl,
&generics.params[..],
Some(ident.span),
),
}) => {
AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span))
}

ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => {
let abi = tcx.hir().get_foreign_abi(hir_id);
Expand Down Expand Up @@ -2142,7 +2137,14 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
} else {
hir::Unsafety::Unsafe
};
let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl, &[], None);
let fty = AstConv::ty_of_fn(
&ItemCtxt::new(tcx, def_id),
unsafety,
abi,
decl,
&hir::Generics::empty(),
None,
);

// Feature gate SIMD types in FFI, since I am not sure that the
// ABIs are handled at all correctly. -huonw
Expand Down
32 changes: 32 additions & 0 deletions src/test/ui/did_you_mean/bad-assoc-ty.rs
Expand Up @@ -49,4 +49,36 @@ trait K<A, B> {}
fn foo<X: K<_, _>>(x: X) {}
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures

fn bar<F>(_: F) where F: Fn() -> _ {}
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures

fn baz<F: Fn() -> _>(_: F) {}
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures

struct L<F>(F) where F: Fn() -> _;
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
struct M<F> where F: Fn() -> _ {
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
a: F,
}
enum N<F> where F: Fn() -> _ {
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
Foo(F),
}

union O<F> where F: Fn() -> _ {
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
//~| ERROR unions with non-`Copy` fields are unstable
foo: F,
}

trait P<F> where F: Fn() -> _ {
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
}

trait Q {
fn foo<F>(_: F) where F: Fn() -> _ {}
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
}

fn main() {}
110 changes: 108 additions & 2 deletions src/test/ui/did_you_mean/bad-assoc-ty.stderr
Expand Up @@ -57,6 +57,19 @@ LL | type J = ty!(u8);
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0658]: unions with non-`Copy` fields are unstable
--> $DIR/bad-assoc-ty.rs:69:1
|
LL | / union O<F> where F: Fn() -> _ {
LL | |
LL | |
LL | | foo: F,
LL | | }
| |_^
|
= note: see issue #55149 <https://github.com/rust-lang/rust/issues/55149> for more information
= help: add `#![feature(untagged_unions)]` to the crate attributes to enable

error[E0223]: ambiguous associated type
--> $DIR/bad-assoc-ty.rs:1:10
|
Expand Down Expand Up @@ -129,8 +142,101 @@ LL | fn foo<X: K<_, _>>(x: X) {}
| ^ ^ not allowed in type signatures
| |
| not allowed in type signatures
|
help: use type parameters instead
|
LL | fn foo<X, T: K<T, T>>(x: X) {}
| ^^^ ^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:52:34
|
LL | fn bar<F>(_: F) where F: Fn() -> _ {}
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | fn bar<F, T>(_: F) where F: Fn() -> T {}
| ^^^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:55:19
|
LL | fn baz<F: Fn() -> _>(_: F) {}
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | fn baz<F, T: Fn() -> T>(_: F) {}
| ^^^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:58:33
|
LL | struct L<F>(F) where F: Fn() -> _;
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | struct L<F, T>(F) where F: Fn() -> T;
| ^^^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:60:30
|
LL | struct M<F> where F: Fn() -> _ {
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | struct M<F, T> where F: Fn() -> T {
| ^^^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:64:28
|
LL | enum N<F> where F: Fn() -> _ {
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | enum N<F, T> where F: Fn() -> T {
| ^^^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:69:29
|
LL | union O<F> where F: Fn() -> _ {
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | union O<F, T> where F: Fn() -> T {
| ^^^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:75:29
|
LL | trait P<F> where F: Fn() -> _ {
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | trait P<F, T> where F: Fn() -> T {
| ^^^ ^

error[E0121]: the type placeholder `_` is not allowed within types on item signatures
--> $DIR/bad-assoc-ty.rs:80:38
|
LL | fn foo<F>(_: F) where F: Fn() -> _ {}
| ^ not allowed in type signatures
|
help: use type parameters instead
|
LL | fn foo<F, T>(_: F) where F: Fn() -> T {}
| ^^^ ^

error: aborting due to 20 previous errors
error: aborting due to 29 previous errors

Some errors have detailed explanations: E0121, E0223.
Some errors have detailed explanations: E0121, E0223, E0658.
For more information about an error, try `rustc --explain E0121`.
5 changes: 0 additions & 5 deletions src/test/ui/typeck/typeck_type_placeholder_item.rs
Expand Up @@ -158,12 +158,9 @@ trait BadTrait<_> {}
//~^ ERROR expected identifier, found reserved identifier `_`
impl BadTrait<_> for BadStruct<_> {}
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
//~| ERROR the type placeholder `_` is not allowed within types on item signatures
//~| ERROR the type placeholder `_` is not allowed within types on item signatures

fn impl_trait() -> impl BadTrait<_> {
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
//~| ERROR the type placeholder `_` is not allowed within types on item signatures
unimplemented!()
}

Expand All @@ -178,14 +175,12 @@ struct BadStruct2<_, T>(_, T);

type X = Box<_>;
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
//~| ERROR the type placeholder `_` is not allowed within types on item signatures

struct Struct;
trait Trait<T> {}
impl Trait<usize> for Struct {}
type Y = impl Trait<_>;
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
//~| ERROR the type placeholder `_` is not allowed within types on item signatures
fn foo() -> Y {
Struct
}
Expand Down

0 comments on commit e75158d

Please sign in to comment.