mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-18 18:04:13 +00:00
librustc: Accept type aliases for structures in structure literals and
structure patterns. Closes #4508.
This commit is contained in:
parent
9897160523
commit
aaaf7e00ec
@ -677,8 +677,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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -804,12 +804,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
|
||||
}
|
||||
})
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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};
|
||||
|
17
src/test/auxiliary/xcrate_struct_aliases.rs
Normal file
17
src/test/auxiliary/xcrate_struct_aliases.rs
Normal file
@ -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;
|
||||
|
@ -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() { }
|
||||
fn main() { }
|
||||
|
31
src/test/run-pass/struct-aliases-xcrate.rs
Normal file
31
src/test/run-pass/struct-aliases-xcrate.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
src/test/run-pass/struct-aliases.rs
Normal file
33
src/test/run-pass/struct-aliases.rs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user