about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/check_match.rs13
-rw-r--r--src/librustc/middle/dead.rs25
-rw-r--r--src/librustc/middle/resolve.rs26
-rw-r--r--src/librustc/middle/trans/_match.rs11
-rw-r--r--src/librustc/middle/typeck/check/_match.rs51
-rw-r--r--src/librustc/middle/typeck/check/mod.rs27
-rw-r--r--src/librustc/util/ppaux.rs3
-rw-r--r--src/test/auxiliary/xcrate_struct_aliases.rs17
-rw-r--r--src/test/compile-fail/issue-14541.rs4
-rw-r--r--src/test/run-pass/struct-aliases-xcrate.rs31
-rw-r--r--src/test/run-pass/struct-aliases.rs33
11 files changed, 173 insertions, 68 deletions
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index db5268220fa..4758825bf0e 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -671,8 +671,17 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
                 } else {
                     None
                 },
-                DefStruct(struct_id) => Some(struct_id),
-                _ => None
+                _ => {
+                    // Assume this is a struct.
+                    match ty::ty_to_def_id(node_id_to_type(cx.tcx, pat_id)) {
+                        None => {
+                            cx.tcx.sess.span_bug(pat_span,
+                                                 "struct pattern wasn't of a \
+                                                  type with a def ID?!")
+                        }
+                        Some(def_id) => Some(def_id),
+                    }
+                }
             };
             class_id.map(|variant_id| {
                 let struct_fields = ty::lookup_struct_fields(cx.tcx, variant_id);
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 70db3e964ab..9ec167ee826 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -141,16 +141,25 @@ impl<'a> MarkSymbolVisitor<'a> {
     }
 
     fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[ast::FieldPat]) {
-        match self.tcx.def_map.borrow().get(&lhs.id) {
-            &def::DefStruct(id) | &def::DefVariant(_, id, _) => {
-                let fields = ty::lookup_struct_fields(self.tcx, id);
-                for pat in pats.iter() {
-                    let field_id = fields.iter()
-                        .find(|field| field.name == pat.ident.name).unwrap().id;
-                    self.live_symbols.insert(field_id.node);
+        let id = match self.tcx.def_map.borrow().get(&lhs.id) {
+            &def::DefVariant(_, id, _) => id,
+            _ => {
+                match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,
+                                                           lhs.id)) {
+                    None => {
+                        self.tcx.sess.span_bug(lhs.span,
+                                               "struct pattern wasn't of a \
+                                                type with a def ID?!")
+                    }
+                    Some(def_id) => def_id,
                 }
             }
-            _ => ()
+        };
+        let fields = ty::lookup_struct_fields(self.tcx, id);
+        for pat in pats.iter() {
+            let field_id = fields.iter()
+                .find(|field| field.name == pat.ident.name).unwrap().id;
+            self.live_symbols.insert(field_id.node);
         }
     }
 
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index b7b4618a790..6ec1f23cdbd 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -4470,17 +4470,7 @@ impl<'a> Resolver<'a> {
 
                 PatStruct(ref path, _, _) => {
                     match self.resolve_path(pat_id, path, TypeNS, false) {
-                        Some((DefTy(class_id), lp))
-                                if self.structs.contains_key(&class_id) => {
-                            let class_def = DefStruct(class_id);
-                            self.record_def(pattern.id, (class_def, lp));
-                        }
-                        Some(definition @ (DefStruct(class_id), _)) => {
-                            assert!(self.structs.contains_key(&class_id));
-                            self.record_def(pattern.id, definition);
-                        }
-                        Some(definition @ (DefVariant(_, variant_id, _), _))
-                                if self.structs.contains_key(&variant_id) => {
+                        Some(definition) => {
                             self.record_def(pattern.id, definition);
                         }
                         result => {
@@ -5200,17 +5190,11 @@ impl<'a> Resolver<'a> {
             }
 
             ExprStruct(ref path, _, _) => {
-                // Resolve the path to the structure it goes to.
+                // Resolve the path to the structure it goes to. We don't
+                // check to ensure that the path is actually a structure; that
+                // is checked later during typeck.
                 match self.resolve_path(expr.id, path, TypeNS, false) {
-                    Some((DefTy(class_id), lp)) | Some((DefStruct(class_id), lp))
-                            if self.structs.contains_key(&class_id) => {
-                        let class_def = DefStruct(class_id);
-                        self.record_def(expr.id, (class_def, lp));
-                    }
-                    Some(definition @ (DefVariant(_, class_id, _), _))
-                            if self.structs.contains_key(&class_id) => {
-                        self.record_def(expr.id, definition);
-                    }
+                    Some(definition) => self.record_def(expr.id, definition),
                     result => {
                         debug!("(resolving expression) didn't find struct \
                                 def: {:?}", result);
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 0809079347b..11d09aa49cf 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -803,12 +803,19 @@ fn any_irrefutable_adt_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
         let pat = *br.pats.get(col);
         match pat.node {
             ast::PatTup(_) => true,
-            ast::PatEnum(..) | ast::PatIdent(_, _, None) | ast::PatStruct(..) =>
+            ast::PatStruct(..) => {
+                match bcx.tcx().def_map.borrow().find(&pat.id) {
+                    Some(&def::DefVariant(..)) => false,
+                    _ => true,
+                }
+            }
+            ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
                 match bcx.tcx().def_map.borrow().find(&pat.id) {
                     Some(&def::DefFn(..)) |
                     Some(&def::DefStruct(..)) => true,
                     _ => false
-                },
+                }
+            }
             _ => false
         }
     })
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 697c5d367ee..a5e7db1d6fd 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -362,36 +362,16 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
     }
 }
 
-pub fn check_struct_pat(pcx: &pat_ctxt, pat_id: ast::NodeId, span: Span,
-                        expected: ty::t, path: &ast::Path,
+pub fn check_struct_pat(pcx: &pat_ctxt, _pat_id: ast::NodeId, span: Span,
+                        _expected: ty::t, _path: &ast::Path,
                         fields: &[ast::FieldPat], etc: bool,
                         struct_id: ast::DefId,
                         substitutions: &subst::Substs) {
-    let fcx = pcx.fcx;
+    let _fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
     let class_fields = ty::lookup_struct_fields(tcx, struct_id);
 
-    // Check to ensure that the struct is the one specified.
-    match tcx.def_map.borrow().find(&pat_id) {
-        Some(&def::DefStruct(supplied_def_id))
-                if supplied_def_id == struct_id => {
-            // OK.
-        }
-        Some(&def::DefStruct(..)) | Some(&def::DefVariant(..)) => {
-            let name = pprust::path_to_str(path);
-            tcx.sess
-               .span_err(span,
-                         format!("mismatched types: expected `{}` but found \
-                                  `{}`",
-                                 fcx.infcx().ty_to_str(expected),
-                                 name).as_slice());
-        }
-        _ => {
-            tcx.sess.span_bug(span, "resolve didn't write in struct ID");
-        }
-    }
-
     check_struct_pat_fields(pcx, span, fields, class_fields, struct_id,
                             substitutions, etc);
 }
@@ -535,6 +515,21 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         let mut error_happened = false;
         match *structure {
             ty::ty_struct(cid, ref substs) => {
+                // Verify that the pattern named the right structure.
+                let item_did = tcx.def_map.borrow().get(&pat.id).def_id();
+                let struct_did =
+                    ty::ty_to_def_id(
+                        ty::lookup_item_type(tcx, item_did).ty).unwrap();
+                if struct_did != cid {
+                    tcx.sess
+                       .span_err(path.span,
+                                 format!("`{}` does not name the \
+                                          structure `{}`",
+                                         pprust::path_to_str(path),
+                                         fcx.infcx()
+                                            .ty_to_str(expected)).as_slice())
+                }
+
                 check_struct_pat(pcx, pat.id, pat.span, expected, path,
                                  fields.as_slice(), etc, cid, substs);
             }
@@ -562,7 +557,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
                             "a structure pattern".to_string(),
                             None);
                 match tcx.def_map.borrow().find(&pat.id) {
-                    Some(&def::DefStruct(supplied_def_id)) => {
+                    Some(def) => {
                          check_struct_pat(pcx,
                                           pat.id,
                                           pat.span,
@@ -570,10 +565,14 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
                                           path,
                                           fields.as_slice(),
                                           etc,
-                                          supplied_def_id,
+                                          def.def_id(),
                                           &subst::Substs::empty());
                     }
-                    _ => () // Error, but we're already in an error case
+                    None => {
+                        tcx.sess.span_bug(pat.span,
+                                          "whoops, looks like resolve didn't \
+                                           write a def in here")
+                    }
                 }
                 error_happened = true;
             }
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index e4d9bcfad61..973227c7116 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -3296,17 +3296,34 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         // Resolve the path.
         let def = tcx.def_map.borrow().find(&id).map(|i| *i);
         match def {
-            Some(def::DefStruct(type_def_id)) => {
-                check_struct_constructor(fcx, id, expr.span, type_def_id,
-                                         fields.as_slice(), base_expr);
-            }
             Some(def::DefVariant(enum_id, variant_id, _)) => {
                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
                                           variant_id, fields.as_slice());
             }
+            Some(def) => {
+                // Verify that this was actually a struct.
+                let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
+                match ty::get(typ.ty).sty {
+                    ty::ty_struct(struct_did, _) => {
+                        check_struct_constructor(fcx,
+                                                 id,
+                                                 expr.span,
+                                                 struct_did,
+                                                 fields.as_slice(),
+                                                 base_expr);
+                    }
+                    _ => {
+                        tcx.sess
+                           .span_err(path.span,
+                                     format!("`{}` does not name a structure",
+                                             pprust::path_to_str(
+                                                 path)).as_slice())
+                    }
+                }
+            }
             _ => {
                 tcx.sess.span_bug(path.span,
-                                  "structure constructor does not name a structure type");
+                                  "structure constructor wasn't resolved")
             }
         }
       }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 85edd4ea481..f228ea32ae5 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -16,8 +16,7 @@ use middle::ty::{ReSkolemized, ReVar};
 use middle::ty::{BoundRegion, BrAnon, BrNamed};
 use middle::ty::{BrFresh, ctxt};
 use middle::ty::{mt, t, ParamTy};
-use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
-                 ReEmpty};
+use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
 use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
 use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup};
