use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
///////////////////////////////////////////////////////////////////////////
/// Context specific to some particular item. This is what implements
-/// `AstConv`. It has information about the predicates that are defined
+/// [`AstConv`].
+///
+/// # `ItemCtxt` vs `FnCtxt`
+///
+/// `ItemCtxt` is primarily used to type-check item signatures and lower them
+/// from HIR to their [`ty::Ty`] representation, which is exposed using [`AstConv`].
+/// It's also used for the bodies of items like structs where the body (the fields)
+/// are just signatures.
+///
+/// This is in contrast to [`FnCtxt`], which is used to type-check bodies of
+/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
+///
+/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
+/// while `FnCtxt` does do inference.
+///
+/// [`FnCtxt`]: crate::check::FnCtxt
+/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
+///
+/// # Trait predicates
+///
+/// `ItemCtxt` has information about the predicates that are defined
/// on the trait. Unfortunately, this predicate information is
/// available in various different forms at various points in the
/// process. So we can't just store a pointer to e.g., the AST or the
/// Returns the predicates defined on `item_def_id` of the form
/// `X: Foo` where `X` is the type parameter `def_id`.
+#[instrument(level = "trace", skip(tcx))]
fn type_param_predicates(
tcx: TyCtxt<'_>,
(item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
assoc_name: Option<Ident>,
) -> Vec<(ty::Predicate<'tcx>, Span)> {
let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
- debug!(?param_def_id);
+ trace!(?param_def_id);
ast_generics
.predicates
.iter()
.collect()
}
+ #[instrument(level = "trace", skip(self))]
fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
- debug!("bound_defines_assoc_item(b={:?}, assoc_name={:?})", b, assoc_name);
-
match b {
hir::GenericBound::Trait(poly_trait_ref, _) => {
let trait_ref = &poly_trait_ref.trait_ref;
tcx.ensure().type_of(trait_item_id.def_id);
}
- hir::TraitItemKind::Const(..) => {
+ hir::TraitItemKind::Const(hir_ty, _) => {
tcx.ensure().type_of(trait_item_id.def_id);
// Account for `const C: _;`.
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
- placeholder_type_error(tcx, None, visitor.0, false, None, "constant");
+ if !tcx.sess.diagnostic().has_stashed_diagnostic(hir_ty.span, StashKey::ItemNoType) {
+ placeholder_type_error(tcx, None, visitor.0, false, None, "constant");
+ }
}
hir::TraitItemKind::Type(_, Some(_)) => {
}
}
- fn visit_poly_trait_ref(
- &mut self,
- tr: &'tcx hir::PolyTraitRef<'tcx>,
- m: hir::TraitBoundModifier,
- ) {
+ fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) {
if self.has_late_bound_regions.is_some() {
return;
}
self.outer_index.shift_in(1);
- intravisit::walk_poly_trait_ref(self, tr, m);
+ intravisit::walk_poly_trait_ref(self, tr);
self.outer_index.shift_out(1);
}
ItemKind::OpaqueTy(hir::OpaqueTy {
origin:
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
+ in_trait,
..
- }) => Some(fn_def_id.to_def_id()),
+ }) => {
+ if in_trait {
+ assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
+ } else {
+ assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
+ }
+ Some(fn_def_id.to_def_id())
+ }
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
let parent_id = tcx.hir().get_parent_item(hir_id);
assert_ne!(parent_id, CRATE_DEF_ID);
_ => None,
};
+ enum Defaults {
+ Allowed,
+ // See #36887
+ FutureCompatDisallowed,
+ Deny,
+ }
+
let no_generics = hir::Generics::empty();
let ast_generics = node.generics().unwrap_or(&no_generics);
let (opt_self, allow_defaults) = match node {
pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type {
has_default: false,
- object_lifetime_default: rl::Set1::Empty,
synthetic: false,
},
});
- (opt_self, true)
+ (opt_self, Defaults::Allowed)
}
ItemKind::TyAlias(..)
| ItemKind::Enum(..)
| ItemKind::Struct(..)
| ItemKind::OpaqueTy(..)
- | ItemKind::Union(..) => (None, true),
- _ => (None, false),
+ | ItemKind::Union(..) => (None, Defaults::Allowed),
+ _ => (None, Defaults::FutureCompatDisallowed),
}
}
- _ => (None, false),
+
+ // GATs
+ Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
+ (None, Defaults::Deny)
+ }
+ Node::ImplItem(item) if matches!(item.kind, ImplItemKind::TyAlias(..)) => {
+ (None, Defaults::Deny)
+ }
+
+ _ => (None, Defaults::FutureCompatDisallowed),
};
let has_self = opt_self.is_some();
kind: ty::GenericParamDefKind::Lifetime,
}));
- let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id.owner);
-
// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
let mut i = 0;
+ const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
+ `struct`, `enum`, `type`, or `trait` definitions";
+
params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref default, synthetic, .. } => {
- if !allow_defaults && default.is_some() {
- if !tcx.features().default_type_parameter_fallback {
- tcx.struct_span_lint_hir(
- lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
- param.hir_id,
- param.span,
- |lint| {
- lint.build(
- "defaults for type parameters are only allowed in \
- `struct`, `enum`, `type`, or `trait` definitions",
- )
- .emit();
- },
- );
+ if default.is_some() {
+ match allow_defaults {
+ Defaults::Allowed => {}
+ Defaults::FutureCompatDisallowed
+ if tcx.features().default_type_parameter_fallback => {}
+ Defaults::FutureCompatDisallowed => {
+ tcx.struct_span_lint_hir(
+ lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+ param.hir_id,
+ param.span,
+ |lint| {
+ lint.build(TYPE_DEFAULT_NOT_ALLOWED).emit();
+ },
+ );
+ }
+ Defaults::Deny => {
+ tcx.sess.span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED);
+ }
}
}
- let kind = ty::GenericParamDefKind::Type {
- has_default: default.is_some(),
- object_lifetime_default: object_lifetime_defaults
- .as_ref()
- .map_or(rl::Set1::Empty, |o| o[i]),
- synthetic,
- };
+ let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic };
let param_def = ty::GenericParamDef {
index: type_start + i as u32,
Some(param_def)
}
GenericParamKind::Const { default, .. } => {
- if !allow_defaults && default.is_some() {
+ if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
tcx.sess.span_err(
param.span,
"defaults for const parameters are only allowed in \
name: Symbol::intern(arg),
def_id,
pure_wrt_drop: false,
- kind: ty::GenericParamDefKind::Type {
- has_default: false,
- object_lifetime_default: rl::Set1::Empty,
- synthetic: false,
- },
+ kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
}));
}
name: Symbol::intern("<const_ty>"),
def_id,
pure_wrt_drop: false,
- kind: ty::GenericParamDefKind::Type {
- has_default: false,
- object_lifetime_default: rl::Set1::Empty,
- synthetic: false,
- },
+ kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
});
}
}
}
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),
+ OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
Path(hir::QPath::TypeRelative(ty, segment)) => {
is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
}
None
}
+#[instrument(level = "debug", skip(tcx))]
fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
use rustc_hir::Node::*;
use rustc_hir::*;
/// Returns a list of type predicates for the definition with ID `def_id`, including inferred
/// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus
/// inferred constraints concerning which regions outlive other regions.
+#[instrument(level = "debug", skip(tcx))]
fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
- debug!("predicates_defined_on({:?})", def_id);
let mut result = tcx.explicit_predicates_of(def_id);
debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,);
let inferred_outlives = tcx.inferred_outlives_of(def_id);
/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
/// N.B., this does not include any implied/inferred constraints.
+#[instrument(level = "trace", skip(tcx), ret)]
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
- debug!("explicit_predicates_of(def_id={:?})", def_id);
-
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let node = tcx.hir().get(hir_id);
+ has_own_self as u32
+ early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32;
+ trace!(?predicates);
+ trace!(?ast_generics);
+
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T: Foo>`).
for param in ast_generics.params {
Some((param.hir_id, ast_generics.predicates)),
param.span,
);
+ trace!(?bounds);
predicates.extend(bounds.predicates(tcx, param_ty));
+ trace!(?predicates);
}
GenericParamKind::Const { .. } => {
// Bounds on const parameters are currently not possible.
}
}
+ trace!(?predicates);
// Add in the bounds that appear in the where-clause.
for predicate in ast_generics.predicates {
match predicate {
);
}
- let result = ty::GenericPredicates {
+ ty::GenericPredicates {
parent: generics.parent,
predicates: tcx.arena.alloc_from_iter(predicates),
- };
- debug!("explicit_predicates_of(def_id={:?}) = {:?}", def_id, result);
- result
+ }
}
fn const_evaluatable_predicates_of<'tcx>(
let def_id = self.tcx.hir().local_def_id(c.hir_id);
let ct = ty::Const::from_anon_const(self.tcx, def_id);
if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
- assert_eq!(uv.promoted, None);
+ assert_eq!(uv.promoted, ());
let span = self.tcx.hir().span(c.hir_id);
self.preds.insert((
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
.to_predicate(self.tcx),
span,
));
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
}
Some(_) => {
- tcx.sess
- .struct_span_err(
- attr.span,
- "expected `used`, `used(compiler)` or `used(linker)`",
- )
- .emit();
+ tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
}
None => {
// Unfortunately, unconditionally using `llvm.used` causes
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
use rustc_ast::{Lit, LitIntType, LitKind};
+ if !tcx.features().raw_dylib && tcx.sess.target.arch == "x86" {
+ feature_err(
+ &tcx.sess.parse_sess,
+ sym::raw_dylib,
+ attr.span,
+ "`#[link_ordinal]` is unstable on x86",
+ )
+ .emit();
+ }
let meta_item_list = attr.meta_item_list();
let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref);
let sole_meta_list = match meta_item_list {