use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
use rustc_span::def_id::LocalDefId;
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_target::abi::VariantIdx;
use rustc_target::asm::InlineAsmRegOrRegClass;
use std::fmt;
}
}
+pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
+
thir_with_elements! {
arms: ArmId => Arm<'tcx> => "a{}",
blocks: BlockId => Block => "b{}",
exprs: ExprId => Expr<'tcx> => "e{}",
stmts: StmtId => Stmt<'tcx> => "s{}",
+ params: ParamId => Param<'tcx> => "p{}",
+}
+
+/// Description of a type-checked function parameter.
+#[derive(Clone, Debug, HashStable)]
+pub struct Param<'tcx> {
+ /// The pattern that appears in the parameter list, or None for implicit parameters.
+ pub pat: Option<Box<Pat<'tcx>>>,
+ /// The possibly inferred type.
+ pub ty: Ty<'tcx>,
+ /// Span of the explicitly provided type, or None if inferred for closures.
+ pub ty_span: Option<Span>,
+ /// Whether this param is `self`, and how it is bound.
+ pub self_kind: Option<hir::ImplicitSelfKind>,
+ /// HirId for lints.
+ pub hir_id: Option<hir::HirId>,
}
#[derive(Copy, Clone, Debug, HashStable)]
pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
}
+
+ pub fn simple_ident(&self) -> Option<Symbol> {
+ match self.kind {
+ PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
+ Some(name)
+ }
+ _ => None,
+ }
+ }
}
#[derive(Clone, Debug, HashStable)]
Ok(())
}
PatKind::Variant { ref subpatterns, .. } | PatKind::Leaf { ref subpatterns } => {
- let variant = match self.kind {
- PatKind::Variant { adt_def, variant_index, .. } => {
- Some(adt_def.variant(variant_index))
- }
- _ => self.ty.ty_adt_def().and_then(|adt| {
- if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
+ let variant_and_name = match self.kind {
+ PatKind::Variant { adt_def, variant_index, .. } => ty::tls::with(|tcx| {
+ let variant = adt_def.variant(variant_index);
+ let adt_did = adt_def.did();
+ let name = if tcx.get_diagnostic_item(sym::Option) == Some(adt_did)
+ || tcx.get_diagnostic_item(sym::Result) == Some(adt_did)
+ {
+ variant.name.to_string()
+ } else {
+ format!("{}::{}", tcx.def_path_str(adt_def.did()), variant.name)
+ };
+ Some((variant, name))
+ }),
+ _ => self.ty.ty_adt_def().and_then(|adt_def| {
+ if !adt_def.is_enum() {
+ ty::tls::with(|tcx| {
+ Some((adt_def.non_enum_variant(), tcx.def_path_str(adt_def.did())))
+ })
+ } else {
+ None
+ }
}),
};
- if let Some(variant) = variant {
- write!(f, "{}", variant.name)?;
+ if let Some((variant, name)) = &variant_and_name {
+ write!(f, "{}", name)?;
// Only for Adt we can have `S {...}`,
// which we handle separately here.
}
}
- let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
- if num_fields != 0 || variant.is_none() {
+ let num_fields =
+ variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
+ if num_fields != 0 || variant_and_name.is_none() {
write!(f, "(")?;
for i in 0..num_fields {
write!(f, "{}", start_or_comma())?;
static_assert_size!(Block, 56);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
- static_assert_size!(Pat<'_>, 72);
- static_assert_size!(PatKind<'_>, 56);
- static_assert_size!(Stmt<'_>, 56);
- static_assert_size!(StmtKind<'_>, 48);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(Pat<'_>, 64);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(PatKind<'_>, 48);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(Stmt<'_>, 48);
+ #[cfg(not(bootstrap))]
+ static_assert_size!(StmtKind<'_>, 40);
}