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

improve _ constants in item signature handling #92582

Merged
merged 5 commits into from
Jan 20, 2022
Merged
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
20 changes: 17 additions & 3 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1210,11 +1210,25 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_ty(Error(DelaySpanBugEmitted(())))
}

/// Like `err` but for constants.
/// Like [TyCtxt::ty_error] but for constants.
#[track_caller]
pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
self.sess
.delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported.");
self.const_error_with_message(
ty,
DUMMY_SP,
"ty::ConstKind::Error constructed but no error reported",
)
}

/// Like [TyCtxt::ty_error_with_message] but for constants.
#[track_caller]
pub fn const_error_with_message<S: Into<MultiSpan>>(
self,
ty: Ty<'tcx>,
span: S,
msg: &str,
) -> &'tcx Const<'tcx> {
self.sess.delay_span_bug(span, msg);
self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty })
}

Expand Down
14 changes: 3 additions & 11 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1148,19 +1148,11 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
if self.visit(ty).is_break() {
return;
}
} else {
// We don't do anything for const infers here.
}
} else {
let local_id = self.tcx.hir().local_def_id(inf.hir_id);
if let Some(did) = self.tcx.opt_const_param_of(local_id) {
if self.visit_def_id(did, "inferred", &"").is_break() {
return;
}
}

// FIXME see above note for same issue.
if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, &inf.to_ty())).is_break() {
return;
}
bug!("visit_infer without typeck_results");
}
intravisit::walk_inf(self, inf);
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod errors;
mod generics;

use crate::bounds::Bounds;
use crate::collect::PlaceholderHirTyCollector;
use crate::collect::HirPlaceholderCollector;
use crate::errors::{
AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits,
TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified,
Expand Down Expand Up @@ -2478,7 +2478,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!(?bound_vars);

// We proactively collect all the inferred type params to emit a single error per fn def.
let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
for ty in decl.inputs {
visitor.visit_ty(ty);
}
Expand Down
46 changes: 26 additions & 20 deletions compiler/rustc_typeck/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ pub struct ItemCtxt<'tcx> {
///////////////////////////////////////////////////////////////////////////

#[derive(Default)]
crate struct PlaceholderHirTyCollector(crate Vec<Span>);
crate struct HirPlaceholderCollector(crate Vec<Span>);

impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
impl<'v> Visitor<'v> for HirPlaceholderCollector {
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
if let hir::TyKind::Infer = t.kind {
self.0.push(t.span);
Expand All @@ -131,6 +131,12 @@ impl<'v> Visitor<'v> for PlaceholderHirTyCollector {
_ => {}
}
}
fn visit_array_length(&mut self, length: &'v hir::ArrayLen) {
if let &hir::ArrayLen::Infer(_, span) = length {
self.0.push(span);
}
intravisit::walk_array_len(self, length)
}
}

struct CollectItemTypesVisitor<'tcx> {
Expand Down Expand Up @@ -175,7 +181,7 @@ crate fn placeholder_type_error<'tcx>(
sugg.push((span, format!(", {}", type_name)));
}

let mut err = bad_placeholder(tcx, "type", placeholder_types, kind);
let mut err = bad_placeholder(tcx, placeholder_types, kind);

// Suggest, but only if it is not a function in const or static
if suggest {
Expand Down Expand Up @@ -233,7 +239,7 @@ fn reject_placeholder_type_signatures_in_item<'tcx>(
_ => return,
};

let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_item(item);

placeholder_type_error(
Expand Down Expand Up @@ -311,7 +317,6 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {

fn bad_placeholder<'tcx>(
tcx: TyCtxt<'tcx>,
placeholder_kind: &'static str,
mut spans: Vec<Span>,
kind: &'static str,
) -> rustc_errors::DiagnosticBuilder<'tcx> {
Expand All @@ -322,8 +327,7 @@ fn bad_placeholder<'tcx>(
tcx.sess,
spans.clone(),
E0121,
"the {} placeholder `_` is not allowed within types on item signatures for {}",
placeholder_kind,
"the placeholder `_` is not allowed within types on item signatures for {}",
kind
);
for span in spans {
Expand Down Expand Up @@ -381,7 +385,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
}

fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
self.tcx().ty_error_with_message(span, "bad_placeholder_type")
self.tcx().ty_error_with_message(span, "bad placeholder type")
}

fn ct_infer(
Expand All @@ -390,13 +394,11 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
_: Option<&ty::GenericParamDef>,
span: Span,
) -> &'tcx Const<'tcx> {
bad_placeholder(self.tcx(), "const", vec![span], "generic").emit();
// Typeck doesn't expect erased regions to be returned from `type_of`.
let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r {
ty::ReErased => self.tcx.lifetimes.re_static,
_ => r,
});
self.tcx().const_error(ty)
self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
}

