Skip to content

Commit

Permalink
Overhaul typechecking of patterns
Browse files Browse the repository at this point in the history
Instead of checking patterns in a top-down fashion with a known
expected type on entry, this changes makes typeck establish
appropriate constraints between a pattern and the expression
it destructures, and lets inference compute the final types
or produce good error messages if it's impossible.
  • Loading branch information
Jakub Bukaj committed Oct 24, 2014
1 parent 3e9ce5a commit 4380e96
Show file tree
Hide file tree
Showing 8 changed files with 415 additions and 717 deletions.
2 changes: 0 additions & 2 deletions src/librustc/diagnostics.rs
Expand Up @@ -44,11 +44,9 @@ register_diagnostics!(
E0025,
E0026,
E0027,
E0028,
E0029,
E0030,
E0031,
E0032,
E0033,
E0034,
E0035,
Expand Down
11 changes: 8 additions & 3 deletions src/librustc/metadata/decoder.rs
Expand Up @@ -673,9 +673,14 @@ pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
item, tcx, cdata);
let name = item_name(&*intr, item);
let arg_tys = match ty::get(ctor_ty).sty {
ty::ty_bare_fn(ref f) => f.sig.inputs.clone(),
_ => Vec::new(), // Nullary enum variant.
let (ctor_ty, arg_tys) = match ty::get(ctor_ty).sty {
ty::ty_bare_fn(ref f) =>
(Some(ctor_ty), f.sig.inputs.clone()),
_ => // Nullary or struct enum variant.
(None, get_struct_fields(intr.clone(), cdata, did.node)
.iter()
.map(|field_ty| get_type(cdata, field_ty.id.node, tcx).ty)
.collect())
};
match variant_disr_val(item) {
Some(val) => { disr_val = val; }
Expand Down
17 changes: 4 additions & 13 deletions src/librustc/middle/privacy.rs
Expand Up @@ -667,21 +667,12 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {

let struct_type = ty::lookup_item_type(self.tcx, id).ty;
let struct_desc = match ty::get(struct_type).sty {
ty::ty_struct(_, _) => format!("struct `{}`", ty::item_path_str(self.tcx, id)),
ty::ty_bare_fn(ty::BareFnTy { sig: ty::FnSig { output, .. }, .. }) => {
// Struct `id` is really a struct variant of an enum,
// and we're really looking at the variant's constructor
// function. So get the return type for a detailed error
// message.
let enum_id = match ty::get(output).sty {
ty::ty_enum(id, _) => id,
_ => self.tcx.sess.span_bug(span, "enum variant doesn't \
belong to an enum")
};
ty::ty_struct(_, _) =>
format!("struct `{}`", ty::item_path_str(self.tcx, id)),
ty::ty_enum(enum_id, _) =>
format!("variant `{}` of enum `{}`",
ty::with_path(self.tcx, id, |mut p| p.last().unwrap()),
ty::item_path_str(self.tcx, enum_id))
}
ty::item_path_str(self.tcx, enum_id)),
_ => self.tcx.sess.span_bug(span, "can't find struct for field")
};
let msg = match name {
Expand Down
11 changes: 6 additions & 5 deletions src/librustc/middle/ty.rs
Expand Up @@ -50,7 +50,7 @@ use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE};
use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
use syntax::ast::{Visibility};
use syntax::ast_util::{mod, PostExpansionMethod, is_local, lit_is_str};
use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod};
use syntax::attr::{mod, AttrMetaMethods};
use syntax::codemap::Span;
use syntax::parse::token::{mod, InternedString};
Expand Down Expand Up @@ -4221,7 +4221,7 @@ pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
pub struct VariantInfo {
pub args: Vec<t>,
pub arg_names: Option<Vec<ast::Ident> >,
pub ctor_ty: t,
pub ctor_ty: Option<t>,
pub name: ast::Name,
pub id: ast::DefId,
pub disr_val: Disr,
Expand Down Expand Up @@ -4249,7 +4249,7 @@ impl VariantInfo {
return VariantInfo {
args: arg_tys,
arg_names: None,
ctor_ty: ctor_ty,
ctor_ty: Some(ctor_ty),
name: ast_variant.node.name.name,
id: ast_util::local_def(ast_variant.node.id),
disr_val: discriminant,
Expand All @@ -4262,7 +4262,8 @@ impl VariantInfo {

assert!(fields.len() > 0);

let arg_tys = ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
let arg_tys = struct_def.fields.iter()
.map(|field| node_id_to_type(cx, field.node.id)).collect();
let arg_names = fields.iter().map(|field| {
match field.node.kind {
NamedField(ident, _) => ident,
Expand All @@ -4274,7 +4275,7 @@ impl VariantInfo {
return VariantInfo {
args: arg_tys,
arg_names: Some(arg_names),
ctor_ty: ctor_ty,
ctor_ty: None,
name: ast_variant.node.name.name,
id: ast_util::local_def(ast_variant.node.id),
disr_val: discriminant,
Expand Down

0 comments on commit 4380e96

Please sign in to comment.