Skip to content

Commit c175ed4

Browse files
committed
auto merge of rust-lang#15440 : pcwalton/rust/struct-aliases, r=brson
Closes rust-lang#4508. r? @nick29581
2 parents 49bc17b + aaaf7e0 commit c175ed4

File tree

11 files changed

+173
-68
lines changed

11 files changed

+173
-68
lines changed

src/librustc/middle/check_match.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -671,8 +671,17 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
671671
} else {
672672
None
673673
},
674-
DefStruct(struct_id) => Some(struct_id),
675-
_ => None
674+
_ => {
675+
// Assume this is a struct.
676+
match ty::ty_to_def_id(node_id_to_type(cx.tcx, pat_id)) {
677+
None => {
678+
cx.tcx.sess.span_bug(pat_span,
679+
"struct pattern wasn't of a \
680+
type with a def ID?!")
681+
}
682+
Some(def_id) => Some(def_id),
683+
}
684+
}
676685
};
677686
class_id.map(|variant_id| {
678687
let struct_fields = ty::lookup_struct_fields(cx.tcx, variant_id);

src/librustc/middle/dead.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,25 @@ impl<'a> MarkSymbolVisitor<'a> {
141141
}
142142

143143
fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, pats: &[ast::FieldPat]) {
144-
match self.tcx.def_map.borrow().get(&lhs.id) {
145-
&def::DefStruct(id) | &def::DefVariant(_, id, _) => {
146-
let fields = ty::lookup_struct_fields(self.tcx, id);
147-
for pat in pats.iter() {
148-
let field_id = fields.iter()
149-
.find(|field| field.name == pat.ident.name).unwrap().id;
150-
self.live_symbols.insert(field_id.node);
144+
let id = match self.tcx.def_map.borrow().get(&lhs.id) {
145+
&def::DefVariant(_, id, _) => id,
146+
_ => {
147+
match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,
148+
lhs.id)) {
149+
None => {
150+
self.tcx.sess.span_bug(lhs.span,
151+
"struct pattern wasn't of a \
152+
type with a def ID?!")
153+
}
154+
Some(def_id) => def_id,
151155
}
152156
}
153-
_ => ()
157+
};
158+
let fields = ty::lookup_struct_fields(self.tcx, id);
159+
for pat in pats.iter() {
160+
let field_id = fields.iter()
161+
.find(|field| field.name == pat.ident.name).unwrap().id;
162+
self.live_symbols.insert(field_id.node);
154163
}
155164
}
156165

src/librustc/middle/resolve.rs

+5-21
Original file line numberDiff line numberDiff line change
@@ -4470,17 +4470,7 @@ impl<'a> Resolver<'a> {
44704470

44714471
PatStruct(ref path, _, _) => {
44724472
match self.resolve_path(pat_id, path, TypeNS, false) {
4473-
Some((DefTy(class_id), lp))
4474-
if self.structs.contains_key(&class_id) => {
4475-
let class_def = DefStruct(class_id);
4476-
self.record_def(pattern.id, (class_def, lp));
4477-
}
4478-
Some(definition @ (DefStruct(class_id), _)) => {
4479-
assert!(self.structs.contains_key(&class_id));
4480-
self.record_def(pattern.id, definition);
4481-
}
4482-
Some(definition @ (DefVariant(_, variant_id, _), _))
4483-
if self.structs.contains_key(&variant_id) => {
4473+
Some(definition) => {
44844474
self.record_def(pattern.id, definition);
44854475
}
44864476
result => {
@@ -5200,17 +5190,11 @@ impl<'a> Resolver<'a> {
52005190
}
52015191

52025192
ExprStruct(ref path, _, _) => {
5203-
// Resolve the path to the structure it goes to.
5193+
// Resolve the path to the structure it goes to. We don't
5194+
// check to ensure that the path is actually a structure; that
5195+
// is checked later during typeck.
52045196
match self.resolve_path(expr.id, path, TypeNS, false) {
5205-
Some((DefTy(class_id), lp)) | Some((DefStruct(class_id), lp))
5206-
if self.structs.contains_key(&class_id) => {
5207-
let class_def = DefStruct(class_id);
5208-
self.record_def(expr.id, (class_def, lp));
5209-
}
5210-
Some(definition @ (DefVariant(_, class_id, _), _))
5211-
if self.structs.contains_key(&class_id) => {
5212-
self.record_def(expr.id, definition);
5213-
}
5197+
Some(definition) => self.record_def(expr.id, definition),
52145198
result => {
52155199
debug!("(resolving expression) didn't find struct \
52165200
def: {:?}", result);

src/librustc/middle/trans/_match.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -803,12 +803,19 @@ fn any_irrefutable_adt_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
803803
let pat = *br.pats.get(col);
804804
match pat.node {
805805
ast::PatTup(_) => true,
806-
ast::PatEnum(..) | ast::PatIdent(_, _, None) | ast::PatStruct(..) =>
806+
ast::PatStruct(..) => {
807+
match bcx.tcx().def_map.borrow().find(&pat.id) {
808+
Some(&def::DefVariant(..)) => false,
809+
_ => true,
810+
}
811+
}
812+
ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
807813
match bcx.tcx().def_map.borrow().find(&pat.id) {
808814
Some(&def::DefFn(..)) |
809815
Some(&def::DefStruct(..)) => true,
810816
_ => false
811-
},
817+
}
818+
}
812819
_ => false
813820
}
814821
})

src/librustc/middle/typeck/check/_match.rs

+25-26
Original file line numberDiff line numberDiff line change
@@ -362,36 +362,16 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt,
362362
}
363363
}
364364

365-
pub fn check_struct_pat(pcx: &pat_ctxt, pat_id: ast::NodeId, span: Span,
366-
expected: ty::t, path: &ast::Path,
365+
pub fn check_struct_pat(pcx: &pat_ctxt, _pat_id: ast::NodeId, span: Span,
366+
_expected: ty::t, _path: &ast::Path,
367367
fields: &[ast::FieldPat], etc: bool,
368368
struct_id: ast::DefId,
369369
substitutions: &subst::Substs) {
370-
let fcx = pcx.fcx;
370+
let _fcx = pcx.fcx;
371371
let tcx = pcx.fcx.ccx.tcx;
372372

373373
let class_fields = ty::lookup_struct_fields(tcx, struct_id);
374374

375-
// Check to ensure that the struct is the one specified.
376-
match tcx.def_map.borrow().find(&pat_id) {
377-
Some(&def::DefStruct(supplied_def_id))
378-
if supplied_def_id == struct_id => {
379-
// OK.
380-
}
381-
Some(&def::DefStruct(..)) | Some(&def::DefVariant(..)) => {
382-
let name = pprust::path_to_str(path);
383-
tcx.sess
384-
.span_err(span,
385-
format!("mismatched types: expected `{}` but found \
386-
`{}`",
387-
fcx.infcx().ty_to_str(expected),
388-
name).as_slice());
389-
}
390-
_ => {
391-
tcx.sess.span_bug(span, "resolve didn't write in struct ID");
392-
}
393-
}
394-
395375
check_struct_pat_fields(pcx, span, fields, class_fields, struct_id,
396376
substitutions, etc);
397377
}
@@ -535,6 +515,21 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
535515
let mut error_happened = false;
536516
match *structure {
537517
ty::ty_struct(cid, ref substs) => {
518+
// Verify that the pattern named the right structure.
519+
let item_did = tcx.def_map.borrow().get(&pat.id).def_id();
520+
let struct_did =
521+
ty::ty_to_def_id(
522+
ty::lookup_item_type(tcx, item_did).ty).unwrap();
523+
if struct_did != cid {
524+
tcx.sess
525+
.span_err(path.span,
526+
format!("`{}` does not name the \
527+
structure `{}`",
528+
pprust::path_to_str(path),
529+
fcx.infcx()
530+
.ty_to_str(expected)).as_slice())
531+
}
532+
538533
check_struct_pat(pcx, pat.id, pat.span, expected, path,
539534
fields.as_slice(), etc, cid, substs);
540535
}
@@ -562,18 +557,22 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
562557
"a structure pattern".to_string(),
563558
None);
564559
match tcx.def_map.borrow().find(&pat.id) {
565-
Some(&def::DefStruct(supplied_def_id)) => {
560+
Some(def) => {
566561
check_struct_pat(pcx,
567562
pat.id,
568563
pat.span,
569564
ty::mk_err(),
570565
path,
571566
fields.as_slice(),
572567
etc,
573-
supplied_def_id,
568+
def.def_id(),
574569
&subst::Substs::empty());
575570
}
576-
_ => () // Error, but we're already in an error case
571+
None => {
572+
tcx.sess.span_bug(pat.span,
573+
"whoops, looks like resolve didn't \
574+
write a def in here")
575+
}
577576
}
578577
error_happened = true;
579578
}

src/librustc/middle/typeck/check/mod.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -3296,17 +3296,34 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
32963296
// Resolve the path.
32973297
let def = tcx.def_map.borrow().find(&id).map(|i| *i);
32983298
match def {
3299-
Some(def::DefStruct(type_def_id)) => {
3300-
check_struct_constructor(fcx, id, expr.span, type_def_id,
3301-
fields.as_slice(), base_expr);
3302-
}
33033299
Some(def::DefVariant(enum_id, variant_id, _)) => {
33043300
check_struct_enum_variant(fcx, id, expr.span, enum_id,
33053301
variant_id, fields.as_slice());
33063302
}
3303+
Some(def) => {
3304+
// Verify that this was actually a struct.
3305+
let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
3306+
match ty::get(typ.ty).sty {
3307+
ty::ty_struct(struct_did, _) => {
3308+
check_struct_constructor(fcx,
3309+
id,
3310+
expr.span,
3311+
struct_did,
3312+
fields.as_slice(),
3313+
base_expr);
3314+
}
3315+
_ => {
3316+
tcx.sess
3317+
.span_err(path.span,
3318+
format!("`{}` does not name a structure",
3319+
pprust::path_to_str(
3320+
path)).as_slice())
3321+
}
3322+
}
3323+
}
33073324
_ => {
33083325
tcx.sess.span_bug(path.span,
3309-
"structure constructor does not name a structure type");
3326+
"structure constructor wasn't resolved")
33103327
}
33113328
}
33123329
}

src/librustc/util/ppaux.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ use middle::ty::{ReSkolemized, ReVar};
1616
use middle::ty::{BoundRegion, BrAnon, BrNamed};
1717
use middle::ty::{BrFresh, ctxt};
1818
use middle::ty::{mt, t, ParamTy};
19-
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region,
20-
ReEmpty};
19+
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
2120
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
2221
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
2322
use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub struct S {
12+
pub x: int,
13+
pub y: int,
14+
}
15+
16+
pub type S2 = S;
17+

src/test/compile-fail/issue-14541.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ struct vec3 { y: f32, z: f32 }
1313

1414
fn make(v: vec2) {
1515
let vec3 { y: _, z: _ } = v;
16-
//~^ ERROR mismatched types: expected `vec2` but found `vec3`
16+
//~^ ERROR `vec3` does not name the structure `vec2`
1717
//~^^ ERROR struct `vec2` does not have a field named `z`
1818
}
1919

20-
fn main() { }
20+
fn main() { }
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:xcrate_struct_aliases.rs
12+
extern crate xcrate_struct_aliases;
13+
14+
use xcrate_struct_aliases::{S, S2};
15+
16+
fn main() {
17+
let s = S2 {
18+
x: 1,
19+
y: 2,
20+
};
21+
match s {
22+
S2 {
23+
x: x,
24+
y: y
25+
} => {
26+
assert_eq!(x, 1);
27+
assert_eq!(y, 2);
28+
}
29+
}
30+
}
31+

src/test/run-pass/struct-aliases.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct S {
12+
x: int,
13+
y: int,
14+
}
15+
16+
type S2 = S;
17+
18+
fn main() {
19+
let s = S2 {
20+
x: 1,
21+
y: 2,
22+
};
23+
match s {
24+
S2 {
25+
x: x,
26+
y: y
27+
} => {
28+
assert_eq!(x, 1);
29+
assert_eq!(y, 2);
30+
}
31+
}
32+
}
33+

0 commit comments

Comments
 (0)