fn projected_ty_from_poly_trait_ref(
Expand Down Expand Up @@ -739,7 +741,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
match item.kind {
hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id),
hir::ForeignItemKind::Static(..) => {
let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_foreign_item(item);
placeholder_type_error(
tcx,
Expand Down Expand Up @@ -822,7 +824,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
// (#75889): Account for `const C: dyn Fn() -> _ = "";`
if let hir::TyKind::TraitObject(..) = ty.kind {
let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_item(it);
placeholder_type_error(
tcx,
Expand Down Expand Up @@ -858,7 +860,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
hir::TraitItemKind::Const(..) => {
tcx.ensure().type_of(trait_item_id.def_id);
// Account for `const C: _;`.
let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "constant");
}
Expand All @@ -867,7 +869,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
tcx.ensure().item_bounds(trait_item_id.def_id);
tcx.ensure().type_of(trait_item_id.def_id);
// Account for `type T = _;`.
let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
}
Expand All @@ -876,7 +878,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
tcx.ensure().item_bounds(trait_item_id.def_id);
// #74612: Visit and try to find bad placeholders
// even if there is no concrete type.
let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);

placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
Expand All @@ -898,7 +900,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
}
hir::ImplItemKind::TyAlias(_) => {
// Account for `type T = _;`
let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_impl_item(impl_item);

placeholder_type_error(tcx, None, &[], visitor.0, false, None, "associated type");
Expand Down Expand Up @@ -1818,10 +1820,14 @@ fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
/// use inference to provide suggestions for the appropriate type if possible.
fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
debug!(?ty);
use hir::TyKind::*;
match &ty.kind {
Infer => true,
Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty),
Slice(ty) => is_suggestable_infer_ty(ty),
Array(ty, length) => {
is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _))
}
Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
Expand Down Expand Up @@ -1873,9 +1879,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
});
let fn_sig = ty::Binder::dummy(fn_sig);

let mut visitor = PlaceholderHirTyCollector::default();
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_ty(ty);
let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type");
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
let ret_ty = fn_sig.skip_binder().output();
if !ret_ty.references_error() {
if !ret_ty.is_closure() {
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_typeck/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ use super::{bad_placeholder, is_suggestable_infer_ty};
/// This should be called using the query `tcx.opt_const_param_of`.
#[instrument(level = "debug", skip(tcx))]
pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
// FIXME(generic_arg_infer): allow for returning DefIds of inference of
// GenericArg::Infer below. This may require a change where GenericArg::Infer has some flag
// for const or type.
use hir::*;
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

Expand Down Expand Up @@ -753,7 +750,7 @@ fn infer_placeholder_type<'a>(
err.emit();
}
None => {
let mut diag = bad_placeholder(tcx, "type", vec![span], kind);
let mut diag = bad_placeholder(tcx, vec![span], kind);

if !ty.references_error() {
let mut mk_nameable = MakeNameable::new(tcx);
Expand Down
12 changes: 0 additions & 12 deletions src/test/ui/const-generics/generic_arg_infer/array-in-sig.rs

This file was deleted.

This file was deleted.

61 changes: 61 additions & 0 deletions src/test/ui/const-generics/generic_arg_infer/in-signature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#![crate_type = "rlib"]
#![feature(generic_arg_infer)]

struct Foo<const N: usize>;
struct Bar<T, const N: usize>(T);

fn arr_fn() -> [u8; _] {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
[0; 3]
}

fn ty_fn() -> Bar<i32, _> {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
Bar::<i32, 3>(0)
}

fn ty_fn_mixed() -> Bar<_, _> {
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types
Bar::<i32, 3>(0)
}

const ARR_CT: [u8; _] = [0; 3];
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
static ARR_STATIC: [u8; _] = [0; 3];
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
const TY_CT: Bar<i32, _> = Bar::<i32, 3>(0);
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
static TY_STATIC: Bar<i32, _> = Bar::<i32, 3>(0);
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
const TY_CT_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
static TY_STATIC_MIXED: Bar<_, _> = Bar::<i32, 3>(0);
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for static variables
trait ArrAssocConst {
const ARR: [u8; _];
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
}
trait TyAssocConst {
const ARR: Bar<i32, _>;
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
}
trait TyAssocConstMixed {
const ARR: Bar<_, _>;
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for constants
}

trait AssocTy {
type Assoc;
}
impl AssocTy for i8 {
type Assoc = [u8; _];
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
}
impl AssocTy for i16 {
type Assoc = Bar<i32, _>;
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
}
impl AssocTy for i32 {
type Assoc = Bar<_, _>;
//~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types
}
Loading