diff --git a/src/test/auxiliary/xcrate_struct_aliases.rs b/src/test/auxiliary/xcrate_struct_aliases.rs
new file mode 100644
index 00000000000..a0ec7272720
--- /dev/null
+++ b/src/test/auxiliary/xcrate_struct_aliases.rs
@@ -0,0 +1,17 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct S {
+    pub x: int,
+    pub y: int,
+}
+
+pub type S2 = S;
+
diff --git a/src/test/compile-fail/issue-14541.rs b/src/test/compile-fail/issue-14541.rs
index 2dcfeac513c..921e331e960 100644
--- a/src/test/compile-fail/issue-14541.rs
+++ b/src/test/compile-fail/issue-14541.rs
@@ -13,8 +13,8 @@ struct vec3 { y: f32, z: f32 }
 
 fn make(v: vec2) {
     let vec3 { y: _, z: _ } = v;
-    //~^ ERROR mismatched types: expected `vec2` but found `vec3`
+    //~^ ERROR `vec3` does not name the structure `vec2`
     //~^^ ERROR struct `vec2` does not have a field named `z`
 }
 
-fn main() { }
\ No newline at end of file
+fn main() { }
diff --git a/src/test/run-pass/struct-aliases-xcrate.rs b/src/test/run-pass/struct-aliases-xcrate.rs
new file mode 100644
index 00000000000..9046cafe757
--- /dev/null
+++ b/src/test/run-pass/struct-aliases-xcrate.rs
@@ -0,0 +1,31 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:xcrate_struct_aliases.rs
+extern crate xcrate_struct_aliases;
+
+use xcrate_struct_aliases::{S, S2};
+
+fn main() {
+    let s = S2 {
+        x: 1,
+        y: 2,
+    };
+    match s {
+        S2 {
+            x: x,
+            y: y
+        } => {
+            assert_eq!(x, 1);
+            assert_eq!(y, 2);
+        }
+    }
+}
+
diff --git a/src/test/run-pass/struct-aliases.rs b/src/test/run-pass/struct-aliases.rs
new file mode 100644
index 00000000000..2cf961a5c0c
--- /dev/null
+++ b/src/test/run-pass/struct-aliases.rs
@@ -0,0 +1,33 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S {
+    x: int,
+    y: int,
+}
+
+type S2 = S;
+
+fn main() {
+    let s = S2 {
+        x: 1,
+        y: 2,
+    };
+    match s {
+        S2 {
+            x: x,
+            y: y
+        } => {
+            assert_eq!(x, 1);
+            assert_eq!(y, 2);
+        }
+    }
+}
+