auto merge of #18171 : jakub-/rust/match-typeck, r=pcwalton
Rather than doing it top-down, with a known expected type, we will now simply establish the appropriate constraints between the pattern and the expression it destructures. Closes #8783. Closes #10200.
This commit is contained in:
commit
a34b8dec69
25 changed files with 488 additions and 745 deletions
|
@ -44,11 +44,9 @@ register_diagnostics!(
|
||||||
E0025,
|
E0025,
|
||||||
E0026,
|
E0026,
|
||||||
E0027,
|
E0027,
|
||||||
E0028,
|
|
||||||
E0029,
|
E0029,
|
||||||
E0030,
|
E0030,
|
||||||
E0031,
|
E0031,
|
||||||
E0032,
|
|
||||||
E0033,
|
E0033,
|
||||||
E0034,
|
E0034,
|
||||||
E0035,
|
E0035,
|
||||||
|
|
|
@ -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},
|
let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
|
||||||
item, tcx, cdata);
|
item, tcx, cdata);
|
||||||
let name = item_name(&*intr, item);
|
let name = item_name(&*intr, item);
|
||||||
let arg_tys = match ty::get(ctor_ty).sty {
|
let (ctor_ty, arg_tys) = match ty::get(ctor_ty).sty {
|
||||||
ty::ty_bare_fn(ref f) => f.sig.inputs.clone(),
|
ty::ty_bare_fn(ref f) =>
|
||||||
_ => Vec::new(), // Nullary enum variant.
|
(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) {
|
match variant_disr_val(item) {
|
||||||
Some(val) => { disr_val = val; }
|
Some(val) => { disr_val = val; }
|
||||||
|
|
|
@ -667,21 +667,12 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
let struct_type = ty::lookup_item_type(self.tcx, id).ty;
|
let struct_type = ty::lookup_item_type(self.tcx, id).ty;
|
||||||
let struct_desc = match ty::get(struct_type).sty {
|
let struct_desc = match ty::get(struct_type).sty {
|
||||||
ty::ty_struct(_, _) => format!("struct `{}`", ty::item_path_str(self.tcx, id)),
|
ty::ty_struct(_, _) =>
|
||||||
ty::ty_bare_fn(ty::BareFnTy { sig: ty::FnSig { output, .. }, .. }) => {
|
format!("struct `{}`", ty::item_path_str(self.tcx, id)),
|
||||||
// Struct `id` is really a struct variant of an enum,
|
ty::ty_enum(enum_id, _) =>
|
||||||
// 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")
|
|
||||||
};
|
|
||||||
format!("variant `{}` of enum `{}`",
|
format!("variant `{}` of enum `{}`",
|
||||||
ty::with_path(self.tcx, id, |mut p| p.last().unwrap()),
|
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")
|
_ => self.tcx.sess.span_bug(span, "can't find struct for field")
|
||||||
};
|
};
|
||||||
let msg = match name {
|
let msg = match name {
|
||||||
|
|
|
@ -5077,7 +5077,6 @@ impl<'a> Resolver<'a> {
|
||||||
PatEnum(ref path, _) => {
|
PatEnum(ref path, _) => {
|
||||||
// This must be an enum variant, struct or const.
|
// This must be an enum variant, struct or const.
|
||||||
match self.resolve_path(pat_id, path, ValueNS, false) {
|
match self.resolve_path(pat_id, path, ValueNS, false) {
|
||||||
Some(def @ (DefFn(..), _)) |
|
|
||||||
Some(def @ (DefVariant(..), _)) |
|
Some(def @ (DefVariant(..), _)) |
|
||||||
Some(def @ (DefStruct(..), _)) |
|
Some(def @ (DefStruct(..), _)) |
|
||||||
Some(def @ (DefConst(..), _)) => {
|
Some(def @ (DefConst(..), _)) => {
|
||||||
|
|
|
@ -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::{MutImmutable, MutMutable, Name, NamedField, NodeId};
|
||||||
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
|
use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
|
||||||
use syntax::ast::{Visibility};
|
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::attr::{mod, AttrMetaMethods};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::parse::token::{mod, InternedString};
|
use syntax::parse::token::{mod, InternedString};
|
||||||
|
@ -4221,7 +4221,7 @@ pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
|
||||||
pub struct VariantInfo {
|
pub struct VariantInfo {
|
||||||
pub args: Vec<t>,
|
pub args: Vec<t>,
|
||||||
pub arg_names: Option<Vec<ast::Ident> >,
|
pub arg_names: Option<Vec<ast::Ident> >,
|
||||||
pub ctor_ty: t,
|
pub ctor_ty: Option<t>,
|
||||||
pub name: ast::Name,
|
pub name: ast::Name,
|
||||||
pub id: ast::DefId,
|
pub id: ast::DefId,
|
||||||
pub disr_val: Disr,
|
pub disr_val: Disr,
|
||||||
|
@ -4249,7 +4249,7 @@ impl VariantInfo {
|
||||||
return VariantInfo {
|
return VariantInfo {
|
||||||
args: arg_tys,
|
args: arg_tys,
|
||||||
arg_names: None,
|
arg_names: None,
|
||||||
ctor_ty: ctor_ty,
|
ctor_ty: Some(ctor_ty),
|
||||||
name: ast_variant.node.name.name,
|
name: ast_variant.node.name.name,
|
||||||
id: ast_util::local_def(ast_variant.node.id),
|
id: ast_util::local_def(ast_variant.node.id),
|
||||||
disr_val: discriminant,
|
disr_val: discriminant,
|
||||||
|
@ -4262,7 +4262,8 @@ impl VariantInfo {
|
||||||
|
|
||||||
assert!(fields.len() > 0);
|
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| {
|
let arg_names = fields.iter().map(|field| {
|
||||||
match field.node.kind {
|
match field.node.kind {
|
||||||
NamedField(ident, _) => ident,
|
NamedField(ident, _) => ident,
|
||||||
|
@ -4274,7 +4275,7 @@ impl VariantInfo {
|
||||||
return VariantInfo {
|
return VariantInfo {
|
||||||
args: arg_tys,
|
args: arg_tys,
|
||||||
arg_names: Some(arg_names),
|
arg_names: Some(arg_names),
|
||||||
ctor_ty: ctor_ty,
|
ctor_ty: None,
|
||||||
name: ast_variant.node.name.name,
|
name: ast_variant.node.name.name,
|
||||||
id: ast_util::local_def(ast_variant.node.id),
|
id: ast_util::local_def(ast_variant.node.id),
|
||||||
disr_val: discriminant,
|
disr_val: discriminant,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -117,7 +117,7 @@ use util::ppaux;
|
||||||
use util::ppaux::{UserString, Repr};
|
use util::ppaux::{UserString, Repr};
|
||||||
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
|
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, Ref, RefCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hashmap::{Occupied, Vacant};
|
use std::collections::hashmap::{Occupied, Vacant};
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
@ -1815,6 +1815,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn item_substs<'a>(&'a self) -> Ref<'a, NodeMap<ty::ItemSubsts>> {
|
||||||
|
self.inh.item_substs.borrow()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn opt_node_ty_substs(&self,
|
pub fn opt_node_ty_substs(&self,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
f: |&ty::ItemSubsts|) {
|
f: |&ty::ItemSubsts|) {
|
||||||
|
|
|
@ -236,10 +236,7 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
|
||||||
};
|
};
|
||||||
|
|
||||||
convert_struct(ccx, &**struct_def, pty, variant.node.id);
|
convert_struct(ccx, &**struct_def, pty, variant.node.id);
|
||||||
|
enum_ty
|
||||||
let input_tys: Vec<_> = struct_def.fields.iter().map(
|
|
||||||
|f| ty::node_id_to_type(ccx.tcx, f.node.id)).collect();
|
|
||||||
ty::mk_ctor_fn(tcx, scope, input_tys.as_slice(), enum_ty)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,12 +30,12 @@ fn main() {
|
||||||
let &&x = &&(&1i as &T);
|
let &&x = &&(&1i as &T);
|
||||||
|
|
||||||
// n == m
|
// n == m
|
||||||
let &x = &1i as &T; //~ ERROR cannot be dereferenced
|
let &x = &1i as &T; //~ ERROR type `&T` cannot be dereferenced
|
||||||
let &&x = &(&1i as &T); //~ ERROR cannot be dereferenced
|
let &&x = &(&1i as &T); //~ ERROR type `&T` cannot be dereferenced
|
||||||
let box x = box 1i as Box<T>; //~ ERROR cannot be dereferenced
|
let box x = box 1i as Box<T>; //~ ERROR type `Box<T>` cannot be dereferenced
|
||||||
|
|
||||||
// n > m
|
// n > m
|
||||||
let &&x = &1i as &T; //~ ERROR found an `&`-pointer pattern
|
let &&x = &1i as &T; //~ ERROR found &-ptr
|
||||||
let &&&x = &(&1i as &T); //~ ERROR found an `&`-pointer pattern
|
let &&&x = &(&1i as &T); //~ ERROR found &-ptr
|
||||||
let box box x = box 1i as Box<T>; //~ ERROR found a box pattern
|
let box box x = box 1i as Box<T>; //~ ERROR found box
|
||||||
}
|
}
|
||||||
|
|
19
src/test/compile-fail/issue-10200.rs
Normal file
19
src/test/compile-fail/issue-10200.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2014 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 Foo(bool);
|
||||||
|
fn foo(_: uint) -> Foo { Foo(false) }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
match Foo(true) {
|
||||||
|
foo(x) //~ ERROR `foo` is not an enum variant, struct or const
|
||||||
|
=> ()
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,8 @@ fn main() {
|
||||||
let x = [1,2];
|
let x = [1,2];
|
||||||
let y = match x {
|
let y = match x {
|
||||||
[] => None,
|
[] => None,
|
||||||
//~^ ERROR expected `[<generic integer #0>, ..2]`, found a fixed array pattern of size 0
|
//~^ ERROR mismatched types: expected `[<generic integer #0>, ..2]`, found `[<generic #7>, ..0]`
|
||||||
|
// (expected array, found array)
|
||||||
[a,_] => Some(a)
|
[a,_] => Some(a)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@ mod b {
|
||||||
let enum_struct_variant = ::a::get_enum_struct_variant();
|
let enum_struct_variant = ::a::get_enum_struct_variant();
|
||||||
match enum_struct_variant {
|
match enum_struct_variant {
|
||||||
a::EnumStructVariant { x, y, z } => {
|
a::EnumStructVariant { x, y, z } => {
|
||||||
//~^ ERROR error: mismatched types: expected `()`, found a structure pattern
|
//~^ ERROR mismatched types: expected `()`, found `a::Enum`
|
||||||
|
// (expected (), found enum a::Enum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ struct vec3 { y: f32, z: f32 }
|
||||||
|
|
||||||
fn make(v: vec2) {
|
fn make(v: vec2) {
|
||||||
let vec3 { y: _, z: _ } = v;
|
let vec3 { y: _, z: _ } = v;
|
||||||
//~^ ERROR `vec3` does not name the structure `vec2`
|
//~^ ERROR mismatched types: expected `vec2`, found `vec3`
|
||||||
//~^^ ERROR struct `vec2` does not have a field named `z`
|
// (expected struct vec2, found struct vec3)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
|
|
@ -9,11 +9,23 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
a: uint,
|
a: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main(){
|
fn main() {
|
||||||
let Foo {a: _, a: _} = Foo {a: 29};
|
let Foo {
|
||||||
//~^ ERROR field `a` bound twice in pattern
|
a: _, //~ NOTE field `a` previously bound here
|
||||||
}
|
a: _ //~ ERROR field `a` bound multiple times in the pattern
|
||||||
|
} = Foo { a: 29 };
|
||||||
|
|
||||||
|
let Foo {
|
||||||
|
a, //~ NOTE field `a` previously bound here
|
||||||
|
a: _ //~ ERROR field `a` bound multiple times in the pattern
|
||||||
|
} = Foo { a: 29 };
|
||||||
|
|
||||||
|
let Foo {
|
||||||
|
a, //~ NOTE field `a` previously bound here
|
||||||
|
a: _, //~ ERROR field `a` bound multiple times in the pattern
|
||||||
|
a: x //~ ERROR field `a` bound multiple times in the pattern
|
||||||
|
} = Foo { a: 29 };
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,9 @@ fn main() {
|
||||||
let e = B(REB(()), Tau { t: 3 });
|
let e = B(REB(()), Tau { t: 3 });
|
||||||
let u = match e {
|
let u = match e {
|
||||||
B(
|
B(
|
||||||
Tau{t: x}, //~ ERROR `Tau` does not name a variant
|
Tau{t: x},
|
||||||
|
//~^ ERROR mismatched types: expected `main::R`, found `main::Tau`
|
||||||
|
// (expected enum main::R, found struct main::Tau)
|
||||||
_) => x,
|
_) => x,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ use std::raw::Slice;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let Slice { data: data, len: len } = "foo";
|
let Slice { data: data, len: len } = "foo";
|
||||||
//~^ ERROR mismatched types: expected `&str`, found a structure pattern
|
//~^ ERROR mismatched types: expected `&str`, found `core::raw::Slice<<generic #3>>`
|
||||||
|
// (expected &-ptr, found struct core::raw::Slice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ use std::raw::Slice;
|
||||||
fn main() {
|
fn main() {
|
||||||
match () {
|
match () {
|
||||||
Slice { data: data, len: len } => (),
|
Slice { data: data, len: len } => (),
|
||||||
//~^ ERROR mismatched types: expected `()`, found a structure pattern
|
//~^ ERROR mismatched types: expected `()`, found `core::raw::Slice<<generic #3>>`
|
||||||
|
// (expected (), found struct core::raw::Slice)
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,6 @@ enum Foo {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match Bar(1i) {
|
match Bar(1i) {
|
||||||
Foo { i } => () //~ ERROR `Foo` does not name a variant
|
Foo { i } => () //~ ERROR `Foo` does not name a struct or a struct variant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ enum MyOption<T> {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match MySome(42i) {
|
match MySome(42i) {
|
||||||
MySome { x: 42i } => (), //~ ERROR `MySome` does not name a struct variant
|
MySome { x: 42i } => (), //~ ERROR `MySome` does not name a struct or a struct variant
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,24 +12,29 @@ enum A { B, C }
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match (true, false) {
|
match (true, false) {
|
||||||
B => (), //~ ERROR expected `(bool,bool)`, found an enum or structure pattern
|
B => (),
|
||||||
|
//~^ ERROR mismatched types: expected `(bool,bool)`, found `A`
|
||||||
|
// (expected tuple, found enum A)
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
match (true, false) {
|
match (true, false) {
|
||||||
(true, false, false) => ()
|
(true, false, false) => ()
|
||||||
//~^ ERROR mismatched types: expected `(bool,bool)`, found tuple
|
//~^ ERROR mismatched types: expected `(bool,bool)`,
|
||||||
|
// found `(<generic #7>,<generic #8>,<generic #9>)`
|
||||||
// (expected a tuple with 2 elements, found one with 3 elements)
|
// (expected a tuple with 2 elements, found one with 3 elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
match (true, false) {
|
match (true, false) {
|
||||||
box (true, false) => ()
|
box (true, false) => ()
|
||||||
//~^ ERROR mismatched types: expected `(bool,bool)`, found a box pattern
|
//~^ ERROR mismatched types: expected `(bool,bool)`, found `Box<<generic #11>>`
|
||||||
|
// (expected tuple, found box)
|
||||||
}
|
}
|
||||||
|
|
||||||
match (true, false) {
|
match (true, false) {
|
||||||
&(true, false) => ()
|
&(true, false) => ()
|
||||||
//~^ ERROR mismatched types: expected `(bool,bool)`, found an `&`-pointer pattern
|
//~^ ERROR mismatched types: expected `(bool,bool)`, found `&<generic #15>`
|
||||||
|
// (expected tuple, found &-ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,9 @@ enum Whatever {
|
||||||
|
|
||||||
fn foo(x: Whatever) {
|
fn foo(x: Whatever) {
|
||||||
match x {
|
match x {
|
||||||
Some(field) => field.access(),
|
Some(field) =>
|
||||||
//~^ ERROR: mismatched types: expected `Whatever`, found
|
//~^ ERROR: mismatched types: expected `Whatever`, found `core::option::Option<<generic #3>>`
|
||||||
|
field.access(), //~ ERROR the type of this value must be known in this context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match () {
|
match () {
|
||||||
[()] => { } //~ ERROR mismatched types: expected `()`, found an array pattern
|
[()] => { }
|
||||||
|
//~^ ERROR mismatched types: expected `()`, found `&[<generic #1>]` (expected (), found &-ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@ fn main() {
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
match 'c' {
|
match 'c' {
|
||||||
S { .. } => (), //~ ERROR mismatched types: expected `char`, found a structure pattern
|
S { .. } => (),
|
||||||
|
//~^ ERROR mismatched types: expected `char`, found `S` (expected char, found struct S)
|
||||||
|
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let (x, y) = (); //~ ERROR expected `()`, found tuple (types differ)
|
let (x, y) = ();
|
||||||
|
//~^ ERROR types: expected `()`, found `(<generic #3>,<generic #4>)` (expected (), found tuple)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
30
src/test/run-pass/issue-8783.rs
Normal file
30
src/test/run-pass/issue-8783.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
use std::default::Default;
|
||||||
|
|
||||||
|
struct X { pub x: uint }
|
||||||
|
impl Default for X {
|
||||||
|
fn default() -> X {
|
||||||
|
X { x: 42u }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Y<T> { pub y: T }
|
||||||
|
impl<T: Default> Default for Y<T> {
|
||||||
|
fn default() -> Y<T> {
|
||||||
|
Y { y: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let X { x: _ } = Default::default();
|
||||||
|
let Y { y: X { x } } = Default::default();
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue