Resolve partially resolved paths in struct patterns/expressions

Treat Def::Err correctly in struct patterns
Make instantiate_path and instantiate_type a bit closer to each other
This commit is contained in:
Vadim Petrochenkov 2016-06-11 18:47:47 +03:00
parent 49ea3d48a2
commit a397b60ebb
15 changed files with 156 additions and 206 deletions

View File

@ -67,21 +67,6 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
} }
} }
pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::Struct(..) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Variant(..)) | Some(Def::Struct(..)) |
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) => true,
_ => false
}
}
_ => false
}
}
pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool { pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node { match pat.node {
PatKind::Path(..) | PatKind::QPath(..) => { PatKind::Path(..) | PatKind::QPath(..) => {

View File

@ -489,39 +489,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn check_pat_struct(&self, pat: &'gcx hir::Pat, fn check_pat_struct(&self,
path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>], pat: &'gcx hir::Pat,
etc: bool, expected: Ty<'tcx>) { path: &hir::Path,
let tcx = self.tcx; fields: &'gcx [Spanned<hir::FieldPat>],
etc: bool,
let def = tcx.expect_def(pat.id); expected: Ty<'tcx>)
let variant = match self.def_struct_variant(def, path.span) { {
Some((_, variant)) => variant, // Resolve the path and check the definition for errors.
None => { let def = self.finish_resolving_struct_path(path, pat.id, pat.span);
let name = pprust::path_to_string(path); let variant = if let Some(variant) = self.check_struct_path(def, path, pat.span) {
span_err!(tcx.sess, pat.span, E0163, variant
"`{}` does not name a struct or a struct variant", name); } else {
self.write_error(pat.id); self.write_error(pat.id);
for field in fields {
for field in fields { self.check_pat(&field.node.pat, self.tcx.types.err);
self.check_pat(&field.node.pat, tcx.types.err);
}
return;
} }
return;
}; };
let pat_ty = self.instantiate_type(def.def_id(), path); // Type check the path.
let item_substs = match pat_ty.sty { let pat_ty = self.instantiate_type_path(def.def_id(), path, pat.id);
self.demand_eqtype(pat.span, expected, pat_ty);
// Type check subpatterns.
let substs = match pat_ty.sty {
ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs, ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
_ => span_bug!(pat.span, "struct variant is not an ADT") _ => span_bug!(pat.span, "struct variant is not an ADT")
}; };
self.demand_eqtype(pat.span, expected, pat_ty); self.check_struct_pat_fields(pat.span, fields, variant, substs, etc);
self.check_struct_pat_fields(pat.span, fields, variant, &item_substs, etc);
self.write_ty(pat.id, pat_ty);
self.write_substs(pat.id, ty::ItemSubsts {
substs: item_substs
});
} }
fn check_pat_path(&self, fn check_pat_path(&self,
@ -539,8 +535,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}; };
// Resolve the path and check the definition for errors. // Resolve the path and check the definition for errors.
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id), let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
opt_self_ty, path, pat.span, pat.id); pat.id, pat.span);
match def { match def {
Def::Err => { Def::Err => {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
@ -565,8 +561,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Type check the path. // Type check the path.
let scheme = tcx.lookup_item_type(def.def_id()); let scheme = tcx.lookup_item_type(def.def_id());
let predicates = tcx.lookup_predicates(def.def_id()); let predicates = tcx.lookup_predicates(def.def_id());
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id); let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
let pat_ty = self.node_ty(pat.id); opt_ty, def, pat.span, pat.id);
self.demand_suptype(pat.span, expected, pat_ty); self.demand_suptype(pat.span, expected, pat_ty);
} }
@ -597,9 +593,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}; };
// Resolve the path and check the definition for errors. // Resolve the path and check the definition for errors.
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(pat.id), let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(None, path, pat.id, pat.span);
None, path, pat.span, pat.id); let variant = match def {
match def {
Def::Err => { Def::Err => {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
on_error(); on_error();
@ -609,10 +604,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
report_unexpected_def(false); report_unexpected_def(false);
return; return;
} }
Def::Variant(..) | Def::Struct(..) => {} // OK Def::Variant(..) | Def::Struct(..) => {
tcx.expect_variant_def(def)
}
_ => bug!("unexpected pattern definition {:?}", def) _ => bug!("unexpected pattern definition {:?}", def)
} };
let variant = tcx.expect_variant_def(def);
if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() { if variant.kind == VariantKind::Unit && subpats.is_empty() && ddpos.is_some() {
// Matching unit structs with tuple variant patterns (`UnitVariant(..)`) // Matching unit structs with tuple variant patterns (`UnitVariant(..)`)
// is allowed for backward compatibility. // is allowed for backward compatibility.
@ -633,20 +629,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
scheme scheme
}; };
let predicates = tcx.lookup_predicates(def.def_id()); let predicates = tcx.lookup_predicates(def.def_id());
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, pat.span, pat.id); let pat_ty = self.instantiate_value_path(segments, scheme, &predicates,
let pat_ty = self.node_ty(pat.id); opt_ty, def, pat.span, pat.id);
self.demand_eqtype(pat.span, expected, pat_ty); self.demand_eqtype(pat.span, expected, pat_ty);
// Type check subpatterns. // Type check subpatterns.
if subpats.len() == variant.fields.len() || if subpats.len() == variant.fields.len() ||
subpats.len() < variant.fields.len() && ddpos.is_some() { subpats.len() < variant.fields.len() && ddpos.is_some() {
let expected_substs = match pat_ty.sty { let substs = match pat_ty.sty {
ty::TyEnum(_, expected_substs) => expected_substs, ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
ty::TyStruct(_, expected_substs) => expected_substs,
ref ty => bug!("unexpected pattern type {:?}", ty), ref ty => bug!("unexpected pattern type {:?}", ty),
}; };
for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) {
let field_ty = self.field_ty(subpat.span, &variant.fields[i], expected_substs); let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs);
self.check_pat(&subpat, field_ty); self.check_pat(&subpat, field_ty);
} }
} else { } else {

View File

@ -1621,62 +1621,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
/// ///
/// Note that this function is only intended to be used with type-paths, /// Note that this function is only intended to be used with type-paths,
/// not with value-paths. /// not with value-paths.
pub fn instantiate_type(&self, pub fn instantiate_type_path(&self,
did: DefId, did: DefId,
path: &hir::Path) path: &hir::Path,
-> Ty<'tcx> node_id: ast::NodeId)
{ -> Ty<'tcx> {
debug!("instantiate_type(did={:?}, path={:?})", did, path); debug!("instantiate_type_path(did={:?}, path={:?})", did, path);
let type_scheme = let type_scheme = self.tcx.lookup_item_type(did);
self.tcx.lookup_item_type(did); let type_predicates = self.tcx.lookup_predicates(did);
let type_predicates =
self.tcx.lookup_predicates(did);
let substs = AstConv::ast_path_substs_for_ty(self, self, let substs = AstConv::ast_path_substs_for_ty(self, self,
path.span, path.span,
PathParamMode::Optional, PathParamMode::Optional,
&type_scheme.generics, &type_scheme.generics,
path.segments.last().unwrap()); path.segments.last().unwrap());
debug!("instantiate_type: ty={:?} substs={:?}", &type_scheme.ty, &substs); let substs = self.tcx.mk_substs(substs);
let bounds = debug!("instantiate_type_path: ty={:?} substs={:?}", &type_scheme.ty, substs);
self.instantiate_bounds(path.span, &substs, &type_predicates); let bounds = self.instantiate_bounds(path.span, substs, &type_predicates);
self.add_obligations_for_parameters( let cause = traits::ObligationCause::new(path.span, self.body_id,
traits::ObligationCause::new( traits::ItemObligation(did));
path.span, self.add_obligations_for_parameters(cause, &bounds);
self.body_id,
traits::ItemObligation(did)),
&bounds);
self.instantiate_type_scheme(path.span, &substs, &type_scheme.ty) let ty_substituted = self.instantiate_type_scheme(path.span, substs, &type_scheme.ty);
} self.write_ty(node_id, ty_substituted);
self.write_substs(node_id, ty::ItemSubsts {
/// Return the dict-like variant corresponding to a given `Def`. substs: substs
pub fn def_struct_variant(&self, });
def: Def, ty_substituted
_span: Span)
-> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
{
let (adt, variant) = match def {
Def::Variant(enum_id, variant_id) => {
let adt = self.tcx.lookup_adt_def(enum_id);
(adt, adt.variant_with_id(variant_id))
}
Def::Struct(did) | Def::TyAlias(did) => {
let typ = self.tcx.lookup_item_type(did);
if let ty::TyStruct(adt, _) = typ.ty.sty {
(adt, adt.struct_variant())
} else {
return None;
}
}
_ => return None
};
if variant.kind == ty::VariantKind::Struct ||
variant.kind == ty::VariantKind::Unit {
Some((adt, variant))
} else {
None
}
} }
pub fn write_nil(&self, node_id: ast::NodeId) { pub fn write_nil(&self, node_id: ast::NodeId) {
@ -3151,34 +3121,54 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn check_struct_path(&self,
def: Def,
path: &hir::Path,
span: Span)
-> Option<ty::VariantDef<'tcx>> {
let variant = match def {
Def::Err => {
self.set_tainted_by_errors();
return None;
}
Def::Variant(..) | Def::Struct(..) => {
Some(self.tcx.expect_variant_def(def))
}
Def::TyAlias(did) | Def::AssociatedTy(_, did) => {
if let ty::TyStruct(adt, _) = self.tcx.lookup_item_type(did).ty.sty {
Some(adt.struct_variant())
} else {
None
}
}
_ => None
};
if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
// Reject tuple structs for now, braced and unit structs are allowed.
span_err!(self.tcx.sess, span, E0071,
"`{}` does not name a struct or a struct variant",
pprust::path_to_string(path));
return None;
}
variant
}
fn check_expr_struct(&self, fn check_expr_struct(&self,
expr: &hir::Expr, expr: &hir::Expr,
path: &hir::Path, path: &hir::Path,
fields: &'gcx [hir::Field], fields: &'gcx [hir::Field],
base_expr: &'gcx Option<P<hir::Expr>>) base_expr: &'gcx Option<P<hir::Expr>>)
{ {
let tcx = self.tcx;
// Find the relevant variant // Find the relevant variant
let def = tcx.expect_def(expr.id); let def = self.finish_resolving_struct_path(path, expr.id, expr.span);
if def == Def::Err { let variant = if let Some(variant) = self.check_struct_path(def, path, expr.span) {
self.set_tainted_by_errors(); variant
} else {
self.check_struct_fields_on_error(expr.id, fields, base_expr); self.check_struct_fields_on_error(expr.id, fields, base_expr);
return; return;
}
let variant = match self.def_struct_variant(def, path.span) {
Some((_, variant)) => variant,
None => {
span_err!(self.tcx.sess, path.span, E0071,
"`{}` does not name a structure",
pprust::path_to_string(path));
self.check_struct_fields_on_error(expr.id, fields, base_expr);
return;
}
}; };
let expr_ty = self.instantiate_type(def.def_id(), path); let expr_ty = self.instantiate_type_path(def.def_id(), path, expr.id);
self.write_ty(expr.id, expr_ty);
self.check_expr_struct_fields(expr_ty, path.span, variant, fields, self.check_expr_struct_fields(expr_ty, path.span, variant, fields,
base_expr.is_none()); base_expr.is_none());
@ -3190,13 +3180,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expr.id, expr.id,
adt.struct_variant().fields.iter().map(|f| { adt.struct_variant().fields.iter().map(|f| {
self.normalize_associated_types_in( self.normalize_associated_types_in(
expr.span, &f.ty(tcx, substs) expr.span, &f.ty(self.tcx, substs)
) )
}).collect() }).collect()
); );
} }
_ => { _ => {
span_err!(tcx.sess, base_expr.span, E0436, span_err!(self.tcx.sess, base_expr.span, E0436,
"functional record update syntax requires a struct"); "functional record update syntax requires a struct");
} }
} }
@ -3349,12 +3339,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
hir::ExprPath(ref opt_qself, ref path) => { hir::ExprPath(ref opt_qself, ref path) => {
let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty)); let opt_self_ty = opt_qself.as_ref().map(|qself| self.to_ty(&qself.ty));
let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(tcx.expect_resolution(id), let (def, opt_ty, segments) = self.resolve_ty_and_def_ufcs(opt_self_ty, path,
opt_self_ty, path, expr.span, expr.id); expr.id, expr.span);
if def != Def::Err { if def != Def::Err {
let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span, let (scheme, predicates) = self.type_scheme_and_predicates_for_def(expr.span,
def); def);
self.instantiate_path(segments, scheme, &predicates, opt_ty, def, expr.span, id); self.instantiate_value_path(segments, scheme, &predicates,
opt_ty, def, expr.span, id);
} else { } else {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
self.write_error(id); self.write_error(id);
@ -3695,18 +3686,45 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
expected); expected);
} }
// Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
// The newly resolved definition is written into `def_map`.
pub fn finish_resolving_struct_path(&self,
path: &hir::Path,
node_id: ast::NodeId,
span: Span)
-> Def
{
let path_res = self.tcx().expect_resolution(node_id);
if path_res.depth == 0 {
// If fully resolved already, we don't have to do anything.
path_res.base_def
} else {
let base_ty_end = path.segments.len() - path_res.depth;
let (_ty, def) = AstConv::finish_resolving_def_to_ty(self, self, span,
PathParamMode::Optional,
path_res.base_def,
None,
node_id,
&path.segments[..base_ty_end],
&path.segments[base_ty_end..]);
// Write back the new resolution.
self.tcx().def_map.borrow_mut().insert(node_id, PathResolution::new(def));
def
}
}
// Resolve associated value path into a base type and associated constant or method definition. // Resolve associated value path into a base type and associated constant or method definition.
// The newly resolved definition is written into `def_map`. // The newly resolved definition is written into `def_map`.
pub fn resolve_ty_and_def_ufcs<'b>(&self, pub fn resolve_ty_and_def_ufcs<'b>(&self,
path_res: PathResolution,
opt_self_ty: Option<Ty<'tcx>>, opt_self_ty: Option<Ty<'tcx>>,
path: &'b hir::Path, path: &'b hir::Path,
span: Span, node_id: ast::NodeId,
node_id: ast::NodeId) span: Span)
-> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment]) -> (Def, Option<Ty<'tcx>>, &'b [hir::PathSegment])
{ {
// If fully resolved already, we don't have to do anything. let path_res = self.tcx().expect_resolution(node_id);
if path_res.depth == 0 { if path_res.depth == 0 {
// If fully resolved already, we don't have to do anything.
(path_res.base_def, opt_self_ty, &path.segments) (path_res.base_def, opt_self_ty, &path.segments)
} else { } else {
// Try to resolve everything except for the last segment as a type. // Try to resolve everything except for the last segment as a type.
@ -3975,15 +3993,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Instantiates the given path, which must refer to an item with the given // Instantiates the given path, which must refer to an item with the given
// number of type parameters and type. // number of type parameters and type.
pub fn instantiate_path(&self, pub fn instantiate_value_path(&self,
segments: &[hir::PathSegment], segments: &[hir::PathSegment],
type_scheme: TypeScheme<'tcx>, type_scheme: TypeScheme<'tcx>,
type_predicates: &ty::GenericPredicates<'tcx>, type_predicates: &ty::GenericPredicates<'tcx>,
opt_self_ty: Option<Ty<'tcx>>, opt_self_ty: Option<Ty<'tcx>>,
def: Def, def: Def,
span: Span, span: Span,
node_id: ast::NodeId) { node_id: ast::NodeId)
debug!("instantiate_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})", -> Ty<'tcx> {
debug!("instantiate_value_path(path={:?}, def={:?}, node_id={}, type_scheme={:?})",
segments, segments,
def, def,
node_id, node_id,
@ -4012,7 +4031,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// actually pass through this function, but rather the // actually pass through this function, but rather the
// `ast_ty_to_ty` function in `astconv`. However, in the case // `ast_ty_to_ty` function in `astconv`. However, in the case
// of struct patterns (and maybe literals) we do invoke // of struct patterns (and maybe literals) we do invoke
// `instantiate_path` to get the general type of an instance of // `instantiate_value_path` to get the general type of an instance of
// a struct. (In these cases, there are actually no type // a struct. (In these cases, there are actually no type
// parameters permitted at present, but perhaps we will allow // parameters permitted at present, but perhaps we will allow
// them in the future.) // them in the future.)
@ -4235,20 +4254,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
Err(_) => { Err(_) => {
span_bug!(span, span_bug!(span,
"instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?", "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
self_ty, self_ty,
impl_ty); impl_ty);
} }
} }
} }
debug!("instantiate_path: type of {:?} is {:?}", debug!("instantiate_value_path: type of {:?} is {:?}",
node_id, node_id,
ty_substituted); ty_substituted);
self.write_ty(node_id, ty_substituted); self.write_ty(node_id, ty_substituted);
self.write_substs(node_id, ty::ItemSubsts { self.write_substs(node_id, ty::ItemSubsts {
substs: substs substs: substs
}); });
ty_substituted
} }
/// Finds the parameters that the user provided and adds them to `substs`. If too many /// Finds the parameters that the user provided and adds them to `substs`. If too many

View File

@ -1895,33 +1895,6 @@ fn my_start(argc: isize, argv: *const *const u8) -> isize {
``` ```
"##, "##,
E0163: r##"
This error means that an attempt was made to match an enum variant as a
struct type when the variant isn't a struct type:
```compile_fail
enum Foo { B(u32) }
fn bar(foo: Foo) -> u32 {
match foo {
B{i} => i, // error E0163
}
}
```
Try using `()` instead:
```
enum Foo { B(u32) }
fn bar(foo: Foo) -> u32 {
match foo {
Foo::B(i) => i,
}
}
```
"##,
E0164: r##" E0164: r##"
This error means that an attempt was made to match a struct type enum This error means that an attempt was made to match a struct type enum
variant as a non-struct type: variant as a non-struct type:
@ -4070,6 +4043,7 @@ register_diagnostics! {
// E0129, // E0129,
// E0141, // E0141,
// E0159, // use of trait `{}` as struct constructor // E0159, // use of trait `{}` as struct constructor
// E0163, // merged into E0071
E0167, E0167,
// E0168, // E0168,
// E0173, // manual implementations of unboxed closure traits are experimental // E0173, // manual implementations of unboxed closure traits are experimental

View File

@ -1,20 +0,0 @@
// Copyright 2016 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.
enum Foo { B(u32) }
fn bar(foo: Foo) -> u32 {
match foo {
Foo::B { i } => i, //~ ERROR E0163
}
}
fn main() {
}

View File

@ -16,7 +16,7 @@ pub struct GslResult {
impl GslResult { impl GslResult {
pub fn new() -> GslResult { pub fn new() -> GslResult {
Result { //~ ERROR: `Result` does not name a structure Result { //~ ERROR: `Result` does not name a struct or a struct variant
val: 0f64, val: 0f64,
err: 0f64 err: 0f64
} }

View File

@ -11,5 +11,5 @@
mod foo {} mod foo {}
fn main() { fn main() {
let p = foo { x: () }; //~ ERROR `foo` does not name a structure let p = foo { x: () }; //~ ERROR `foo` does not name a struct or a struct variant
} }

View File

@ -15,6 +15,5 @@ enum Foo {
fn main() { fn main() {
match Foo::Bar(1) { match Foo::Bar(1) {
Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo` Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo`
//~^ ERROR `Foo` does not name a struct or a struct variant
} }
} }

View File

@ -11,5 +11,5 @@
mod MyMod {} mod MyMod {}
fn main() { fn main() {
let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a structure let myVar = MyMod { T: 0 }; //~ ERROR `MyMod` does not name a struct or a struct variant
} }

View File

@ -12,6 +12,5 @@ fn main() {
match 'a' { match 'a' {
char{ch} => true char{ch} => true
//~^ ERROR expected variant, struct or type alias, found builtin type `char` //~^ ERROR expected variant, struct or type alias, found builtin type `char`
//~| ERROR `char` does not name a struct or a struct variant
}; };
} }

View File

@ -11,12 +11,10 @@
mod A {} mod A {}
fn main() { fn main() {
let u = A { x: 1 }; //~ ERROR `A` does not name a structure let u = A { x: 1 }; //~ ERROR `A` does not name a struct or a struct variant
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure let v = u32 { x: 1 }; //~ ERROR `u32` does not name a struct or a struct variant
match () { match () {
A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A` A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
//~^ ERROR `A` does not name a struct or a struct variant
u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32 u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32
//~^ ERROR `u32` does not name a struct or a struct variant
} }
} }

View File

@ -18,7 +18,7 @@ enum Enum {
fn main() { fn main() {
let x = Foo(1); let x = Foo(1);
Foo { ..x }; //~ ERROR `Foo` does not name a structure Foo { ..x }; //~ ERROR `Foo` does not name a struct or a struct variant
let Foo { .. } = x; //~ ERROR `Foo` does not name a struct let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
let x = Bar; let x = Bar;

View File

@ -11,5 +11,5 @@
struct NonCopyable(()); struct NonCopyable(());
fn main() { fn main() {
let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a structure let z = NonCopyable{ p: () }; //~ ERROR `NonCopyable` does not name a struct or a struct variant
} }

View File

@ -10,7 +10,7 @@
struct T { i: i32 } struct T { i: i32 }
fn f<T>() { fn f<T>() {
let t = T { i: 0 }; //~ ERROR `T` does not name a structure let t = T { i: 0 }; //~ ERROR `T` does not name a struct or a struct variant
} }
mod Foo { mod Foo {

View File

@ -12,5 +12,5 @@ trait TraitNotAStruct {}
fn main() { fn main() {
TraitNotAStruct{ value: 0 }; TraitNotAStruct{ value: 0 };
//~^ ERROR: `TraitNotAStruct` does not name a structure [E0071] //~^ ERROR: `TraitNotAStruct` does not name a struct or a struct variant [E0071]
} }